我有一个具有多个相关属性的类,例如:
class SomeClass:
def __init__(self, n=0):
self.list = range(n)
self.listsquare = [ x**2 for x in self.list ]
如果我通常使用
创建一个没问题的对象a = SomeClass(10)
我将获得2个列表,a.list
和a.listsquare
。
现在,如果我想首先创建一个空对象,并为其指定一个属性,我希望其他属性自动更新,例如,如果我这样做
b = SomeClass()
b.list = range(5,10)
我希望自动更新b.listsquare
,反之亦然(分配b.listsquare
和自动更新b.list
)。这可能吗? Class 是正确的选择吗?
感谢大家,但我完全被所有不同答案所震撼。任何人都可以提供完整的解决方案,这样我就可以自学了吗?
我希望获得一个包含3个属性Foo
,length
和list
的课程listsquare
,以便:
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]
。答案 0 :(得分:16)
如果由于对另一个属性的更新而更新一个属性是您正在寻找的(而不是在访问时重新计算下游属性的值),请使用属性setter:
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]
答案 1 :(得分:6)
绝对。但请改用property。
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
隐藏属性值是留给读者的练习。
答案 2 :(得分:2)
您也可以使用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))
答案 3 :(得分:2)
Ignacio的@property解决方案非常棒,但每次引用listsquare时它都会重新计算列表 - 这可能会变得很昂贵。 Mathew的解决方案很棒,但现在你有功能调用。您可以将这些与“属性”功能结合起来。在这里,我为my_list定义了一个getter和一个setter(我只是不能称之为'list'!),它生成了listsquare:
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
输出:
[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]