gpt4 book ai didi

Python - 观察者模式 - 对象没有属性

转载 作者:行者123 更新时间:2023-11-28 22:46:20 25 4
gpt4 key购买 nike

我尝试运行“Python Essential Reference”一书中涉及观察者模式的一个示例,但属性存在问题。当 AccountObserver 执行 __del__ 时会出现错误 - 对象没有属性“观察者”。我不知道代码有什么问题,所以非常感谢任何帮助。

class Account(object):
def __init__(self, name, balance):
self.name = name
self.balance = balance
self.observers = set()
def __del__(self):
for ob in self.observers:
ob.close()
del self.observers
def register(self, observer):
self.observers.add(observer)
def unregister(self, observer):
self.observers.remove(observer)
def notify(self):
for ob in self.observers:
ob.update()
def withdraw(self, amt):
self.balance -= amt
self.notify()


class AccountObserver(object):
def __init__(self, theaccount):
self.theaccount = theaccount
self.theaccount.register(self)

def __del__(self):
self.theaccount.unregister(self)
del self.theaccount

def update(self):
print("Balance is %0.2f" % self.theaccount.balance)

def close(self):
print("Account no longer in use")


a = Account("Ketty", 200000)
a_mama = AccountObserver(a)
a_tata = AccountObserver(a)
a.unregister(a_mama)
a.withdraw(10)

输出:

Balance is 199990.00
Account no longer in use
Exception ignored in: <bound method AccountObserver.__del__ of <__main__.AccountObserver object at 0x024BF9F0>>
Traceback (most recent call last):
File "F:\Projects\TestP\src\main.py", line 28, in __del__
File "F:\Projects\TestP\src\main.py", line 13, in unregister
AttributeError: 'Account' object has no attribute 'observers'
Exception ignored in: <bound method AccountObserver.__del__ of <__main__.AccountObserver object at 0x024BFEB0>>
Traceback (most recent call last):
File "F:\Projects\TestP\src\main.py", line 28, in __del__
File "F:\Projects\TestP\src\main.py", line 13, in unregister
AttributeError: 'Account' object has no attribute 'observers'

最佳答案

Python 在解释器退出时清除模块。那时所有实例和类都被删除,这意味着 Account.__del__ 可以 AccountObserver.__del__ 之前运行。清除类的顺序取决于全局命名空间字典的顺序,由于 random hash seed,这是随机的用过的。 Account.__del__ 删除 self.observers,因此以后对 account.unregister() 的任何调用都会引发 AttributeError

您的代码依赖于模块退出时仍然存在的类和属性。这意味着您可以获得 KeyError 错误(因为 a_mama 已经取消注册),或者 AttributeError 作为 self.observers 属性已被清除(因为 Account.__del__ 已清除它)。

object.__del__ documentation中有一个大胖警告:

Warning: Due to the precarious circumstances under which __del__() methods are invoked, exceptions that occur during their execution are ignored, and a warning is printed to sys.stderr instead. Also, when __del__() is invoked in response to a module being deleted (e.g., when execution of the program is done), other globals referenced by the __del__() method may already have been deleted or in the process of being torn down (e.g. the import machinery shutting down). For this reason, __del__() methods should do the absolute minimum needed to maintain external invariants. Starting with version 1.5, Python guarantees that globals whose name begins with a single underscore are deleted from their module before other globals are deleted; if no other references to such globals exist, this may help in assuring that imported modules are still available at the time when the __del__() method is called.

解决方法是让您的 __del__ 方法在遇到此类异常时更加健壮:

def unregister(self, observer):
try:
self.observers.remove(observer)
except (KeyError, AttributeError):
# no such observer, or the observers set has already been cleared

关于Python - 观察者模式 - 对象没有属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27602290/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com