2017-08-31 51 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.