[英]How can a class run some function when any of its attributes are modified?
當類的任何屬性被修改時,是否有一些通用的方法可以讓類運行一個函數? 我想知道是否可以運行一些子on_change
來監視類的更改,但也許有一種方法可以從class
繼承並修改一些作為 Python 類一部分的on_change
函數,有點像類的默認__repr__
方法可以被修改。 這里有什么明智的方法?
實際應用不僅僅是打印輸出,而是更新數據庫中與實例化類的數據屬性相對應的條目。
#!/usr/bin/env python
class Event(object):
def __init__(self):
self.a = [10, 20, 30]
self.b = 15
#def _on_attribute_change(self):
# print(f'attribute \'{name_of_last_attribute_that_was_changed}\' changed')
event = Event()
event.a[1] = 25
# printout should happen here: attribute 'a' changed
event.a.append(35)
# printout should happen here: attribute 'a' changed
event.c = 'test'
# printout should happen here: attribute 'c' changed
您可以覆蓋__setattr__
魔術方法。
class Foo:
def on_change(self):
print("changed")
def __setattr__(self, name, value):
self.__dict__[name] = value
self.on_change()
您可以覆蓋__setattr__
。
class Event:
def __init__(self):
self.a = [10, 20, 30]
self.b = 15
def __setattr__(self, attr, value):
print(f'attribute {attr} changed')
super().__setattr__(attr, value)
但是,這只檢測直接分配給屬性。 event.a[1] = 25
是對event.a.__setitem__(1, 25)
的調用,所以Event
對此一無所知; 它完全由event.a
解析為的任何值處理。
如果您不希望__init__
的賦值觸發通知,請直接調用super().__setattr__
以避免調用您的覆蓋。
def __init__(self):
super().__setattr__('a', [10, 20, 30])
super().__setattr(__('b', 15)
最近我在 python 上開發了服務器端,我不得不檢測列表/字典/任何你想要的變化,拯救我生命的庫是traits
。 我強烈推薦它。 您可以輕松檢查更改/刪除/添加到您的屬性的內容。
你可以在這里閱讀更多。
專門針對您的情況, 通知章節是最相關的
這是我剛剛運行的一個小片段:
from traits.api import *
class DataHandler(HasTraits):
a = List([10, 20, 30])
b = Int(15)
class Event(HasTraits):
def __init__(self):
super().__init__()
self.data_handler = DataHandler()
self.data_handler.on_trait_change(Event._anytrait_changed)
@staticmethod
def _anytrait_changed(obj, name, old, new):
is_list = name.endswith('_items')
if is_list:
name = name[0:name.rindex('_items')]
current_val = getattr(obj, name)
if is_list:
# new handles all the events(removed/changed/added to the list)
if any(new.added):
print("{} added to {} which is now {}".format(new.added, name, current_val))
if any(new.removed):
print("{} removed from {} which is now {}".format(new.removed, name, current_val))
else:
print('The {} trait changed from {} to {} '.format(name, old, (getattr(obj, name))))
e = Event()
e.data_handler.b = 13
e.data_handler.a.append(15)
e.data_handler.a.remove(15)
e.data_handler.a.remove(20)
輸出:
The b trait changed from 15 to 13
[15] added to a which is now [10, 20, 30, 15]
[15] removed from a which is now [10, 20, 30]
[20] removed from a which is now [10, 30]
希望這可以幫助。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.