Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python-Observer模式-Object没有属性_Python_Design Patterns_Python 3.x_Finalizer - Fatal编程技术网

Python-Observer模式-Object没有属性

Python-Observer模式-Object没有属性,python,design-patterns,python-3.x,finalizer,Python,Design Patterns,Python 3.x,Finalizer,我试着运行《Python基本参考》一书中的一个例子,其中涉及观察者模式,但属性有一个问题。当AccountObserver执行_del__时,将引发错误-对象没有属性“Observer”。我不知道代码出了什么问题,所以非常感谢您的帮助 class Account(object): def __init__(self, name, balance): self.name = name self.balance = balance self.o

我试着运行《Python基本参考》一书中的一个例子,其中涉及观察者模式,但属性有一个问题。当AccountObserver执行_del__时,将引发错误-对象没有属性“Observer”。我不知道代码出了什么问题,所以非常感谢您的帮助

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.\uu del\uuuuuuuu可以在AccountObserver.\uu del\uuuuu之前运行。清除类的顺序取决于全局命名空间字典顺序,由于使用了。Account.\uuu del\uuuu删除self.observators,因此以后调用Account.unregister将引发AttributeError

您的代码依赖于当模块退出时仍然存在的类和属性。这意味着您可以同时获得KeyError错误(因为已注销帐户),或者AttributeError错误(因为self.observators属性已被清除),因为Account.\u del\u已清除它

有一个巨大的脂肪警告,在:

警告:由于调用u_del_u___)方法的情况不稳定,在执行过程中发生的异常将被忽略,并将警告打印到sys.stderr。此外,当调用uu del u以响应被删除的模块时,例如,当程序执行完成时,u del u方法引用的其他全局变量可能已经被删除或正在被拆除,例如,导入机器关闭。出于这个原因,_del_u_________________________________。从版本1.5开始,Python保证在删除其他全局变量之前,从其模块中删除名称以单个下划线开头的全局变量;如果不存在对此类全局变量的其他引用,这可能有助于确保在调用_del___方法时导入的模块仍然可用

解决方法是使您的_del____________)方法在遇到此类异常时更为稳健:

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

您正在使用Python3吗?Py2.7。。我无法复制it@MartijnPieters我可以使用python3.4,AttributeError:'Account'对象没有属性'Observators'@padraiccnningham:我在3.4 shell中运行了这个。现在将尝试使用一个单独的文件。@PadraicCunningham:ah,由于清除顺序,已复制。python 2和python 3之间有什么区别?@PadraicCunningham:python 3默认使用随机哈希种子,因此字典顺序更不可预测。它也可以在Python2中发生,但是字典顺序更稳定,所以除非您使用-R开关运行Python,否则在这里不会发生这种情况。非常感谢您的及时响应和解释。