如何使用元类拦截类创建和添加属性?

Vin*_*uki 6 python

在下面的代码,我想元类NameMeta以属性添加genderMyName类的情况下,此类不声明属性.

class NameMeta(type):
    def __new__(cls, name, bases, dic):
        if 'gender' not in dic:
            setattr(name, 'gender', 'Male')
        return super().__new__(cls, name, bases, dic)

class MyName(metaclass=NameMeta):
    def __init__(self, fname, lname):
        self.fname = fname
        self.lname = lname       
    def fullname(self):
        self.full_name = self.fname + self.lname
        return self.full_name 
inst = MyName('Joseph ', 'Vincent')
print(MyName.gender)
Run Code Online (Sandbox Code Playgroud)

这是我得到的输出:

<ipython-input-111-550ff3cfae41> in __new__(cls, name, bases, dic)
      2     def __new__(cls, name, bases, dic):
      3         if 'gender' not in dic:
----> 4             setattr(name, 'gender', 'Male')
      5         return super().__new__(cls, name, bases, dic)
      6 

AttributeError: 'str' object has no attribute 'gender'
Run Code Online (Sandbox Code Playgroud)

我知道这个错误很有意义,因为它name是一个字符串.我的问题是,如何将MyName类作为元类中的对象访问,以便我可以添加属性?

Chr*_*ean 5

你很接近。你的问题是,你试图您的属性添加到的名称元级的使用name,这是一个字符串。您需要将该属性分配给您正在创建的类对象。这可以使用dic

class NameMeta(type):
    def __new__(cls, name, bases, dic):
        if 'gender' not in dic:
            dic['gender'] = 'Male'
        return super().__new__(cls, name, bases, dic)
Run Code Online (Sandbox Code Playgroud)

通过以上更改您的代码输出:

Male
Run Code Online (Sandbox Code Playgroud)