6.23 自我總結 1.描述符\_\_get\_\_,\_\_set\_\_,\_\_delete\_\_ 描述符是什麼:描述符本質就是一個新式類,在這個新式類中,至少實現了___\_get\_\_(),\_\_set\_\_(),\_\_delete\_\_()中的一個,這也被稱為描述符協議 __ ...
6.23 自我總結
1.描述符__get__,__set__,__delete__
描述符是什麼:描述符本質就是一個新式類,在這個新式類中,至少實現了____get__(),__set__(),__delete__()中的一個,這也被稱為描述符協議
- __get__():調用一個屬性時,觸發
- __set__():為一個屬性賦值時,觸發
- __delete__():採用del刪除屬性時,觸發
這三者來對於類的屬性生成一個類,然後對一個新類立面的特征進行調用方法
使用方法
class FooSet:
def __get__(self, instance, owner):
print('你調用了該方法')
def __set__(self, instance, value):
print('你修改了')
def __delete__(self, instance):
print('你刪除了')
class Foo:
name = FooSet()
foo = Foo()
#調用生成對象的屬性
print(foo.name)
#修改生成對象的屬性
foo.name = 123
#刪除生成對象的屬性
del foo.name
- 包含這三個方法的新式類稱為描述符,由這個類產生的實例進行屬性的調用/賦值/刪除,並不會觸發這三個方法
2.__init__,__new_,__call__
__new__方法的第一個參數是這個類,而其餘的參數會在調用成功後全部傳遞給
__init__方法初始化,這一下子就看出了誰是老子誰是小子的關係。
__call__方法,該方法會在調用對象主要是在定義元類的時候使用時自動觸發
class A:
pass
class B(A):
def __new__(cls): #如果沒寫這一步其實他在init時候預設會進行著一步先
print("__new__方法被執行")
return super().__new__(cls)
def __init__(self):
print("__init__方法被執行")
b = B()
'''
__new__方法被執行
__init__方法被執行
'''
我們比較兩個方法的參數,可以發現__new__方法是傳入類(cls),而__init__方法傳入類的實例化對象(self),而有意思的是,__new__方法返回的值就是一個實例化對象(ps:如果__new__方法返回None,則__init__方法不會被執行,並且返回值只能調用父類中的__new__方法,而不能調用毫無關係的類的__new__方法)。我們可以這麼理解它們之間的關係,__new__是開闢疆域的大將軍,而__init__是在這片疆域上辛勤勞作的小老百姓,只有__new__執行完後,開闢好疆域後,__init__才能工作。
絕大多數情況下,我們都不需要自己重寫__new__方法,但在當繼承一個不可變的類型(例如str類,int類等)時,它的特性就尤顯重要了。我們舉下麵這個例子:
class CapStr(str):
def __init__(self, string):
#他在這一步已經傳string進去了後面沒有意義了
string = string.upper()
a = CapStr("I love China!")
print(a)
#I love China!
class CapStr(str):
def __new__(cls, string):
string = string.upper()
return super().__new__(cls, string)
a = CapStr("I love China!")
print(a)
#I LOVE CHINA!
3.元類
1.元類的模板
元類定義 class 元類名(type)
class Mymeta(type):
def __init__(self, class_name, class_bases, class_dic):
# 加上邏輯,控制類Foo的創建
super(Mymeta, self).__init__(class_name, class_bases, class_dic)
def __call__(self, *args, **kwargs):
# 加上邏輯,控制Foo的調用過程,即Foo對象的產生過程
obj = self.__new__(self)
self.__init__(obj, *args, **kwargs)
# 修改屬性為隱藏屬性
obj.__dict__ = {
'_%s__%s' % (self.__name__, k): v
for k, v in obj.__dict__.items()
}
return obj
2.元類調用
class Foo(object, metaclass=Mymeta): # Foo = Mymeta(...)
def __init__(self, name, age, sex):
self.name = name
self.age = age
self.sex = sex
obj = Foo('nick', 18, 'male')