Python 在类对象中,如何自动更新属性?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14916284/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
In class object, how to auto update attributes?
提问by LWZ
I have a class which has multiple attributes that are related, for example:
我有一个具有多个相关属性的类,例如:
class SomeClass:
def __init__(self, n=0):
self.list = range(n)
self.listsquare = [ x**2 for x in self.list ]
If I make an object normally that would no problem, with
如果我正常制作一个对象就没有问题,
a = SomeClass(10)
I will get 2 lists, a.listand a.listsquare.
我会得到 2 个列表,a.list并且a.listsquare.
Now if I want to make a empty object first, and assign one attribute to it, I want the other attributes to be automatically updated, for example if I do
现在,如果我想先创建一个空对象,并为其分配一个属性,我希望其他属性自动更新,例如,如果我这样做
b = SomeClass()
b.list = range(5,10)
I want b.listsquareto be automatically updated, and also the other way around (assign b.listsquareand auto update b.list). Is this possible? Is Classthe right choice for this?
我想b.listsquare自动更新,反之亦然(分配b.listsquare和自动更新b.list)。这可能吗?是类这个正确的选择?
Thanks to you all, but I'm completely overwhelmed by all the different answers. Can anyone give a complete solution so I can learn write my own?
谢谢大家,但我完全被所有不同的答案所淹没。任何人都可以提供完整的解决方案,以便我可以学习自己编写吗?
I would like to achieve a class Foowith 3 attributes length, listand listsquaresuch that:
我想实现一个Foo具有 3 个属性的类length,list并且listsquare:
- If I do
a = Foo(3), I geta.length = 3,a.list = [0, 1, 2],a.listsquare = [0, 1, 4]. - If I do
b = Foo().list = [5, 6], I getb.length = 2,b.listsquare = [25, 36]. - If I do
c = Foo().listsquare = [4, 9], I getc.length = 2,c.list = [2, 3].
- 如果我这样做
a = Foo(3),我得到的a.length = 3,a.list = [0, 1, 2],a.listsquare = [0, 1, 4]。 - 如果我这样做
b = Foo().list = [5, 6],我得到b.length = 2,b.listsquare = [25, 36]。 - 如果我这样做
c = Foo().listsquare = [4, 9],我得到c.length = 2,c.list = [2, 3]。
采纳答案by Ali-Akber Saifee
if updating one property due to an update on another property is what you're looking for (instead of recomputing the value of the downstream property on access) use property setters:
如果由于更新另一个属性而更新一个属性是您正在寻找的(而不是在访问时重新计算下游属性的值),请使用属性设置器:
class SomeClass(object):
def __init__(self, n):
self.list = range(0, n)
@property
def list(self):
return self._list
@list.setter
def list(self, val):
self._list = val
self._listsquare = [x**2 for x in self._list ]
@property
def listsquare(self):
return self._listsquare
@listsquare.setter
def listsquare(self, val):
self.list = [int(pow(x, 0.5)) for x in val]
>>> c = SomeClass(5)
>>> c.listsquare
[0, 1, 4, 9, 16]
>>> c.list
[0, 1, 2, 3, 4]
>>> c.list = range(0,6)
>>> c.list
[0, 1, 2, 3, 4, 5]
>>> c.listsquare
[0, 1, 4, 9, 16, 25]
>>> c.listsquare = [x**2 for x in range(0,10)]
>>> c.list
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
回答by Ignacio Vazquez-Abrams
Absolutely. But use a propertyinstead.
绝对地。但请改用属性。
class SomeClass(object):
def __init__(self, n=5):
self.mylist = range(n)
@property
def listsquare(self):
return [ x**2 for x in self.mylist ]
a = SomeClass()
a.mylist = [4, 5, 8]
print a.listsquare
Caching of the property value is left as an exercise for the reader.
缓存属性值留给读者作为练习。
回答by Matthew Adams
You can also just use setter methods, like this:
您也可以只使用 setter 方法,如下所示:
class SomeClass:
def __init__(self, n=5):
self.set_list(range(n))
def set_list(self, n):
self.list = n
self.listsquare = [ x**2 for x in self.list ]
b = SomeClass()
b.set_list(range(5,10))
回答by tdelaney
Ignacio's @property solution is great but it recalculates the list every time you reference listsquare - that could get expensive. Mathew's solution is great, but now you have function calls. You can combine these with the 'property' function. Here I define a getter and a setter for my_list (I just couldn't call it 'list'!) that generates listsquare:
Ignacio 的 @property 解决方案很棒,但每次引用 listsquare 时它都会重新计算列表 - 这可能会变得昂贵。Mathew 的解决方案很棒,但现在您有了函数调用。您可以将这些与“属性”功能结合使用。在这里,我为生成 listsquare 的 my_list 定义了一个 getter 和一个 setter(我不能称它为“list”!):
class SomeClass(object):
def __init__(self, n=5):
self.my_list = range(n)
def get_my_list(self):
return self._my_list
def set_my_list(self, val):
self._my_list = val
# generate listsquare when my_list is updated
self.my_listsquare = [x**2 for x in self._my_list]
# now my_list can be used as a variable
my_list = property(get_my_list, set_my_list, None, 'this list is squared')
x = SomeClass(3)
print x.my_list, x.my_listsquare
x.my_list = range(10)
print x.my_list, x.my_listsquare
This outputs:
这输出:
[0, 1, 2] [0, 1, 4]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

