類也是對象
在大多數編程語言中,類就是一組用來描述如何生成一個對象的代碼段,在python中也是成立的。
class ObjectCreator: pass my_object = ObjectCreator() print(my_object) """ 輸出結果: <__main__.ObjectCreator object at 0x037DACD0> """
但是,python的類不止于此,類同樣也是一種對象。
class ObjectCreator: pass
上面的代碼段將在內存中創建一個對象,名字就叫做ObjectCreator。這個對象(類對象ObjectCreator)擁有創建對象(實例對象)的能力,但它本質上仍然還是一個對象,于是你就可以對它做如下的操作:
- 給它復制一個變量
- 拷貝它
- 給它增加屬性
- 將它作為函數參數傳遞
示例代碼:
class ObjectCreator: pass # 把它賦值給一個變量 a = ObjectCreator print(a) ## 作為函數參數傳遞 def echo(o): print(o) echo(ObjectCreator) #
動態的創建類
因為類也是對象,所以可以在運行時動態的創建它們,使用class關鍵字即可。
def choose_class(name): if name == 'foo': class Foo(object): pass return Foo # 返回的是類,不是類的實例 else: class Bar(object): pass return Bar MyClass = choose_class("foo") print(MyClass) # 打印類對象 # 輸出結果.Foo'> print(MyClass()) # 打印實例對象 # 輸出結果 <__main__.choose_class. .Foo object at 0x0368CFD0>
使用type創建類
我們知道通過type()可以知道這個對象的類型是什么,他還有一個完全不同的功能,動態的創建類。
type可以接受一個類的描述作為參數,然后返回一個類。
語法:
type(類名,由父類名稱構成的元組(針對繼承的情況可以為空),包含屬性的字典)
MyClass = type("MyClass",(),{}) print(MyClass) # 輸出結果:
使用type創建帶屬性的類
type 接受一個字典來為類定義屬性,如下所示:
Foo = type("Foo",(),{'bar':True})
等價于
class Foo: bar = True
使用type創建繼承的子類
接著上面的代碼,我們已經創建了一個Foo類,現在來創建一個它的子類。
FooChild = type("FooChild",(Foo,),{}) print(FooChild.bar) # # bar屬性是由Foo繼承而來 # 輸出結果: True
注意:
- type的第二個參數,元組中是父類的名字,不是字符串。
- 添加的屬性是類屬性,不是實例屬性。
使用type創建帶有方法的類
最終你會希望為你的類增加方法。只需要定義一個有著恰當簽名的函數并將其作為屬性賦值就可以了。
添加實例方法
def test_f(self): print("添加的實例方法") Foo = type("Foo",(),{"test_f":test_f}) f = Foo() f.test_f() # 輸出結果: 添加的實例方法
添加靜態方法
@staticmethod def test_static(): print("添加的靜態方法") Foo = type("Foo",(),{"test_static":test_static}) Foo.test_static() Foo.test_static() # 輸出結果: 添加的靜態方法
添加類方法
@classmethod def test_class(cls): print("添加的類方法") Foo = type("Foo",(),{"test_class":test_class}) Foo.test_class() # 輸出的結果: 添加的類方法
什么是元類
元類就是用來創建類的“東西”。元類就是就是用來創建類對象的,元類就是類的類。
可以這樣理解:
MyClass = MetaClass() # 使用元類創建類對象 MyObject = MyClass() # 使用類對象創建實例對象
type函數其實就是元類。type就是在Python在背后創建所有類的元類,可以通過__class __屬性來查看,__class __的功能是查看對象所在的類,它可以嵌套使用。
class A: pass print(A.__class__) a = A() print(a.__class__) print(a.__class__.__class__) # 輸出結果:
可以看出,最后對象的類都是type元類。
Python中所有的東西,注意,我是指所有的東西――都是對象。這包括整數、字符串、函數以及類。它們全部都是對象,而且它們都是從一個類創建而來,這個類就是type。
整數:
age = 18 print(age.__class__) print(age.__class__.__class__) # 輸出結果:
字符串:
name = "張三" print(name .__class__) print(name .__class__.__class__) # 輸出結果:
函數:
def f(): pass print(f.__class__) print(f.__class__.__class__) # 輸出結果:
自定義元類
首先的了解一下metaclass屬性,用它來指定一個元類,python會在定義的類中尋找metaclass屬性,如果沒找到,就到它的父類找以此類推。如果找到了,python就會用它來創建類對象,如果實在沒有找到就會用內建的type來創建這個類。
metaclass中可以放type或者任何使用到type或者子類化type的東東都可以。
自定義類的主要目的:
- 攔截類的創建
- 修改類
使用函數實現一個自定義的元類
功能:把不是__開頭的類屬性名字變為大寫
def upper_attr(future_class_name: str,future_class_parents: tuple,future_class_attr: dict): newAttr = {} for key,value in future_class_attr.items(): if not key.startswith("__"): newAttr[key.upper()] = value return type(future_class_name,future_class_parents,newAttr) class Foo(metaclass=upper_attr): name = "張三" age = 18 hasattr(Foo,"name") # 判斷是否有該類屬性 False hasattr(Foo,"NAME") # True hasattr(Foo,"age") # False hasattr(Foo,"AGE") # True
繼承type實現一個自定義元類
功能:同上
class MyMetaClass(type): def __new__(cls, class_name: str, class_parents: tuple, class_attr: dict): newAttr = {} for key, value in class_attr.items(): if not key.startswith("__"): newAttr[key.upper()] = value # 方法1:通過'type'來做類對象的創建 # return type(class_name, class_parents, newAttr) # 方法2:復用type.__new__方法 # 這就是基本的OOP編程,沒什么魔法 # return type.__new__(cls, class_name, class_parents, newAttr) # 方法3:使用super方法 return super(MyMetaClass, cls).__new__(cls, class_name, class_parents, newAttr) class Foo(metaclass=MyMetaClass): name = "張三" age = 18 hasattr(Foo,"name") # 判斷是否有該類屬性 False hasattr(Foo,"NAME") # True hasattr(Foo,"age") # False hasattr(Foo,"AGE") # True
效果和上面是一樣的。
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
