2011-10-06 79 views
3

我似乎無法弄清楚如何獲取類數據描述符的列表。基本上,我想對字段和未設置的字段進行一些驗證。例如:python類數據描述符列表

class Field (object): 
    def __init__ (self, name, required=False): 
     self.name = name 
     self.required = required 

    def __set__ (self, obj, val): 
     obj.__dict__[self.name] = val 

    def __get__ (self, obj): 
     if obj == None: 
      raise AttributeError 
     if self.name not in obj.__dict__: 
      raise AttributeError 
     return obj.__dict__[self.name] 

然後我想實現它的模型,像這樣:

class BaseModel (object): 
    some_attr = Field('some_attr', required=True) 
    def save (self): 
     for field in fields: 
      if field.required and field.name not in self.__dict__: 
       raise Exeception, 'Validation Error' 

我怎麼會去讓我定義的字段列表?我在想,我可以做到以下幾點:

import inspect 

fields = [] 
for attr in self.__class__.__dict__: 
    if inspect.isdatadescriptor(self.__class__.__dict__[attr]): 
     fields.append(attr) 

但我遇到了繼承問題,有什麼想法?

回答

2

爲了迭代類的成員,您需要使用inpsect.getmembers。所以,你的最後一個例子是這樣的:

import inspect 

fields = [] 
for member_name, member_object in inspect.getmembers(self.__class__): 
    if inspect.isdatadescriptor(member_object): 
     fields.append(member_name) 

在你descriptor就應該更換直接與Python的getattrsetattr建宏訪問__dict__

此外,請記住,您要區分descriptor屬性在類上的名稱和基礎實例的屬性。在這種情況下,我通常會預先加下劃線。例如:

class Field (object): 
    def __init__(self, name, required=False): 
     self.name = '_' + name 
     self.required = required 

    def __set__(self, obj, val): 
     setattr(obj, self.name, val) 

    def __get__(self, obj): 
     return getattr(obj, self.name) 
+0

我只是想知道,是否有可能使它只執行一次,因爲字段不會改變我不想在每個對象實例上做它。 –

+1

我不確定我是否理解你的意思。這是一個驗證類的問題,以便它只包含字段屬性?然後,只有在創建課程時才進行一次驗證,而不是每次調用「保存」時都進行驗證? –

+1

如果是這樣的話,那麼我會考慮在元類或者類裝飾器中包裝這種驗證。 –