2017-08-31 90 views
5

在下面的代码中,我希望元类NameMeta在属性没有声明该属性的情况下,将属性gender添加到MyName类。如何拦截类创建并使用元类添加属性?

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) 

这是我得到的输出:我知道这个错误是有道理的,因为name是一个字符串

<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' 

。 我的问题是,我如何在元类中访问MyName类作为对象,以便我可以添加属性?

回答

3

您近距离了。你的问题是你试图使用name这个字符串将你的属性添加到meta-class的名字中。您需要将属性分配给您正在创建的类对象。这可以通过使用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) 

通过上述更改代码输出:

Male 
+0

工作。非常感谢您的快速响应。我不得不说,我诚实地认为,在这种情况下,CLS反映了它在这个案例中的名称。 –

+0

@ VincentJ.Michuki我已经更新了我的答案。正如Artyer如此友好地指出的那样,您需要使用:'dic ['gender'] ='Male''。 –

+0

您可以使用'dic.setdefault('gender','Male')'代替“if not present then insert”。可能不会更快,但“更短”。 :) – MSeifert

2

您只需将它添加到dic如果它不存在,因为它拥有类的属性:

def __new__(mcs, name, bases, dict): 
    if 'gender' not in dict: 
     dict['gender'] = 'Male' 
    # or just `dict.setdefault('gender', 'Male')` 
    return super().__new__(mcs, name, bases, dic) 

    # Or you can create the class and set it 

    cls = super().__new__(mcs, name, bases, dic) 
    if not hasattr(cls, 'gender'): 
     cls.gender = 'Male' 
    return cls 

或者你可以有一个class属性:

class NameMeta(type): 
    gender = 'Male' 
    # `gender = 'Male'` will be inherited by all classes 
    # but not instances of those classes.