日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

python 的类装饰器

發布時間:2024/8/26 python 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python 的类装饰器 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

我們都知道python的函數有裝飾器,那么類也有裝飾器嗎?有的,為什么沒有呢,來看下代碼吧

def out(args):def inner(cls):cls._args = argsreturn clsreturn innerclass Student:passprint(Student.__dict__) Student.name = "ALICE" print(Student.__dict__) ###來看下執行結果### {'__module__': '__main__', '__dict__': <attribute '__dict__' of 'Student' objects>, '__weakref__': <attribute '__weakref__' of 'Student' objects>, '__doc__': None} {'__module__': '__main__', '__dict__': <attribute '__dict__' of 'Student' objects>, '__weakref__': <attribute '__weakref__' of 'Student' objects>, '__doc__': None, 'name': 'ALICE'}

我們定義了一個空類Student,里面沒有任何屬性,第一次打印類的dict屬性時候大家看到是沒有任何屬性的,只有類的特殊屬性

然后我們增加了一個name屬性,然后再打印一次dict屬性,就看到有一個常規的name屬性,屬性值是ALICE

然后看最上面的函數,這個函數是個裝飾函數,out函數接收常規str參數,當然不限制類型,你也可以傳入int參數等等。

Inner函數的參數值是cls,也就是一個類,我們把類當做一個參數傳進去,既然函數裝飾器都可以把函數當做 參數傳進去,類也可以當做參數傳進去,在python里萬物皆對象,只要是對象就是可以被傳入的

cls._args = args 這里就是給這個類增加一個新屬性,新屬性是_args 并且值是形參args的實參值

然后最重要的來了,必須要有??return cls 不然的話下面的類的調用就要出問題了,一會我們測試下,因為給類增加新的屬性后,一定要返回類,具體為什么,我們一會測試下就明白了

最后我們使用裝飾器的@方式來裝飾類,我們來看下代碼與執行結果

def out(args):def inner(cls):cls._args = argsreturn clsreturn inner @out("TOM") ##=>>這里必須要帶上args的實參 class Student:passprint(Student.__dict__) Student.name = "ALICE" print(Student.__dict__) ####執行結果如下##### {'__module__': '__main__', '__dict__': <attribute '__dict__' of 'Student' objects>, '__weakref__': <attribute '__weakref__' of 'Student' objects>, '__doc__': None, '_args': 'TOM'} {'__module__': '__main__', '__dict__': <attribute '__dict__' of 'Student' objects>, '__weakref__': <attribute '__weakref__' of 'Student' objects>, '__doc__': None, '_args': 'TOM', 'name': 'ALICE'}

我們可以看到,新增了_args屬性,并且屬性值是TOM。

我們來看下是否是在python內部新建了一個類?

def out(args):def inner(cls):cls._args = argsprint("The new class id is {}".format(id(cls)))return clsreturn inner @out("TOM") class Student:passprint("The old class id is {}".format(id(Student))) foo = out("TOM") foo(Student)###我們返回每個類的ID##### The new class id is 32509208 The old class id is 32509208 The new class id is 32509208

ID值完全相同,看來在內部并沒有創建一個新類,只是裝飾器給其增加了一個屬性

我們來測試下,在裝飾器函數內部如果不返回類也就是cls呢?

def out(args):def inner(cls):cls._args = argsprint("The new class id is {}".format(id(cls)))#return clsreturn inner @out("TOM") class Student:pass#print("The old class id is {}".format(id(Student))) #foo = out("TOM") #foo(Student) print(Student.__dict__) ###看下執行結果#### Traceback (most recent call last): The new class id is 7146776File "E:/python_learn/test1.py", line 15, in <module>print(Student.__dict__) AttributeError: 'NoneType' object has no attribute '__dict__'

為什么會是NoneType呢?因為在inner函數里沒有返回值,所以是空類型,所以不能調用類的任何屬性

看下面代碼就明白了

def out(args):def inner(cls):cls._args = argsprint("The new class id is {}".format(id(cls)))return clsreturn inner #@out("TOM") class Student:passfoo = out("TOM") print(id(foo(Student))) print(foo(Student).__dict__) ###看下結果### The new class id is 32967960 32967960 The new class id is 32967960 {'__module__': '__main__', '__dict__': <attribute '__dict__' of 'Student' objects>, '__weakref__': <attribute '__weakref__' of 'Student' objects>, '__doc__': None, '_args': 'TOM'}

我們注釋掉了@調用

直接以賦值的方式來調用

首先定義foo = out("TOM") ,此時foo的值是inner函數

print(foo(Student)) 這時是打印inner函數的返回值,如果inner函數沒有return的話,那么inner函數的返回值就是None,還記得嗎?如果函數不寫return那么默認返回就是空None,這也就是為什么上面代碼會報NoneType error 了。

在inner函數里,我們把Student類以參數方式傳入,再用return返回Student類也就是形參cls,如果不返回的話,下面裝飾調用就無法調用到了,調用過程和裝飾器一樣,所以必須有return cls

def out(args):def inner(cls):cls._args = argsprint("The new class id is {}".format(id(cls)))#return clsreturn inner #@out("TOM") class Student:passfoo = out("TOM") print(id(foo(Student))) print(foo(Student).__dict__)###注釋掉return,一樣的報錯### The new class id is 32247064 1577322688 The new class id is 32247064 Traceback (most recent call last):File "E:/python_learn/test1.py", line 13, in <module>print(foo(Student).__dict__) AttributeError: 'NoneType' object has no attribute '__dict__'

然后下面的調用方式是不會出錯的

def out(args):def inner(cls):cls._args = argsprint("The new class id is {}".format(id(cls)))#return clsreturn inner #@out("TOM") class Student:passfoo = out("TOM") print(id(foo(Student))) print(foo(Student)) #####來看下結果######## The new class id is 37621016 1577322688 The new class id is 37621016 None

看到了有個None了嗎?那是inner函數的默認返回值,這樣調用是不會出錯的,因為你沒調用特殊屬性啊,比如__dict__屬性,空類型一調用肯定出錯啊,所以這里不調用就沒事了

return cls 的作用是,你傳入的cls參數是什么類型,它給你返回的也是什么類型,只不過你傳入的參數類型是個類,返回的是個增加了一個新屬性的類而已

可以測試下

def out(args):def inner(cls):cls._args = argsprint("The new class id is {}".format(id(cls)))print(type(cls))return clsreturn inner #@out("TOM") class Student:passfoo = out("TOM") print(id(foo(Student))) print(foo(Student)) ####看下執行結果### The new class id is 37883160 <class 'type'> 37883160 The new class id is 37883160 <class 'type'> <class '__main__.Student'> ###看到了吧,類型為class### def out(args):def inner(cls):#cls._args = argsprint("The new class id is {}".format(id(cls)))print(type(cls))return clsreturn inner #@out("TOM") class Student:passfoo = out("TOM") print(id(foo("tools"))) #####傳入的是str那么返回的也是str### The new class id is 32593504 <class 'str'> 32593504

?

總的來說,多實踐出真知,才能明白其中的道理

在函數裝飾器里,如果不返回任何值是不會報錯的

def out(fn):def inner(args):print("這個是個裝飾器,是用來裝飾其他函數用的")ret = fn(args)print("******************")#return retreturn inner#@out def test(name):print("這個是fn函數,是被裝飾的")return name #print(test("Bob")) foo = out(test) print(foo("JOke")) ####來看下結果#### 這個是個裝飾器,是用來裝飾其他函數用的 這個是fn函數,是被裝飾的 ****************** None

下面也一樣

def out(fn):def inner(args):print("這個是個裝飾器,是用來裝飾其他函數用的")ret = fn(args)print("******************")#return retreturn inner@out def test(name):print("這個是fn函數,是被裝飾的")return name print(test("SBB")) ############### 這個是個裝飾器,是用來裝飾其他函數用的 這個是fn函數,是被裝飾的 ****************** None

具體為什么,很簡單,打印的是inner函數,只要inner函數是正確的,有沒有返回值是無所謂的。

轉載于:https://www.cnblogs.com/hh2737/p/9202759.html

總結

以上是生活随笔為你收集整理的python 的类装饰器的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。