python當中的metaclass使用

2021-09-18 07:26:02 字數 3361 閱讀 3133

type(class_name, base_class, attrs)

# example

newclass = type("newcls", (), )

a = newclass()

a.name

我們用type成功生成了乙個類,他的意義在於,我可以在程式執行的過程中,使用**動態的去定義乙個類(*區別於那種傳統的先用class定義完你用的類,然後例項化使用的方式*)

這裡使用type,將乙個字典或者列表,動態的轉化生成乙個類陣列

def upper_attr(class_name, class_parents, class_attr):

attrs = ((name, value)

for name, value in class_attr.items() if not name.startswith('__'))

uppercase_attrs = dict((name.upper(), value) for name, value in attrs)

return type(class_name, class_parents, uppercase_attrs)

class newcls(metaclass=upper_attr):

name = "lanix"

*** = "male"

newcls.name # lanix

newcls.name # attributeerror: type object 'newcls' has no attribute 'name'

很明顯,類定義時通過乙個metaclass可以把定義的attrs中的屬性key,全部變為大寫, metaclass除了可以接受乙個函式,也可以介紹乙個type作為基類的類。類如

class upperattrmetaclass(type):

def __new__(mcs, class_name, class_parents, class_attr):

attrs = ((name, value) for name, value in class_attr.items() if not name.startswith('__'))

uppercase_attrs = dict((name.upper(), value) for name, value in attrs)

return super(upperattrmetaclass, mcs).__new__(mcs, class_name, class_parents, uppercase_attrs)

class newcls(metaclass=upperattrmetaclass):

name = "lanix"

*** = "male"

兩者可以實現同樣的效果

在py2中, 使用元類(metaclass)可以這麼寫, 很多介紹metaclass的文章都是這樣介紹的,而且當__metaclass__ = mymetaclass 跟類定義同級別時,會成為所有同級別的類的元類。

class newclass:

__metaclass__ = mymetaclass

但是在py3版本中, 並不支援__metaclass__的寫法,應該

class newclass(metaclass=mymetaclass):

pass

最簡單的方式可以

class badman:

def __init__(self, name):

self.name = name

self.state = ''

def run(self):

print(f' is runing!')

self.state = "run"

def fight(self):

print(f' is fighting')

self.state = "fight"

b = badman("bob")

b.run()

定義都是固定不變的,不夠靈活 ,也不夠優雅。這裡有乙個使用metaclass的例子, 可以使用metaclass寫乙個fsm。

class action(object):

def __init__(self, act_desc):

self.desc = act_desc

class manmeta(type):

def __new__(cls, name, bases, attrs):

actives = {}

for k, v in attrs.items():

if isinstance(v, action):

cls.add_action(actives, k, v)

attrs.update(actives)

return type.__new__(cls, name, bases, attrs)

@classmethod

def add_action(cls, action_dict, active_name, action_obj):

def active(self):

self.state = active_name

print(action_obj.desc)

action_dict[active_name] = active

class hero(object, metaclass=manmeta):

walk = action("from on place to another")

fight = action("use weapon to fight")

die = action("your hero is dying now")

sleep = action("fall asleep")

def __init__(self):

self.state = ""

這裡首先定義了乙個active動作類,用來描述各種動作,

隨後定義了乙個metaclass,並使用這個metaclass 改變了hero的建立過程,hero.walk 定義中是乙個 action 例項,在manmeta中,對這個walk這個屬性進行了修改,變為乙個類方法的定義函式,經過這一步神奇的轉換之後。

z = hero()

z.fight() # use weapon to fight

z.state # 'fight'

(給action物件新增乙個__call__(self) 也可以實現fight()呼叫,這裡為了解釋metaclass, 我們並不關心這些)

Python 當中的and和or

一 and 在python 中,and 和 or 執行布林邏輯演算,如你所期待的一樣,但是它們並不返回布林值 而是,返回它們實際進行比較的值之一。舉例 1 2 3 4 5 6 a and b b and b a and b and c c 在布林上下文中從左到右演算表示式的值,如果布林上下文中的所有...

python當中的裝飾器

首先我們來說一下乙個軟體的設計原則 開閉原則,又被稱為開發封閉原則,你的 對功能的擴充套件是開放的,你的程式對修改源 是封閉的.這樣的軟體設計思路可以更好的維護和開發.開放 對功能擴充套件開放 封閉 對修改 封閉 接下來我們看裝飾器.首先我們先模擬一下女媧造人.def create print 女媧...

python當中的深淺copy

首先,我們要明確以下概念 在python中,物件按照可變不可變分為可變物件和不可變物件 可變物件 指 可以在原處修改,而不用建立新的物件 包括列表,字典,集合 不可變物件指 不支援在原處修改,只能通過表示式建立新的物件,然後把結果分配給變數 包括 數字,字串,元組 像a 3,這段 的執行過程是這樣 ...