【问题标题】:loop through a list of properties循环遍历属性列表
【发布时间】:2016-05-26 20:40:03
【问题描述】:

我遇到了以下问题。 我的类中有一个视图属性,它可以访问配置,如果用户向配置中添加垃圾,则可以引发ValueError

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

我尝试了以下代码,当然,它会在创建列表时调用属性,因此在我的尝试之外抛出错误。
我的问题有什么优雅的解决方案吗?

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

【问题讨论】:

  • 您可以存储名称并改用getattr(self, property_name)
  • @karthikr:这很正常。我认为您没有正确阅读问题。
  • @VincentSavard 如何提取属性名称? name 似乎不适用于属性
  • num = getattr(self, "bar1")。等等......会做的伎俩。
  • @Altoyyr:您可以通过像[property_name for property_name, obj in self.__class__.__dict__.items() if isinstance(obj, property)] 这样的操作来获取所有属性名称。我会写一个答案。

标签: python list python-3.x properties


【解决方案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)

【讨论】:

  • 只是为了向通过这种方式的其他人挥动红旗,这个解决方案是有风险的,因为它假定所有属性都应该被调用。如果您有其他属性执行您不希望在检查期间执行的计算,请不要使用。它也不会检查类父级,因此如果您使用类继承,则必须对其进行更新。
  • @tdelaney:我认为人们知道风险,因为问题实际上是“如何评估对象中的所有属性?”。不过,您关于继承的观点是有效的。
  • 绝对是一个有效的观点,这在我的情况下效果很好,但在其他情况下可能会非常危险。
猜你喜欢
  • 1970-01-01
  • 2023-01-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-22
  • 1970-01-01
相关资源
最近更新 更多