【问题标题】:python reference a property like a functionpython引用一个像函数一样的属性
【发布时间】:2012-07-24 12:06:51
【问题描述】:

如何在不单独引用它们的情况下以 Python 方式设置多个属性?以下是我的解决方案。

class Some_Class(object):

    def __init__(self):
        def init_property1(value): self.prop1 = value
        def init_property2(value): self.prop2 = value

        self.func_list = [init_property1, init_property2]

    @property
    def prop1(self):
        return 'hey im the first property'

    @prop1.setter
    def prop1(self, value):
        print value

    @property
    def prop2(self):
        return 'hey im the second property'

    @prop2.setter
    def prop2(self, value):
        print value


class Some_Other_Class(object):

    def __init__(self):

        myvalues = ['1 was set by a nested func','2 was set by a nested func']
        some_class= Some_Class()

        # now I simply set the properties without dealing with them individually
        # this assumes I know how they are ordered (in the list)
        # if necessary, I could use a map

        for idx, func in enumerate(some_class.func_list):
            func(myvalues[idx])

        some_class.prop1 = 'actually i want to change the first property later on'

if __name__ == '__main__':
    test = Some_Other_Class()

当我有许多属性要使用用户定义的值进行初始化时,这变得很有必要。否则我的代码看起来就像一个单独设置每个属性的巨大列表(非常混乱)。

请注意,很多人在下面都有很好的答案,我认为我已经找到了一个很好的解决方案。这是一个重新编辑,主要是为了清楚地说明问题。但是,如果有人有更好的方法,请分享!

【问题讨论】:

  • 您无法确保在 Python 中对类的变量进行只读访问。您只能不鼓励访问这些变量。
  • self.setter1 在做什么?如果您在类声明中,那么 self 将不会是您的类的实例。您能否更清楚地说明这段代码在哪里以及self 在这种情况下是什么。
  • 另外,您的代码中没有任何属性。
  • 你的问题还不是很清楚。 “稍后在代码中单独访问这些功能”是什么意思?在您的示例中,“稍后”在哪里?请张贴一个你想做的例子。
  • -1 因为有一个问题如此乱码,以至于您抱怨每个答案。看看:sscce.orgwhathaveyoutried.com(很有用,即使你有一些代码)。

标签: python list properties reference setter


【解决方案1】:

只需使用@property 装饰器

>>> class A:
...    a=2
...    @property
...    def my_val(self,val=None):
...        if val == None:return self.a
...        self.a = val
...
>>> a=A()
>>> a.my_val
2
>>> a.my_val=7
>>> a.my_val
7

这样的?

如果你只想允许设置,那么不要给它一个默认值

>>> class A:
...    a=2
...    @property
...    def my_val(self,val):
...        self.a = val
...
>>> a=A()
>>> a.my_val
<Exception>
>>> a.my_val=7
>>> a.a
7

或者如果您只想允许检索,只需省略第二个参数

>>> class A:
...    a=2
...    @property
...    def my_val(self):
...        return self.a
...      
...
>>> a=A()
>>> a.my_val
2
>>> a.my_val=7
<Exception>

【讨论】:

  • In >= 2.6 - 在@property ... def my_val ... 之后,您可以执行@my_val.setter ... def my_val(self, val)...,因此您不需要第一个代码块中的默认参数和第二个参数。
  • 很好的补充......我想我以前用过......但通常默认的 arg 对于我的目的来说足够优雅
  • 问题不在于如何实现基本检索的属性。以您为例:现在我想将“a”存储在列表 g 中,然后执行 g[index_of_a] = 5 并让它更新属性。不幸的是,鉴于您的方法,属性的值被存储在列表中 - 而不是属性设置器方法。
  • 是的,我不能回答我自己的问题,因为我是一个新手......但我得到了它的工作。这是我所做的:创建一个简单地调用属性 set 方法的小函数:def setprop1(value): self.prop = value。现在可以在列表中引用该函数(每个属性都有一个)。而且,如果您将其设置为设置所有属性的函数内部的嵌套函数,您将永远不必再看到它!如果有人对此有更优雅的解决方案,请告诉我!我明天会发布我的答案(当我有能力的时候)。
【解决方案2】:

我……终于想我知道你想要做什么,而且你不需要按照你接近它的方式去做。让我试一试。

class someclass(object):

    def __init__(self):
        func_list = [self.setter1, self.setter2]
        value_list = [1, 2]
        #    These lines don't need to be this complicated.
        #    for ind in range(len(func_list)): 
        #        func_list[ind](value_list[ind])

        for idx, func in enumerate(func_list):
            func(value_list[idx])

        #  Or even better
        for idx, (func, val) in enumerate(zip(func_list, value_list)):
            func(val)

    def setter1(self, value): 
        self.a = value

    def setter2(self, value): 
        self.b = value

值得指出的是,idx 变量和枚举调用在第二种形式中是多余的,但我不确定你是否需要在其他地方。

【讨论】:

  • 关闭 - 但我正在尝试使用属性。看我的回答
  • 感谢您对枚举的见解 - 您的部分答案将在我的手中!
【解决方案3】:

如果你在对象字典中查找属性,你会得到属性描述符(如果有的话),同样也会得到类;例如

a = SomeClass()
descriptor = a.__dict__.get('descriptor', type(a).__dict__.get('descriptor'))

假设descriptor是一个描述符,它会有以下方法:

['deleter', 'fdel', 'fget', 'fset', 'getter', 'setter']

注意fgetfset

【讨论】:

  • 我确定这可行,但老实说,这样的代码对我的大脑来说太难了。我恳求无知!
  • 这对您来说到底有什么困难?它有一个嵌套在另一个函数调用中。
  • 好吧,看看如何使用它来访问属性设置器方法会很好。否则它不直观 - 请参阅下面的答案
  • @ecr 我在描述符上添加了一个方法列表,以防您无法查找。
  • @ecr 我仍然不知道你想做什么。上面向您展示了如何获取属性描述符。列表不是可执行的代码。
猜你喜欢
  • 2014-03-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-05
  • 1970-01-01
  • 2014-02-15
相关资源
最近更新 更多