亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Python元類是怎么創建一個類的

發布時間:2021-07-14 13:47:30 來源:億速云 閱讀:139 作者:chen 欄目:編程語言

本篇內容介紹了“Python元類是怎么創建一個類的”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!

如果你看過比較優秀的 Python 開源框架,肯定見到過元類的身影。例如,在一個類中定義了類屬性 __metaclass__,這就說明這個類使用了元類來創建。

那元類的實現原理究竟是怎樣的?使用元類能幫我們在開發中解決什么樣的問題?

這篇文章,我們就來看一下 Python 元類的來龍去脈。

什么是元類?

我們都知道,定義一個類,然后調用它的構造方法,就可以初始化出一個實例出來,就像下面這樣:

class Person(object)      def __init__(name):          self.name = name  p = Person('zhangsan')

那你有沒有想過,我們平時定義的類,它是如何創建出來的?

別著急,我們先來看一個例子:

>>> a = 1               # 創建a的類是int a是int的實例  >>> a.__class__  <type 'int'>  >>> b = 'abc'           # 創建b的類是str b是str的實例  >>> b.__class__  <type 'str'>  >>> def c():            # 創建c的類是function 方法c是function的實例  ...     pass  >>> c.__class__  <type 'function'>  >>> class D(object):    # 創建d的類是D d是D的實例  ...     pass  >>> d.__class__  <class '__main__.D'>

在這個例子中,我們定義了 int、str、function、class,然后分別調用了它們的__class__ 方法,這個 __class__ 方法可以返回實例是如何創建出來的。

從方法返回的結果我們可以看到:

  •  創建整數 a 的類是 int,也就是說 a 是 int 的一個實例

  •  創建字符串 b 的類是 str,也就是說 b 是 str 的一個實例

  •  創建函數 c 的類是 function,也就是說 c 是 function 的一個實例

  •  創建實例 d 的類是 class,也就是說 d 是 class 的一個實例

除了這些之外,我們在開發中使用到的例如 list、dict 也類似,你可以測試觀察一下結果。

現在我們已經得知,創建這些實例的類是 int、str、function、class,那進一步思考一下,這些類又是怎么創建出來的呢?

同樣地,我們也調用這些類的 __class__ 方法,觀察結果:

>>> a = 1 >>> a.__class__.__class__  <type 'type'>  >>>  >>> b = 'abc'  >>> b.__class__.__class__  <type 'type'>  >>>  >>> def c():  ...     pass  >>> c.__class__.__class__ <type 'type'>  >>>  >>> class D(object):  ...     pass  >>> d = D()  >>> d.__class__.__class__  <type 'type'>

從結果我們可以看到,創建這些類的類,都是 type,所以 type 就是創建所有類的「元類」。也就是說,元類的作用就是用來創建類的。

你可以這樣理解:

  1. 鴻蒙官方戰略合作共建——HarmonyOS技術社區

  2.  元類 -> 類

  3.  類 -> 實例

用偽代碼表示,就是下面這樣:

klass = MetaClass()     # 元類創建類  obj = klass()           # 類創建實例

是不是很有意思?

在這里,你也可以感受一下這句話的含義:Python 中一切皆對象!

無論是普通類型、方法、實例,還是類,都可以統一看作對象,它們的起源就是元類。

其實,在 Python 中,使用 type 方法,我們可就以創建出一個類,type 方法的語法如下:

type(class_name, (base_class, ...), {attr_key: attr_value, ...})

例如,像下面這樣,我們使用 type 方法創建 MyClass 類,并且讓它繼承 object:

>>> A = type('MyClass', (object, ), {}) # type創建一個類,繼承object  >>> A  <class '__main__.MyClass'>  >>> A()  <__main__.MyClass object at 0x10d905950>

我們還可以使用 type 創建一個包含屬性和方法的類:

>>> def foo(self):  ...     return 'foo'  ...  >>> name = 'zhangsan'  >>>  # type 創建類B 繼承object 包含 name 屬性和 foo 方法  >>> B = type('MyClass', (object, ), {'name': name, 'foo': foo})   >>> B.name          # 打印 name 屬性  'zhangsan'  >>> print B().foo() # 調用 foo 方法  foo

通過 type 方法創建的類,和我們自己定義一個類,在使用上沒有任何區別。

其實,除了使用 type 方法創建一個類之外,我們還可以使用類屬性 __metaclass__ 創建一個類,這就是下面要講的「自定義元類」。

自定義元類

我們可以使用類屬性 __metaclass__ 把一個類的創建過程,轉交給其它地方,可以像下面這樣寫:

class A(object):      __metaclass__ = ... # 這個類的創建轉交給其他地方      pass

這個例子中,我們先定義了類 A,然后定義了一個類屬性 __metaclass__,這個屬性表示創建類 A 的過程,轉交給其它地方處理。

那么,這個類屬性 __metaclass__ 需要怎么寫呢?

其實,它可以是一個方法,也可以是一個類。

用方法創建類

如果類屬性 __metaclass__ 賦值的是一個方法,那么創建類的過程,就交給了一個方法來執行。

def create_class(name, bases, attr):      print 'create class by method...'      # 什么事都沒做 直接用type創建了一個類      return type(name, bases, attr)  class A(object):      # 創建類的過程交給了一個方法      __metaclass__ = create_class  # Output:      # create class by method ...

我們定義了 create_class 方法,然后賦值給 __metaclass__,那么類 A 被創建時,就會調用 create_class 方法。

而 create_class 方法中的邏輯,就是我們上面所講到的,使用 type 方法創建出一個類,然后返回。

用類創建類

明白了用方法創建類之后,我們來看一下用類來創建另一個類。

class B(type):      # 必須定義 __new__ 方法 返回一個類      def __new__(cls, name, bases, attr):          print 'create class by B ...'          return type(name, bases, attr)  class A(object):      # 創建類的過程交給了B      __metaclass__ = B    # Output:  # create class by B ...

在這個例子中,我們定義了類 B,然后把它賦值給了 A 的類變量 __metaclass__,這就表示創建 A 的過程,交給了類 B。

B 在定義時,首先繼承了 type,然后定義了 __new__ 方法,最后調用 type 方法返回了一個類,這樣當創建類 A 時,會自動調用類 B 的 __new__ 方法,然后得到一個類實例。

創建類的過程

好了,上面我們演示了通過元類創建一個類的兩種方式,分別是通過方法創建和通過類創建。

其實創建一個類的完整流程如下:

  1. 鴻蒙官方戰略合作共建——HarmonyOS技術社區

  2.  檢查類中是否有 __metaclass__ 屬性,如果有,則調用 __metaclass__ 指定的方法或類創建

  3.  如果類中沒有 __metaclass__ 屬性,那么會繼續在父類中尋找

  4.  如果任何父類中都沒有,那么就用 type 創建這個類

也就是說,如果我們沒有指定 __metaclass__,那么所有的類都是默認由 type 創建,這種情況是我們大多數定義類時的流程。

如果類中指定了 __metaclass__,那么這個類的創建就會交給外部來做,外部可以定義具體的創建邏輯。

哪種創建類的方式更好?

雖然有兩種方式可以創建類,那么哪種方式更好呢?

一般我們建議使用類的方式創建,它的優點如下:

  •  使用類更能清楚地表達意圖

  •  使用類更加 OOP,因為類可以繼承其他類,而且可以更友好地使用面向對象特性

  •  使用類可以更好地組織代碼結構

另外,使用類創建一個類時,這里有一個優化點:在 __new__ 方法中不建議直接調用 type 方法,而是建議調用 super 的 __new__ 來創建類,執行結果與 type 方法是一樣的:

class B(type):      def __new__(cls, name, bases, attr):          # 使用 super.__new__ 創建類          return super(B, cls).__new__(cls, name, bases, attr)

創建類時自定義行為

前面我們用元類創建一個類時,它的功能非常簡單。現在我們來看一下,使用元類創建類時,如何定義一些自己的邏輯,然后改變類的屬性或行為。

我們看下面這個例子:

# coding: utf8  class Meta(type):      def __new__(cls, name, bases, attr):          # 通過 Meta 創建的類 屬性會都變成大寫          for k, v in attr.items():              if not k.startswith('__'):                  attr[k] = v.upper()              else:                  attr[k] = v          return type(name, bases, attr)  class A(object):      # 通過 Meta 創建類      __metaclass__ = Meta      name = 'zhangsan'  class B(object):      # 通過 Meta 創建類      __metaclass__ = Meta       name = 'lisi'  # 打印類屬性 會自動變成大寫  print A.name    # ZHANGSAN  print B.name    # LISI

在這個例子中,我們定義了一個元類 Meta,然后在定義類 A 和 B 時,把創建類的過程交給了  Meta,在 Meta 類中,我們可以拿到 A 和 B 的屬性,然后把它們的屬性都轉換成了大寫。

所以當我們打印 A 和 B 的屬性時,雖然定義的變量是小寫的,但輸出結果都變成了大寫,這就是元類發揮的作用。

使用場景

了解了元類的實現原理,那么元類都會用在哪些場景呢?

我們在開發中其實用的并不多,元類的使用,經常會出現在一些框架中,例如Django ORM、peewee,下面是使用 Django ORM 定義一個數據表映射類的代碼:

class Person(models.Model):      # 注意: name 和 age 是類屬性      name = models.CharField(max_length=30)      age = models.IntegerField()      person = Person(name='zhangsan', age=20)  print person.name   # zhangsan  print person.age    # 20

仔細看在這段代碼中,我們定義了一個 Person 類,然后在類中定義了類屬性 name 和 age,它們的類型分別是 CharField 和 IntegerField,之后我們初始化 Person 實例,然后通過實例獲取 name 和 age 屬性,輸出的卻是 str 和 int,而不再是 CharField 和 IntegerField。

能做到這樣的秘密就在于,Person 類在創建時,它的邏輯交給了另一個類,這個類針對類屬性進行了轉換,最終變成對象與數據表的映射,通過轉換映射,我們就可以通過實例屬性的方式,友好地訪問表中對應的字段值了。

總結

總結一下,這篇文章我們講了元類的實現原理,了解到元類是創建所有類的根源,我們可以通過 type 方法,或者在類中定義 __metaclass__ 的方式,把創建類的過程交給外部。

當使用 __metaclass__ 創建類時,它可以是一個方法,也可以是一個類。我們通常會使用類的方式去實現一個元類,這樣做更方便我們組織代碼,實現面向對象。

在使用元類創建一個類時,我們可以修改創建類的細節,例如對屬性做統一的轉換,或者增加新的方法等等,這對于我們開發一個復雜功能的類很友好,它可以把創建類的細節屏蔽在元類中,所以元類常常用在優秀的開源框架中。、

“Python元類是怎么創建一個類的”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

汉沽区| 陕西省| 梅河口市| 巴楚县| 张家港市| 沭阳县| 象山县| 乌苏市| 贵南县| 贵州省| 吉林省| 囊谦县| 沈丘县| 隆化县| 申扎县| 山西省| 长顺县| 龙井市| 绥芬河市| 兴义市| 察哈| 永安市| 师宗县| 石嘴山市| 连云港市| 霍邱县| 大埔县| 临沧市| 临高县| 察雅县| 大竹县| 小金县| 贺州市| 星子县| 大城县| 肃北| 武清区| 孟连| 馆陶县| 理塘县| 秭归县|