西西軟件園多重安全檢測(cè)下載網(wǎng)站、值得信賴(lài)的軟件下載站!
軟件
軟件
文章
搜索

首頁(yè)業(yè)內(nèi)動(dòng)態(tài) 業(yè)內(nèi)資訊 → Python基礎(chǔ)教程:元類(lèi)

Python基礎(chǔ)教程:元類(lèi)

相關(guān)軟件相關(guān)文章發(fā)表評(píng)論 來(lái)源:西西整理時(shí)間:2013/11/6 1:22:25字體大小:A-A+

作者:西西點(diǎn)擊:16次評(píng)論:0次標(biāo)簽: Python基礎(chǔ)教程

一、概述

Python雖然是多范式的編程語(yǔ)言,但它的數(shù)據(jù)模型卻是 純面向?qū)ο?/strong> 的。與那些僅在語(yǔ)法層面聲稱(chēng)純OO的編程語(yǔ)言(如Java)相比,Python的這種純粹性更加深入骨髓。

在Python的世界里,一切皆為對(duì)象:數(shù)值、序列、字典、函數(shù)、模塊、文件、類(lèi)、類(lèi)實(shí)例 等等,無(wú)一例外(參考 Data model)。其中,“類(lèi)也是對(duì)象” 的概念最讓人匪夷所思,這完全超越了傳統(tǒng)的OO思想。

元類(lèi)(metaclass)是Python 2.2中引入的概念,利用元類(lèi)可以 定制類(lèi)的創(chuàng)建行為(Customizing class creation)!霸(lèi)” 的概念同樣讓人難以理解,然而理解 “元類(lèi)” 是理解 “類(lèi)也是對(duì)象” 的關(guān)鍵。

二、經(jīng)典闡述

對(duì)于元類(lèi)的理解,目前為止,最經(jīng)典的闡述莫過(guò)于Stack Overflow上面的這篇帖子 What is a metaclass in Python?,e-satis 神一般的回復(fù)讓人醍醐灌頂,看完后基本就了然于胸了。

如果覺(jué)得看英文比較吃力,這里有一篇中文譯版 深刻理解Python中的元類(lèi)(metaclass)(注:英文原版最近有更新,但核心內(nèi)容不變)。

三、核心總結(jié)

1、類(lèi)的創(chuàng)建過(guò)程

對(duì)于類(lèi)定義:

class Foo(Base):
    def say(self):
        print 'hello'

Python解釋器 執(zhí)行class語(yǔ)句 時(shí),處理步驟如下:

確定元類(lèi)mcls。元類(lèi)的查找優(yōu)先級(jí)為:

首先查找 類(lèi)Foo 是否擁有屬性__metaclass__

否則查找 類(lèi)Foo的父類(lèi) 是否具有屬性__metaclass__

否則查找 類(lèi)Foo所在模塊 是否具有全局變量__metaclass__

否則使用默認(rèn)元類(lèi)(經(jīng)典類(lèi):types.ClassType;新式類(lèi):type)

使用元類(lèi)mcls創(chuàng)建類(lèi)Foo。創(chuàng)建語(yǔ)意等價(jià)于:

def say(self):
    print 'hello'

# 元類(lèi)的參數(shù):mcls(name, bases, dict)
Foo = mcls('Foo', (Base,), {'say': say})

創(chuàng)建成功后,類(lèi)Foo 是 元類(lèi)mcls 的 實(shí)例。

綜上:創(chuàng)建類(lèi) 其實(shí)是一種更高級(jí)別的 實(shí)例化過(guò)程,本質(zhì)上與 創(chuàng)建類(lèi)實(shí)例 相似。

實(shí)例化過(guò)程類(lèi)實(shí)例語(yǔ)意形式
創(chuàng)建類(lèi)Foo元類(lèi)mcls類(lèi)Fooclass Foo: pass <=> Foo = mcls('Foo', (), {})
創(chuàng)建類(lèi)實(shí)例foo類(lèi)Foo實(shí)例foofoo = Foo()

2、元類(lèi)的使用慣例

原則上,元類(lèi)可以是:任何接受參數(shù) name, bases, dict 并返回 類(lèi) 的 可調(diào)用對(duì)象(參考 metaclass)。

例如元類(lèi)可以是 函數(shù)

def metacls_func(name, bases, dict):
    # do customizing here
    return type(name, bases, dict)

根據(jù)最佳實(shí)踐指導(dǎo),更好的習(xí)慣是使用 類(lèi) 作為元類(lèi),典型風(fēng)格如下:

class MetaCls(type):
    def __new__(cls, name, bases, dict):
        # do customizing here
        return super(MetaCls, cls).__new__(cls, name, bases, dict)

注意:

元類(lèi)可以繼承自另一個(gè)元類(lèi),也可以使用其他元類(lèi)

除了常用的__new__,還可以借助__init__和__call__來(lái)定制被創(chuàng)建的類(lèi)

四、簡(jiǎn)單案例

1、默認(rèn)行為

1)經(jīng)典類(lèi)(Classic classes)

類(lèi)Old的三種等價(jià)定義:

class Old: pass

class Old:
    __metaclass__ = types.ClassType

Old = types.ClassType('Old', (), {})

類(lèi)Old是元類(lèi)types.ClassType的實(shí)例:

>>> isinstance(Old, types.ClassType)
True

2)新式類(lèi)(New-style classes)

類(lèi)New的三種等價(jià)定義:

class New(object): pass

class New:
    __metaclass__ = type

New = type('New', (), {})

類(lèi)New是元類(lèi)type的實(shí)例:

>>> isinstance(New, type)
True

2、使用元類(lèi)

為所有類(lèi)打上作者標(biāo)簽:

class AuthorTag(type):
    def __new__(cls, name, bases, dict):
        dict['__author__'] = 'RussellLuo'
        return super(AuthorTag, cls).__new__(cls, name, bases, dict)

class MyBlog:
    __metaclass__ = AuthorTag

class MyGitHub:
    __metaclass__ = AuthorTag

現(xiàn)在,類(lèi)MyBlog和類(lèi)MyGitHub都免費(fèi)獲得了作者簽名:

>>> MyBlog.__author__
'RussellLuo'
>>> MyGitHub.__author__
'RussellLuo'

五、實(shí)踐為王

請(qǐng)記住上面的簡(jiǎn)單案例,如果您想從本文中獲得對(duì)Python元類(lèi)僅有的一點(diǎn)印象。紙上得來(lái)終覺(jué)淺,絕知此事要躬行,開(kāi)始吧。

    相關(guān)評(píng)論

    閱讀本文后您有什么感想? 已有人給出評(píng)價(jià)!

    • 8 喜歡喜歡
    • 3 頂
    • 1 難過(guò)難過(guò)
    • 5 囧
    • 3 圍觀圍觀
    • 2 無(wú)聊無(wú)聊

    熱門(mén)評(píng)論

    最新評(píng)論

    發(fā)表評(píng)論 查看所有評(píng)論(0)

    昵稱(chēng):
    表情: 高興 可 汗 我不要 害羞 好 下下下 送花 屎 親親
    字?jǐn)?shù): 0/500 (您的評(píng)論需要經(jīng)過(guò)審核才能顯示)