元編程


    physics,即物理學,是研究物質、能量的本質與性質,以及它們彼此之間相互作用的自然科學。
    metaphysics, 被翻譯爲「形而上學」,由日本人 井上哲次郎 於 明治時代 翻譯爲漢字詞語,指研究事物本身的學問。通常人們在談論形而上學時,往往將它作爲一種哲學上的討論--關於根本(或者存在)本身的意義。

    meta前綴,源於希臘語,其本意是「在…後,越過…的」,而後在西方哲學界的發展中漸漸賦予該詞綴一種全新的意義:關於某事自身的某事。比如 meta-knowledge 就是「關於知識本身的知識」,meta-data 就是「關於數據的數據」,meta-language 就是「關於語言的語言」,而 meta-programming 也是由此而來,是「關於編程的編程」。

meta在中國大陸多被翻譯爲「元」,在臺灣多被翻譯爲「後設」

什麼是元編程

元編程的目的是操作其他的程序(或自身)作爲它自身的數據,在運行時完成它本應該在編譯時應該完成的任務。

一個使用bash腳本描述的元程序


#!/bin/bash
# metaprogram
echo '#!/bin/bash' >program
for ((I=1; I<=992; I++)) do
    echo "echo $I" >>program
done
chmod +x program

元編程的能力在很大的程度上也和選擇的語言有關係,比如:C/C++ 的宏, Java的反射和動態代理……
而像Python這種動態性強的語言,給對象加個屬性、方法啥的,簡直不值一提。

一切都是對象……嗎?

繼在(類)Unix世界喊出了「一切皆是文件」的口號之後,Python世界也喊出了「一切皆是對象」的口號。

不信?打開終端,隨便輸入點什麼,來看看結果


>>> type("a")
<class 'str'>
>>> type(1)
<class 'int'>
>>> type([])
<class 'list'>
>>> type({})
<class 'dict'>
>>> type(Exception())
<class 'Exception'>
>>> type(object())
<class 'object'>

如果你有一個自定義的類Person, 就會有


>>> EvinK = Person()
>>> type(EvinK)
<class 'Person'>

上面所有的東西,都被type()識別爲某個class(對象)的實例。

對象的對象

Python世界裏所有的對象都繼承於object對象,使用isinstance(instance, object)就可以驗證這一點。但是,object又是什麼類型呢?按照直覺的話,它應該還是一個object類型,多說無益,開一個終端來測試一下吧!


>>> type(object)
<class 'type'>
>>> type(type)
<class 'type'>
>>> isinstance(object, object)
True
>>> isinstance(object, type)
True
>>> isinstance(type, object)
True
>>> isinstance(type, type)
True

原來,object是一個 type類型。

type不光作爲一個類型鑑定函數,居然是一個類。那既然是類,肯定也 object的子類,但是同時, objecttype的一個實例,於是間接地 object也成爲了自身的實例(由於 typeobject的繼承關係)。

python-type-instance.png

由此推論,所有繼承於 object的類(即Python中的所有對象),都是 type的一個實例。

type在此就作爲這些類的類之存在,並用來定義這些類中的屬性的方法。它是Python世界裏最爲特殊的一個對象,一個用來操縱對象的對象。它是 object的子類, object是它的實現。

使用type來定義一個類

一個已知的定義類的方式(如下),已經寫入了各種文章中


class Person:
    """
    Person Document
    """
    # 類變量
    name = "EvinK"
    # 私有類變量
    __private_var = 1

    # 實際上的構造函數
    def __new__(cls, *args, **kwargs):
        cls.age = kwargs["age"]
        return cls

    # 此方法將不會被執行
    def __init__(self, age):
        self.age_ = age

    # 靜態方法
    @staticmethod
    def get_private_var():
        return Person.__private_var

    # 類方法
    @classmethod
    def get_last_age(cls):
        # 返回最後一個實例的age
        return cls.age

if __name__ == "__main__":

    print(Person.__dict__)

    {
        '__module__': '__main__',
        '__doc__': '\n    Person Document\n    ',
        'name': 'EvinK',
        '_Person__private_var': 1,
        '__new__': <staticmethod object at 0x7f98aec409b0>,
        '__init__': <function Person.__init__ at 0x7f98acf25840>,
        'get_private_var': <staticmethod object at 0x7f98aec40908>,
        'class_method': <classmethod object at 0x7f98aec40ac8>,
        '__dict__': <attribute '__dict__' of 'Person' objects>,
        '__weakref__': <attribute '__weakref__' of 'Person' objects>
    }

    evink = Person(age=13)
    print(evink.__dict__)

    {
        '__module__': '__main__',
        '__doc__': '\n    Person Document\n    ',
        'name': 'EvinK',
        '_Person__private_var': 1,
        '__new__': <staticmethod object at 0x7f4e297d8d30>,
        '__init__': <function Person.__init__ at 0x7f4e297db840>,
        'get_private_var': <staticmethod object at 0x7f4e2b4f6ac8>,
        'class_method': <classmethod object at 0x7f4e2b4f69b0>,
        '__dict__': <attribute '__dict__' of 'Person' objects>,
        '__weakref__': <attribute '__weakref__' of 'Person' objects>,
        'age': 13
    }

上述的類被一個字典給描述,其中包含有這個類的類變量, 靜態方法類方法, 方法構造方法。而類的實例也可以被一個字典描述,只不過多了寫 實例變量而已。這兩者的結構看上去是如此的相似,但是一個是類型(type的實例),一個是(類的)實例。

既然通過類的構造方法就可以生成實例,那作爲 type實例的類,是不是也可以由 type生成呢?


Person = type("Person", (), dict(
        name="EvinK",
        # 使用type生成的類聲明將不會被轉換爲 _Person__private_var 這種形式
        __private_var=1
    ))

Person.__doc__ = \
        """
            Person
        """

@staticmethod
def new(cls, *args, **kwargs):
        return cls

# 出現__new__方法時, 此構造將不會被執行
def init(self, age):
        self.age = age

Person.__init__ = init
Person.__new__ = new

上面由type生成的類,使用 __dict__屬性時,可以看到,基本和我們使用 class關鍵字聲明的類長得一樣。這對某些靜態類型的語言來說簡直是天方夜譚!

未完待續……

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章