1. 程式人生 > >Python記錄9:函式4:名稱空間作用域+閉包函式+裝飾器

Python記錄9:函式4:名稱空間作用域+閉包函式+裝飾器

'''
一: 名稱空間namespaces
    名稱空間就是存放名字與值繫結關係的記憶體空間

二: 名稱空間分為三種
    內建名稱空間:
        1. 特點: 存放是python直譯器自帶的名字,len,print
        2. 生命週期: 直譯器啟動則產生,直譯器關閉則銷燬
    全域性名稱空間
        1. 特點: 存放是全域性的名字(沒有任何縮排\頂頭定義的名字)
        x=10
        y=20
        def func():
            pass
        print(x)

        if True:
            x=1111
        2. 生命週期: python檔案執行時則建立,檔案執行完畢則銷燬
    區域性名稱空間:
        1. 特點: 在函式內定義的名字
        2. 生命週期: 在函式呼叫時臨時建立,函式呼叫完畢則立即銷燬

三 名稱空間總結:
    1. 載入順序:
        先產生內建名稱空間
        再產生全域性名稱空間
        如果呼叫函式則會臨時區域性名稱空間

    2. 名字的查詢順序:
        從當前位置向上查詢
        def func():
        #     # len=2222
        #     print(len)
        # len=1111
        # func()
    3. 函式的區域性名稱空間彼此隔離,但是全域性名稱空間與內建名稱空間是所有函式共享的
    4. 名稱空間的巢狀關係是在函式定義(檢測語法)就固定死的與呼叫位置無關,即無論在
       何處呼叫函式都必須老老實實地按照定義階段規定的巢狀關係去查詢名字
'''
#示範一
# mmm=11111111111111
# # x='aaaa'
# def f1():
#     x=1
#     def f2():
#         # x=2
#         def f3():
#             # x=3
#             print(x)
#         f3()
#     f2()
#
#
# f1()
#
# def foo():
#     xxx=1111
#     print(mmm)
#     print(len)
#
# def bar():
#     yyy=2222
#     print(mmm)
#     print(len)
#
#
# foo()
# bar()


#示範二
# def f1():
#     # x=1111
#     def f2():
#         # x=333333333333333333333
#         print('from f2',x)
#     return f2
#
# xxx=f1()
# x='全域性'
#
# def foo():
#     x='foo'
#     xxx()
#
# def bar():
#     x='bar'
#     xxx()
#
# def func():
#     x='func'
#     xxx()
#
#
# foo()
# bar()
# func()


#示範三
# yyy=111
# def func():
#     print(yyy)
#     xxx=2222
#
# func()


'''
全域性作用域:內建名稱空間+全域性名稱空間
    特點:全域性存活,全域性有效
   
區域性作用域:區域性名稱空間
    特點:臨時存活,函式內有效

'''
# 關鍵字: global
# 如果想要在區域性修改全域性名字對應的值是不可變型別時.必須在區域性用global關鍵字加以宣告
# x=111
# def func():
#     global x
#     x=222
#
# func()
# print(x)

#如果想要在區域性修改全域性名字對應的值是可變型別時,直接修改即可
# l=[1,2,3]
# def func():
#     l.append(4)
#
# func()
# print(l)

# nonlocal
# x=2222
# def f1():
#     x=1111
#     def f2():
#         # global x
#         nonlocal x
#         x=0
#     f2()
#     print('在f1內的x的值===>',x)
#
# f1()
# print(x)


aaaaaa=1111111111111
# print(globals())

def func():
    x=1
    y=2
    print(locals())

func()
'''
1.
什麼是閉包函式=>函式巢狀+函式物件+名稱空間與作用域
    閉:定義在函式內的函式
    包:該內部函式需要訪問一個名字,該名字屬於外層函式作用域的(強調:不是全域性作用域)
2. 為何要用閉包函式
    為了實現裝飾器
3. 如何用閉包函式
    def outter(xxx):
        def inner():
            xxx
        return inner
'''
# def outter():
#     xxx=111
#     def inner():
#         print(xxx)
#     return inner
#
# f=outter()
# def foo():
#     xxx=2222
#     f()
# foo()

# 為函式體傳參的兩種解決方案
# 方案一: 直接以引數的形式傳入
# def func(xxx):
#     print(xxx)
# func(111)

#方案二:
def outter(xxx):
    # xxx=111
    def func():
        print(xxx)
    return func

func=outter(111)

'''
1.
什麼是裝飾器
    裝飾器就是用來為被裝飾的物件新增功能的工具/函式
    被裝飾的物件可以是任意可呼叫的物件
    裝飾器本事也可以是任意可呼叫的物件

2. 為何要用裝飾器
    開放封閉原則:對修改封閉,對擴充套件開放
    也就是不可以修改原始碼,而對原有的功能進行擴充套件
    裝飾器需要遵循的原則:
        1. 不能修改被裝飾物件的原始碼
        2. 不能修改被裝飾物件的呼叫方式

    裝飾器的目標:就是要在遵循原則1和2的前提下,為被裝飾物件新增功能

3. 如何實現裝飾器

'''
# # 階段一:
###計算出一段程式執行的時間並打印出來
# import time
# def index():
#     time.sleep(1)
#     print('welcome to index page')
#
# start=time.time()
# index()
# stop=time.time()
# print('run time is %s' %(stop - start))

# # 階段二:
# import time
# def index():
#     time.sleep(1)
#     print('welcome to index page')
#
# def wrapper():
#     start=time.time()
#     index()
#     stop=time.time()
#     print('run time is %s' %(stop - start))

# wrapper()


# # 階段三:
# import time
#
# def index():
#     time.sleep(1)
#     print('welcome to index page')
#
# def wrapper(func):
#     start=time.time()
#     func()
#     stop=time.time()
#     print('run time is %s' %(stop - start))
#
# wrapper(index)

# 階段四:
# import time
#
# def index():
#     time.sleep(1)
#     print('welcome to index page')
#
# def timmer(func):
#     # func=最原始那個index的記憶體地址
#     def wrapper():
#         start=time.time()
#         func()
#         stop=time.time()
#         print('run time is %s' %(stop - start))
#     return wrapper
#
# index=timmer(index) #index=wrapper的記憶體地址
# index() #wrapper()

#############################################################################################################
# 裝飾器語法糖
# 在被裝飾器物件正上方單獨一行寫: @裝飾器的名字
# 直譯器一旦執行到@裝飾器的名字就會: 原函式名=裝飾器的名字(正下方那個函式)

# import time
#
# def timmer(func):
#     # func=最原始那個index的記憶體地址
#     def wrapper():
#         start=time.time()
#         func()
#         stop=time.time()
#         print('run time is %s' %(stop - start))
#     return wrapper
#
# @timmer #index=timmer(index) #index=wrapper的記憶體地址
# def index():
#     time.sleep(1)
#     print('welcome to index page')
#
# index() #wrapper()


# 裝飾器修訂:
# import time
#
# def timmer(func):
#     # func=最原始那個index的記憶體地址
#     def wrapper(*args,**kwargs):
#         start=time.time()
#         res=func(*args,**kwargs)
#         stop=time.time()
#         print('run time is %s' %(stop - start))
#         return res
#     return wrapper
#
# @timmer #index=timmer(最原始那個index的記憶體地址) #index=wrapper的記憶體地址
# def index():
#     time.sleep(1)
#     print('welcome to index page')
#
#
# @timmer # home=timmer(最原始那個home的記憶體地址) #home=wrapper的記憶體地址
# def home(name):
#     time.sleep(2)
#     print('welcome %s to home page' %name)
#     return 11111
#
# res=index() #wrapper()
# print('index====>',res)
# res=home('egon') #wrapper('egon')
# print('home====>',res)