1. 程式人生 > >生活不止眼前的苟且

生活不止眼前的苟且

裝飾器

函式裡面定義函式 (函式裡面可以定義類)

def foo():
    def bar():     #3
        print('in bar()')    #4

    print('in foo()')    #1
    bar()     #2
foo()

#結果
in foo()
in bar()

為什麼要在函式裡面定義函式呢?有啥特別之處? 函式裡面函式的有效範圍是在foo()函式裡面的, 其實定義在裡面的函式,在外面還是有辦法訪問的,可以吧函式變數弄到外面去,通過返回值

def foo():
    def bar():
        print('in bar()')

    print('in foo()')
    return bar    #這裡的bar對應的是bar()這個函式的變數,是沒有括號的

#foo()()   #也可以把下面兩行註釋掉,直接foo()(),因為foo()返回的是bar,
inner = foo()    #foo的返回值賦值給一個變數,inner對應的是一個函式物件
inner()     #inner()和bar(),是同一樣的函式

裝飾器

定義類的靜態方法時,就使用了裝飾器 @staticmethod #靜態方法不需要self,例項方法要self。因為他不需要訪問不同的例項的屬性。 #靜態方法不能訪問例項屬性,但是可以訪問靜態屬性

def jump():    
    print("3 meters high")

裝飾器的特點是用一個@開頭的字串 在我們閱讀別人的程式碼時,會經常碰到裝飾器 裝飾器通常用來裝飾函式 裝飾器主要用來給函式增加一點功能 一般裝飾器本身也是一個函式 我們可以想象成它包含了被裝飾的函式

例子:

def hello():
    return "hello"

def hi():
    return "hi"

*我們需要返回值多兩個感嘆號

def endsign(func):
    def wrapper():
        return func() + "!!"
    return wrapper

@endsign        #裝飾器,裝飾hello的,裝飾器本身是一個函式,或是類的方法。@endsign等價於執行了hello = endsign(hello)這行程式碼。
def hello():
    return "hello"
#hello = endsign(hello)    #等號的右邊,賦值給左邊,hello是endsign()函式的返回值
print(hello())

#上面的等價於這個

def endsign(func):    #5
    def wrapper():      #6
        return func()  + ' !!'    #7          一個函式裡包含了外部物件,叫閉包
    return wrapper      #hello   hello對應的是hello()這個函式的變數
@endsign    #寫他的效果和註釋的哪行效果一樣的
def hello():       #2
    return 'hello'     #3

#hello = endsign(hello)       #4   endsign(hello)的返回值賦給變數

print(hello())   #1

#結果
hello!!

用裝飾器一般開發的是庫 有時候要裝飾的函式還沒有寫呢

有引數的的函式 有引數的的函式 要裝飾的函式的引數還不一樣???該怎麼辦? 可以用可變引數的方法

def endsign(func):
    def wrapper(*args,**kargs):   #可變引數*args時元組,關鍵字可變引數**kargs是字典
        print('args:',args)
        print('kargs:',kargs)
        return func(*args,**kargs) + ' !!'    #func(*args,**kargs)這種方法,不管被裝飾的函式,原來是怎麼呼叫的,後來就怎麼傳給他
    return wrapper

@endsign    #被修飾了之後,呼叫hello,就是呼叫wrapper
def hello(arg1,arg2=''):
    print('arg1:',arg1)
    print('arg2:',arg2)
    return 'hello %s %s' % (arg1,arg2)
# hello = endsign(hello)

@endsign
def goodbye(targets):
    return 'goodbye %s ' % ' '.join(targets)


# print(hello('cat', 'dog'))
# print('=====================\n')
print(hello('cat', arg2='dog'))
# print('=====================\n')
print(goodbye(['jack', 'lisa', 'tom', 'mike']))

有引數的函式 裝飾器本身有引數 比如,hello後面,加!!或??等

def endsign(func):
    def wrapper(*args,**kargs):   #可變引數*args時元組,關鍵字可變引數**kargs是字典
        print('args:',args)
        print('kargs:',kargs)
        return func(*args,**kargs) + ' !!'    #func(*args,**kargs)這種方法,不管被裝飾的函式,原來是怎麼呼叫的,後來就怎麼傳給他
    return wrapper

@endsign    #被修飾了之後,呼叫hello,就是呼叫wrapper
def hello(arg1,arg2=''):
    print('arg1:',arg1)
    print('arg2:',arg2)
    return 'hello %s %s' % (arg1,arg2)
# hello = endsign(hello)

@endsign
def goodbye(targets):
    return 'goodbye %s ' % ' '.join(targets)


# print(hello('cat', 'dog'))
# print('=====================\n')
print(hello('cat', arg2='dog'))
# print('=====================\n')
print(goodbye(['jack', 'lisa', 'tom', 'mike']))