Python 如何处理内部类属性依赖关系?
如果您想在更改属性时更改类Python 如何处理内部类属性依赖关系?,python,list,Python,List,如果您想在更改属性时更改类中的其他变量,只需为其编写一个属性即可。如果您有一个简单的数据类型,那么这很好。但是,如果您的变量包含一个复杂的类型,如列表(不是那么不典型),则可以更改内容本身,而无需再次调用变量.setter 是否有任何回调或事件可用于跟踪对类的列表属性的更改?还可以做些什么来保持代码干净,而不破坏类的内部功能 例如: class Accumulator(object) def __init__(self,all_things): # :param all_thing
中的其他变量,只需为其编写一个属性即可。如果您有一个简单的数据类型,那么这很好。但是,如果您的变量包含一个复杂的类型,如列表(不是那么不典型),则可以更改内容本身,而无需再次调用变量.setter
是否有任何回调或事件可用于跟踪对类的列表属性的更改?还可以做些什么来保持代码干净,而不破坏类的内部功能
例如:
class Accumulator(object)
def __init__(self,all_things):
# :param all_things: a list of stuff of any kind
self.__all_things = all_things
@property
def all_things(self):
return self.__all_things
@all_things.setter
def all_things(self,input):
self.__all_things = input
跳出框框思考可能是解决办法。首要任务不是让类结构保持活动状态,而是找到一个可以工作并允许干净API的模式 您必须使用list的自定义子类来检测更改:
class MyList(list):
on_change_callback = None
def _notify(self):
if self.on_change_callback is not None:
self.on_change_callback(self)
def __setitem__(self, index, value):
super(MyList, self).__setitem__(self, index, value)
self._notify()
# Etc, each mutating method needs to be overridden.
您需要覆盖每个变异方法,调用原始方法(通过super()
),然后调用self.\u notify()
。有关方法列表,请参见章节。为了便于讨论和提高创造力,我想自己提供以下解决方案:
class Accumulator(object):
def __init__(self,all_things):
#:param all_things: a sequence or generator of stuff of any kind
self.__all_things = tuple(all_things)
@property
def all_things(self):
return self.__all_things
@property
def all_things(self, all_things):
self.__all_things = tuple(all_things)
它是干净的,只读的,不会出错或被滥用。现在同样的假设适用于问题的结构:如果你想改变它,你需要重置它。但你不必告诉用户,因为这是他唯一的机会。如果用户仍然想知道为什么,他可以阅读希望详细的类docstring。简短回答:不使用自定义类替换列表,这是一个可能的解决方案。你能告诉我怎么做吗?在你写答案的时候,我做了一些研究。子类化(或者合成,如果你更喜欢的话)看起来都像是一个简单的过程。在你完成并假定没有bug之后,你仍然有一个比标准列表慢得多的对象(它可能是优化的C代码)。@erikb85:但这是你的选择;或者事实上,完全不允许对项目进行变异。在这种情况下,也许你是对的。我认为还是有更好的解决办法,就是不要像我那样写这门课。否则很多人会遇到这个问题,并且会有众所周知的标准解决方案,这些解决方案并不难实现<代码>应该有一种——最好只有一种——显而易见的方法来实现它。虽然这种方式一开始可能并不明显,除非你是荷兰人。
-Zen of PythonTotally脱离了主题,但请记住:我是荷兰人。;-)另外:pythonic的方法是不担心这些类型的突变,除非有一个令人信服的方法这样做。例如,ZODB持久化模块确实关心(因此它可以将更改提交到数据库),并为您提供跟踪它们的工具(列表和映射的自定义类)。至于性能:列表突变本身仍然以原始的list
类型处理(因此在C中)。Python只处理通知,而瓶颈将在回调本身,而不是调用它。我认为你把重点放在了错误的问题上。