標籤:pass ble ict 針對 操作 繼承 添加 對象 pre
前言
元類在python中是很重要的一部分,我將分兩次去講解元類及其應用,此篇為詳解元類及其應用第一篇,下面開始今天的說明~~~
1. 類也是對象
在?多數編程語?中,類就是?組?來描述如何?成?個對象的程式碼片段。在 Python中這?點仍然成?:
>>> class ObjectCreator(object): … pass … >>>my_object = ObjectCreator() >>>print(my_object)<__main__.ObjectCreator object at 0x8974f2c>
但是,Python中的類還遠不?如此。類同樣也是?種對象。是的,沒錯,就是對象。只要你使?關鍵字class,Python解譯器在執?的時候就會建立?個 對象。
下?的程式碼片段:
>>> class ObjectCreator(object):... pass...
將在記憶體中建立?個對象,名字就是ObjectCreator。這個對象(類對象 ObjectCreator)擁有建立對象(執行個體對象)的能?。但是,它的本質仍然是 ?個對象,於是乎你可以對它做如下的操作:
1.你可以將它賦值給?個變數
2.你可以拷?它
3.你可以為它增加屬性
4.你可以將它作為函數參數進?傳遞
下?是樣本:
>>> print(ObjectCreator)#你可以列印?個類,因為它其實也是?個對象 <class ‘__main__.ObjectCreator‘> >>> def echo(o):... print(o)... >>> echo(ObjectCreator)#你可以將類做為參數傳給函數 <class ‘__main__.ObjectCreator‘> >>> print(hasattr(ObjectCreator,‘new_attribute‘))False >>>ObjectCreator.new_attribute=‘foo‘#你可以為類增加屬性 >>>print(hasattr(ObjectCreator, ‘new_attribute‘))True >>>print(ObjectCreator.new_attribute)foo >>>ObjectCreatorMirror=ObjectCreator#你可以將類賦值給?個變數 >>>print(ObjectCreatorMirror())<__main__.ObjectCreator object at 0x8997b4c>
2. 動態地建立類
因為類也是對象,你可以在運?時動態建立它們,就像其他任何對象?樣。?先,你可以在函數中建立類,使?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)#函數返回的是類,不是類的執行個體<class ‘__main__.choose_class.<locals>.Foo‘>>>> print(MyClass())#你可以通過這個類建立類執行個體,也就是對象<__main__.choose_class.<locals>.Foo object at 0x000001C54F7007B8>
但這還不夠動態,因為你仍然需要??編寫整個類的代碼。由於類也是對 象,所以它們必須是通過什麼東?來?成的才對。當你使?class關鍵字時, Python解譯器?動建立這個對象。但就和Python中的?多數事情?樣, Python仍然提供給你?動處理的?法。
還記得內建函數type嗎?這個古?但強?的函數能夠讓你知道?個對象的類 型是什麼,就像這樣:
>>> print(type(1))#數值的類型<class ‘int‘>>>> print(type("1"))#字串的類型<class ‘str‘>>>> print(type(ObjectCreator()))#執行個體對象的類型<class ‘__main__.ObjectCreator‘> >>> print(type(ObjectCreator))#類的類型 <type ‘type‘>
仔細觀察上?的運?結果,發現使?type對ObjectCreator查看類型是,答案 為type, 是不是有些驚訝。。。看下?
3. 使?type建立類
type還有?種完全不同的功能,動態建立類。
type可以接受?個類的描述作為參數,然後返回?個類。(要知道,根據傳入參數的不同,同?個函數擁有兩種完全不同的?法是?件很傻的事情,但 這在Python中是為了保持向後相容性)
type可以像這樣?作:
type(類名,由?類名稱組成的元組(針對繼承的情況,可以為空白),包含屬 性的字典(名稱和值))
?如下?的代碼:
In [7]: class Test:#定義了?個Test類 ...: pass ...:In [8]: Test()#建立了?個Test類的執行個體對象Out[8]: <__main__.Test at 0x1c54f648518>
可以?動像這樣建立:
In [9]: Test2 = type("Test2",(),{})#定義了?個Test2類In [10]: Test2()#建立了?個Test2類的執行個體對象Out[10]: <__main__.Test2 at 0x1c54f66ed68>
我們使?"Test2"作為類名,並且也可以把它當做?個變數來作為類的引?。 類和變數是不同的,這?沒有任何理由把事情弄的複雜。即type函數中第1個實參,也可以叫做其他的名字,這個名字表示類的名字
In [11]: MyDogClass = type(‘MyDog‘,(),{})In [12]: print(MyDogClass)<class ‘__main__.MyDog‘>
使?help來測試這2個類
In [13]: help(Test)#?help查看Test類Help on class Test in module __main__:class Test(builtins.object) | Data descriptors defined here: | | __dict__ | dictionary for instance variables (if defined) | | __weakref__ | list of weak references to the object (if defined)
In [14]: help(Test2)#?help查看Test2類Help on class Test2 in module __main__:class Test2(builtins.object) | Data descriptors defined here: | | __dict__ | dictionary for instance variables (if defined) | | __weakref__ | list of weak references to the object (if defined)
4.使?type建立帶有屬性的類
type 接受?個字典來為類定義屬性,因此
In [15]: Foo = type(‘Foo‘,(),{‘bar‘:True})
可以翻譯為:
In [16]: class Foo(object): ...: bar = True
並且可以將Foo當成?個普通的類?樣使?:
In [17]: print(Foo)<class ‘__main__.Foo‘>In [18]: print(Foo.bar)TrueIn [19]: f = Foo()In [20]: print(f)<__main__.Foo object at 0x000001C54F6511D0>In [21]: print(f.bar)True
當然,你可以向這個類繼承,所以,如下的代碼:
In [22]: class FooChild(Foo): ...: pass
就可以寫成:
In [23]: FooChild = type(‘FooChild‘,(Foo,),{})In [24]: print(FooChild)<class ‘__main__.FooChild‘>In [25]: print(FooChild.bar)True
注意:
- type的第2個參數,元組中是?類的名字,?不是字串
添加的屬性是類屬性,並不是執行個體屬性
【python進階】詳解元類及其應用1