我试图跟踪可变python对象(例如,list tor字典)的条目的外部修改。这种能力在以下两种情况下特别有用:捕获作为实例类变量的可变python对象的外部修改
1)当想避免将不需要的值分配给可变的python对象时。这里有一个简单的例子,其中x必须是唯一的整数列表:
class foo(object):
def __init__(self,x):
self.x = x
def __setattr__(self,attr_name,attr_value):
# x must be a list of integers only
if attr_name == 'x' and not isinstance(attr_value,list):
raise TypeError('x must be a list!')
elif attr_name == 'x' and len([a for a in attr_value if not isinstance(a,int)]) > 0:
raise TypeError('x must be a list of integers only')
self.__dict__[attr_name] = attr_value
# The following works fine and it throws an error because x has a non-integer entry
f = foo(x = ['1',2,3])
# The following assigns an authorized list to x
f = foo(x = [1,2,3])
# However, the following does not throw any error.
#** I'd like my code to throw an error whenever a non-integer value is assigned to an element of x
f.x[0] = '1'
print 'f.x = ',f.x
2)当需要修改可变Python对象后更新了许多其它变量。下面是一个例子,其中x是一本字典,需要时进行任何更改(如删除条目或指定特定键的新值)来x
做得到更新x_vals
:
class foo(object):
def __init__(self,x,y = None):
self.set_x(x)
self.y = y
def set_x(self,x):
"""
x has to be a dictionary
"""
if not isinstance(x,dict):
raise TypeError('x must be a dicitonary')
self.__dict__['x'] = x
self.find_x_vals()
def find_x_vals(self):
"""
NOTE: self.x_vals needs to get updated each time one modifies x
"""
self.x_vals = self.x.values()
def __setattr__(self,name,value):
# Any Changes made to x --> NOT SURE HOW TO CODE THIS PART! #
if name == 'x' or ...:
raise AttributeError('Use set_x to make changes to x!')
else:
self.__dict__[name] = value
if __name__ == '__main__':
f = foo(x={'a':1, 'b':2, 'c':3}, y = True)
print f.x_vals
# I'd like this to throw an error asking to use set_x so self.x_vals
# gets updated too
f.x['a'] = 5
# checks if x_vals was updated
print f.x_vals
# I'd like this to throw an error asking to use set_x so self.x_vals gets updated too
del f.x['a']
print f.x_vals
你的意思是使用'property'就像我建议的那样? –
@IlyaPeterov:不可以。但是,如果OP唯一担心的是保持'x_vals'更新,那么您的解决方案就可以正常工作。 –
实际上,除了更新x_vals之外,还需要捕获不需要的值赋值给可变python对象的条目(请参阅修改后的问题中的第一个示例)。我修改了这个问题,并试图使它更一般。提供一个例子说明你如何做到让你的答案更清晰。 – user3076813