元程式設計 python Python中的類元程式設計

2021-10-19 04:50:39 字數 4493 閱讀 9633

1、了解執行時建立類的方法——類工廠函式;

2、熟悉元類的基礎知識和使用場景;

3、了解元類的__prepare__的意義;

4、了解class的屬性以及python直譯器如何處理匯入的模組。

類元程式設計是指在執行時建立或定製類的技藝。

一、類工廠函式

類是一等物件,因此任何時候都可以使用函式新建類,而無需使用class關鍵字。

例項: 下面我們寫乙個簡單的類工廠函式:

def record_factory(cls_name,field_names):

try:

field_names=field_names.replace(',',' ').split()

except attributeerror:

pass

field_names=tuple(field_names)#使用屬性名構建元組,這將成為新的__slots__。

def __init__(self,*args,**kwards):#通過字典解析輸入資料,然後將值賦給新建的類的屬性。

attrs=dict(zip(self.__slots__,args))

attrs.update(kwards)

for key,value in attrs.items():

setattr(self,key,value)

def __iter__(self):#迭代特殊方法的思想在於讓直譯器查詢到屬性對應的值。

for name in self.__slots__:

yield getattr(self,name)#實現迭代的方法在於:通過內建getattr方法獲取已經初始化的類屬性對應的值。

def __repr__(self):#返回乙個合適的字串。

msg=', '.join('{}='.format(*i) for i in zip(self.__slots__,self))

return '{}({})'.format(self.__class__.__name__,msg)

cls_attrs=dict(__slots__=field_names,

__init__=__init__,

__iter__=__iter__,

__repr__=__repr__)

return type(cls_name,(object,),cls_attrs)#使用type構造方法構建新類並返回,注意object後的逗號很重要。

animal=record_factory('animal','name,age,price')

dog=animal('dog','bob','1000')

print(dog)#構造animal例項物件

a,b,_=dog#可以實現預期的拆包賦值

print(a,b)

輸出:animal(name='dog', age='bob', price='1000')

dog bob

type的三個引數:class type(name, bases, dict)

type最後乙個引數是乙個對映,指定新類的屬性名和值。

注意:在python中做元程式設計時, 最好不要用 exec 和 eval 函式.。如果接接收的字串來自不可信的源,這兩個函式會帶來嚴重的安全風險.

二、定製描述符的類裝飾器

類裝飾器:本質上是高階函式,其引數是被裝飾的類,用於審查審查、修改、甚至把被裝飾的類替換成其他類。

類裝飾器的重大缺點:只對直接依附的類有效。即被裝飾的類的子類可能繼承也可能不繼承裝飾器所做的改動,具體情況視改動的方式而定。

三、元類

1、基礎知識

元類:是類元程式設計最高端的工具:使用元類可以建立具有某種特質的全新變種,例如抽象基類。

功能:元類是建立類的類。

特點:所有類都直接或間接地是type的例項,不過只有元類同時也是type的子類。

具體而言,元類可以通過實現__init__方法定製類。

為了避免無限回溯,type.__class是type,即type是自身的例項。

建議:除非開發框架,否則不要在生產**中定義元類或抽象基類。

例項:使用元類定製描述符

class entitymeta(type):

"""metaclass for business entities with validated fields"""

def __init__(cls, name, bases, attr_dict):

super().__init__(name, bases, attr_dict) # 建立類物件。

for key, attr in attr_dict.items(): # <2>

if isinstance(attr, validated):

type_name = type(attr).__name__

attr.storage_name = '_{}#{}'.format(type_name, key)

class entity(metaclass=entitymeta): # <3>

"""business entity with validated fields"""

2、元類的使用場景:

驗證屬性

一次把裝飾器依附到多個方法上

序列化物件或轉換資料

物件關係對映

基於物件的持久儲存

動態轉換使用其他語言編寫為所有類定義的方法

四、元類的特殊方法__prepare__

__prepare__的功能:知道類的屬性定義的順序。

使用場景:__prepare__只在元類中有用,而且必須宣告為類方法(即要使用@classmethod 裝飾器定義)。

引數要求:__prepare__方法的第乙個引數是元類,隨後兩個引數分別是要構建的類的名稱和基類組成的元組, 返回值必須是對映。

工作原理:元類構建新類時,直譯器會先呼叫__prepare__ 方法,使用類定義體中的屬性建立對映。接著把__prepare__方法返回的對映會傳給__new__ 方法的最後乙個引數,然後再傳給__init__ 方法。

例項:使用__prepare__

class entitymeta(type):

"""metaclass for business entities with validated fields"""

@classmethod

def __prepare__(cls, name, bases):

return collections.ordereddict() # 返回乙個空的 ordereddict 例項,類屬性將儲存在裡面。

def __init__(cls, name, bases, attr_dict):

super().__init__(name, bases, attr_dict)

cls._field_names = # 中建立乙個 _field_names 屬性

for key, attr in attr_dict.items():

if isinstance(attr, validated):

type_name = type(attr).__name__

attr.storage_name = '_{}#{}'.format(type_name, key)

class entity(metaclass=entitymeta):

"""business entity with validated fields"""

@classmethod

def field_names(cls): # field_names 類方法的作用簡單:按照新增欄位的順序產出欄位的名稱

for name in cls._field_names:

yield name

五、其他

1、python中的匯入時和執行時

在程序中首次匯入模組時,python直譯器還會執行所匯入模組中的全部頂層**。以後匯入相同的模組則使用快取,只做名稱繫結。

對函式而言,首次匯入模組時:直譯器會執行頂層的 def 語句,編譯函式的定義體,把函式物件繫結到對應的全域性名稱上,但是顯然直譯器不會執行函式的定義體。通常這意味著直譯器在匯入時定義頂層函式,但是僅當在執行時呼叫函式時才會執行函式的定義體。

對類而言,首次匯入模組時:直譯器會執行每個類的定義體,甚至會執行巢狀類的定義體。執行類定義體的結果是,定義了類的屬性和方法,並構建了類物件。從這個意義上理解,類的定義體屬於「頂層**」,因為它在匯入時執行。

2、類的屬性

class除了除__mro__、__class__、和__name__之外還有以下屬性:

cls.__bases__:由類的基類組成的元組。

cls.__qualname__:其值是類或函式的限定名稱,即從模組的全域性作用域到類的點分路徑。

cls.__subclasses__():這個方法返回乙個列表,包含類的直接子類。其實現使用弱引用,防止超類和子類之間出現迴圈引用。這個方法返回的列表是記憶體裡現存的子類。

cls.mro():構建類時,如果需要獲取儲存在類屬性__mro__ 中的超類元組,直譯器會呼叫這個方法。元類可以覆蓋這個方法,定製要構建的類解析方法的順序。

Python python多執行緒程式設計

說起多執行緒,必然想到了程序 鎖等東西,python跟執行緒有關的模組有thread模組 threading模組 queue模組 mutex模組 socketserver模組。thread模組提供了基本的執行緒和鎖的支援,但不建議使用,因為當主線程退出的時候,所有其它執行緒沒有被清除就退出了,而th...

Python python資料庫程式設計

在任何的應用程式中,都需要持久儲存。一般說來,有三種基本的儲存機制 檔案 關係型資料庫或其它的一些變種,例如現有系統的api orm 檔案管理器 電子 配置檔案等等。通過python訪問資料庫,可以直接使用資料庫介面來訪問,也可以通過orm 不需要自己書寫sql 來訪問。從python中訪問資料庫需...

程式設計語法python Python 基礎語法

2017 06 24 09 50 14 一 變數 python中的變數名的要求和c 基本一致 1 只能以字母或者下劃線作為開頭,不能以數字開頭 2 識別符號的其他部分可以有字母下滑線和數字組成,不允許有特殊字元出現如 等 c 中可以有 且可以放在首位 3 不允許有空格,不允許有 分割 python ...