使用 type() 動(dòng)態(tài)創(chuàng)建類
因?yàn)轭愐彩菍?duì)象,所以我們可以在程序運(yùn)行的時(shí)候創(chuàng)建類。Python 是動(dòng)態(tài)語言。動(dòng)態(tài)語言和靜態(tài)語言最大的不同,就是函數(shù)和類的定義,不是編譯時(shí)定義的,而是運(yùn)行時(shí)動(dòng)態(tài)創(chuàng)建的。在之前,我們先了了解下 type() 函數(shù)。
首先我們新建一個(gè) hello.py 的模塊,然后定義一個(gè) Hello 的 class ,
class Hello(object): def hello(self, name='Py'): print('Hello,', name)
然后在另一個(gè)模塊中引用 hello 模塊,并輸出相應(yīng)的信息。其中 type() 函數(shù)的作用是可以查看一個(gè)類型和變量的類型。
#!/usr/bin/env python3 # -*- coding: UTF-8 -*- from com.twowater.hello import Hello h = Hello() h.hello() print(type(Hello)) print(type(h))
輸出的結(jié)果是怎樣的呢?
Hello, Py <class 'type'> <class 'com.twowater.hello.Hello'>
上面也提到過,type() 函數(shù)可以查看一個(gè)類型或變量的類型,Hello 是一個(gè) class ,它的類型就是 type ,而 h 是一個(gè)實(shí)例,它的類型就是 com.twowater.hello.Hello。前面的 com.twowater 是我的包名,hello 模塊在該包名下。
在這里還要細(xì)想一下,上面的例子中,我們使用 type() 函數(shù)查看一個(gè)類型或者變量的類型。其中查看了一個(gè) Hello class 的類型,打印的結(jié)果是: <class 'type'> 。其實(shí) type() 函數(shù)不僅可以返回一個(gè)對(duì)象的類型,也可以創(chuàng)建出新的類型。class 的定義是運(yùn)行時(shí)動(dòng)態(tài)創(chuàng)建的,而創(chuàng)建 class 的方法就是使用 type() 函數(shù)。比如我們可以通過 type() 函數(shù)創(chuàng)建出上面例子中的 Hello 類,具體看下面的代碼:
# -*- coding: UTF-8 -*- def printHello(self, name='Py'): # 定義一個(gè)打印 Hello 的函數(shù) print('Hello,', name) # 創(chuàng)建一個(gè) Hello 類 Hello = type('Hello', (object,), dict(hello=printHello)) # 實(shí)例化 Hello 類 h = Hello() # 調(diào)用 Hello 類的方法 h.hello() # 查看 Hello class 的類型 print(type(Hello)) # 查看實(shí)例 h 的類型 print(type(h))
輸出的結(jié)果如下:
Hello, Py <class 'type'> <class '__main__.Hello'>
在這里,需先了解下通過 type() 函數(shù)創(chuàng)建 class 對(duì)象的參數(shù)說明:
1、class 的名稱,比如例子中的起名為 Hello
2、繼承的父類集合,注意 Python 支持多重繼承,如果只有一個(gè)父類,tuple 要使用單元素寫法;例子中繼承 object 類,因?yàn)槭菃卧氐?tuple ,所以寫成 (object,)
3、class 的方法名稱與函數(shù)綁定;例子中將函數(shù) printHello 綁定在方法名 hello 中
具體的模式如下:
type(類名, 父類的元組(針對(duì)繼承的情況,可以為空),包含屬性的字典(名稱和值))
好了,了解完具體的參數(shù)使用之外,我們看看輸出的結(jié)果,可以看到,通過 type() 函數(shù)創(chuàng)建的類和直接寫 class 是完全一樣的,因?yàn)镻ython 解釋器遇到 class 定義時(shí),僅僅是掃描一下 class 定義的語法,然后調(diào)用 type() 函數(shù)創(chuàng)建出 class 的 。
不過一般的情況下,我們都是使用 class ***... 的方法來定義類的,不過 type() 函數(shù)也可以讓我們創(chuàng)建出類來。也就是說,動(dòng)態(tài)語言本身支持運(yùn)行期動(dòng)態(tài)創(chuàng)建類,這和靜態(tài)語言有非常大的不同,要在靜態(tài)語言運(yùn)行期創(chuàng)建類,必須構(gòu)造源代碼字符串再調(diào)用編譯器,或者借助一些工具生成字節(jié)碼實(shí)現(xiàn),本質(zhì)上都是動(dòng)態(tài)編譯,會(huì)非常復(fù)雜。
可以看到,在 Python 中,類也是對(duì)象,你可以動(dòng)態(tài)的創(chuàng)建類。其實(shí)這也就是當(dāng)你使用關(guān)鍵字 class 時(shí) Python 在幕后做的事情,而這就是通過元類來實(shí)現(xiàn)的。