Python元編程


  簡單定義“元編程是一種編寫計算機程序的技術,這些程序可以將自己看做數據,因此你可以在運行時對它進行內審、生成和/或修改”,本博參考<<Python高級編程>>將對元編程內容進行詳細描述,若有不正確之處希望大家指出。

1. 概述

  Python元編程有兩種方法,一是采用類似“裝飾器”的工具對基本元素(例如函數、類、類型)內審和對其進行實時創建和修改,二是運用類型"元類"的方式對類實例的創建過程進行修改,甚至於允許重新設計Python面對對象編程范式的實現。

2. 裝飾器

  關於裝飾器的內容可以閱讀上篇博客<<Python裝飾器>>,鏈接:http://www.cnblogs.com/xiaobingqianrui/p/8435074.html

  對wraps裝飾器的使用進行補充說明,在類裝飾器中使用閉包會導致生成的對象不再是被裝飾的類的實例,二是在裝飾器函數創建的子類的實例,這會影響__name__和__doc__等屬性,在上篇我們使用@wraps裝飾器對函數裝飾器進行操作讓問題得到解決,但在類裝飾器中這一方法無效。

3. 元類

  元類是Python的一個重要特性,是定義其他類的類,理解其工作方式,最重要的是要知道定義了對象實例的類也是對象,那么它一定有與其相關聯的類,所有的類定義的基類都是內置的type類。

#coding=utf-8

class MyClass:
    pass

if __name__ == "__main__":
    myclass = MyClass()
    print ("type of myclass:", type(myclass))
    print ("type of MyClass:", type(MyClass))

>>> type of myclass: <class '__main__.MyClass'>
>>> type of MyClass: <class 'type'>

3.1 type()語法

  type()類作為class語句的動態等效,給定類名,基類名和屬性映射會創建一個新類 

#coding=utf-8

def func1(self):
    print (1)

def func2(*argv):
    print (argv)

if __name__ == "__main__":
    MyClass = type("MyClass",(object, ), {"func1":func1, "func2":func2})
    a = MyClass()
    print (type(a))
    a.func1()
    a.func2(2)

>>> <class '__main__.MyClass'>
>>> 1
>>> (<__main__.MyClass object at 0x01A02270>,2)

3.2 元類的常用模板 

#coding=utf-8

'''元類模板 '''
class MyClass(type):
#創建一個空的命名空間,返回一個空的dict   
    @classmethod
    def __prepare__(mcs, name, bases, **kwargs):
        print ("MyClass __prepare__")
        return super().__prepare__(name, bases, **kwargs)   

    def __new__(mcs, name, bases, namespace):
        print ("MyClass __new__")
        return super().__new__(mcs, name, bases, namespace)

    def __init__(cls, name, bases, namespace, **kdargv):
        print ("MyClass __init__")   
        super().__init__(name, bases, namespace)

    def __call__(cls, *argv, **kdargv):
        print ("MyClass __call__")
        return super().__call__(*argv, **kdargv)

class _MyClass(metaclass=MyClass):
    def __new__(cls):
        print ("_MyClass __new__")
        return super().__new__(cls)

    def __init__(self):
        print("__MyClass __init__")
        super().__init__()

if __name__ == "__main__":
    a =  _MyClass()
    

>>> MyClass __prepare__
>>> MyClass __new__
>>> MyClass __init__
>>> MyClass __call__
>>> _MyClass __new__
>>> __MyClass __init_

用class語句創建的每個類都隱式的使用type作為元類,可以用metaclass=“指定元類”的方式改變這一默認行為。

3.3 元類的使用

  元類是一種非常強大的特性,但總是會是代碼更加復雜,將其用於任意類型的類時,這可能會降低代碼的魯棒性,我們必須靈活的使用元類。

#coding=utf-8

class OrderedMeta(type):
    @classmethod
    def __prepare__(mcs, name, bases, **kdargv):
        return super().__prepare__(mcs, name, bases, **kdargv)

    def __new__(mcs, name, bases, namespace):
        namespace["orderofattr"] = list(namespace.keys())
        return super().__new__(mcs, name, bases, namespace)
        
class test(metaclass = OrderedMeta):
    first = 8
    secord = 2

if __name__ == "__main__":
    print (test.orderofattr)    
    print (test.__dict__.keys())

>>> ['__module__', '__qualname__', 'first', 'secord']
>>> dict_keys(['__module__', 'first', 'secord', 'orderofattr', '__dict__', '__weakre
>>> f__', '__doc__'])


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM