2016-02-15 178 views
3

我得到以下问题。 我有一个视图属性在我的班级访问一个配置,并可以引发ValueError如果用户添加垃圾到配置。通过属性列表循环

我想写一个方法来检查我的配置文件的错误,所以我想我通过列表中的每个属性,并尝试访问它的价值。因此,我不需要为每个属性都复制try-except

我尝试了下面的代码,当然在创建列表时会调用属性,因此会在我的try之外引发错误。
有没有一个优雅的解决我的问题?

import random 


def load_config(): 
    rand_number = random.randint(0, 9) 
    if rand_number == 5: 
     raise ValueError 

    return rand_number 


class foo: 
    @property 
    def bar1(self): 
     return load_config() 

    @property 
    def bar2(self): 
     return load_config() 

    @property 
    def bar3(self): 
     return load_config() 

    @property 
    def bar4(self): 
     return load_config() 

    @property 
    def bar5(self): 
     return load_config() 


    def check_properties(self): 
     properties = [ 
      self.bar1, //Exceptions are thrown here 
      self.bar2, 
      self.bar3, 
      self.bar4, 
      self.bar5, 
     ] 

     for property in properties: 
      try: 
       num = property 
      except ValueError: 
       print("ValueError at " + property.__name__) 

my_foo = foo() 
my_foo.check_properties() 

若要使MVE我更换了财产机构提供的函数的调用与创建一个随机ValueError

+0

你可以存储的名称,并使用'GETATTR(个体经营,PROPERTY_NAME)'代替。 –

+1

@karthikr:这很正常。我认为你没有正确地阅读这个问题。 –

+0

@VincentSavard如何提取一个属性的名称? __name__似乎不适用于属性 – Altoyyr

回答

1

你可以像这样定义check_properties

def check_properties(self): 
     properties = [property_name for property_name, obj in self.__class__.__dict__.items() 
          if isinstance(obj, property)] 

     for property_name in properties: 
      try: 
       getattr(self, property_name) 
      except ValueError: 
       print("ValueError at " + property_name) 

它将尝试评估getattr的房产。

这对于由基类继承的属性不起作用。你可以使用一个辅助功能,这样,而是如果你使用继承:

def get_property_names(cls, follow_inheritance=False): 
    property_names = [] 

    for attr_name, attr in cls.__dict__.items(): 
     if isinstance(attr, property): 
      property_names.append(attr_name) 

    if follow_inheritance: 
     for parent_class in cls.__mro__: 
      if parent_class != cls: 
       property_names.extend(get_property_names(parent_class, True)) 

    return property_names 

然后定义check_properties为:

def check_properties(self): 
     properties = get_property_names(self.__class__, follow_inheritance=True) 

     for property_name in properties: 
      try: 
       getattr(self, property_name) 
      except ValueError: 
       print("ValueError at " + property_name) 
+0

完美,谢谢! – Altoyyr

+1

为了给其他通过这种方式的人发出红旗,这个解决方案是有风险的,因为它假设所有的属性都应该被调用。如果您有其他属性可以执行您不想在检查过程中执行的计算,请勿使用。它也不检查父类,所以如果你使用类继承,它将不得不被更新。 – tdelaney

+0

@tdelaney:我假设人们知道风险,因为问题的字面意思是“我如何评估对象中的所有属性?”。然而,你关于继承的观点是有效的。 –