Python 變量做用域,閉包和裝飾器

from dis import dis


b = 6

def f1(a):
    print(a)print(b)
    b = 9

f1(3)


print(dis(f1))  # dis模塊能夠查看python函數字節碼

解決報錯的方案一:申明b全局變量python

from dis import dis


b = 6

def f1(a):
    print(a)
    global b
    print(b)
    b = 9

f1(3)


print(dis(f1))  # dis模塊能夠查看python函數字節碼

閉包

計算移動平均值閉包

 

class Averager:

    def __init__(self):
        self.series = []

    def __call__(self, new_value):
        self.series.append(new_value)
        total = sum(self.series)  # 彙總
        return total/len(self.series)  # 求平均值


avg = Averager()
print(avg(10))
print(avg(11))
print(avg(12))

經過高階函數實現app

def make_averager():
    series = []

    def averager(new_value):
        series.append(new_value)
        total = sum(series)
        return total/len(series)
    return averager


avg = make_averager()
print(avg(10))
print(avg(11))
print(avg(12))

print(avg.__code__.co_varnames)  # 打印局部變量
print(avg.__code__.co_freevars)  # 打印自由變量
print(avg.__closure__)  # series的綁定在返回的函數的__closure__屬性中
print(avg.__closure__[0].cell_contents)  # 這些元素是cell對象,有個cell_contents屬性,保存着真正的值

# 綜上,閉包是一種函數,它會保留定義函數時存在的自由變量的綁定,這樣調用函數時,雖然定義做用域不可用了,可是仍能使用那些綁定

# 注意,只有嵌套在其餘函數中的函數纔可能須要處理不在全局做用域中的外部變量

若是是賦值操做呢?函數

def make_averager():
    count = 0
    total = 0

    def averager(new_value):
        count += 1
        total +=new_value
        return total / count
    return averager
# 這裏直接執行會報錯,由於count += 1 至關於count = count + 1,所以當在averager的定義體內爲count賦值,會把count變成局部變量。total變量也是同理

解決方案this

# 引入nonlocal聲明,做用是把變量標記爲自由變量
def make_averager():
    count = 0
    total = 0

    def averager(new_value):
        nonlocal count, total
        count += 1
        total += new_value
        return total / count

    return averager

 

 

 

裝飾器代碼一spa

def deco(func):
    def inner(*args, **kwargs):
        print('this is inner')
    return inner


@deco
def foo():
    print('this is foo')


foo()  # this is inner
print(foo.__name__)  # inner

 

裝飾器代碼二code

def wrap(func):
    def deco(*args, **kwargs):
        print('deco ==> ', args, kwargs)
        func(*args, **kwargs)
        print('this is inner')
    return deco


@wrap
def foo(*args, **kwargs):
    print('this is foo')


foo()
# deco ==>  () {}
# this is foo
# this is inner

print(foo.__name__)  # deco

 

裝飾器代碼三對象

from functools import wraps


def wrap(func):
    @wraps(func)
    def deco(*args, **kwargs):
        print('deco ==> ', args, kwargs)
        func(*args, **kwargs)
        print('this is inner')
    return deco


@wrap
def foo(*args, **kwargs):
    print('this is foo')


foo()
# deco ==>  () {}
# this is foo
# this is inner

print(foo.__name__)  # foo

 

有空講解0.0blog

相關文章
相關標籤/搜索