我正在学习 Python 中的设计模式,并希望将抽象工厂与委托模式结合起来(以更深入地了解该模式的工作原理)。但是,在组合这两种模式时,我遇到了一个奇怪的递归错误,我不明白。
错误是:
[Previous line repeated 987 more times]
File "c:\Users\jenny\Documents\design_pattern\creational\abstract_factory.py", line 60, in __getattribute__
def __getattribute__(self, name: str):
RecursionError: maximum recursion depth exceeded
当调用
client_with_laptop.display()
时,它会被引发。然而,尽管 client_with_laptop._hardware
返回笔记本电脑实例,但递归错误已在 __init__
期间存储在 factory.get_hardware()
中。
代码是:
from abc import abstractmethod
class ITechnique:
#abstract product
@abstractmethod
def display(self):
pass
def turn_on(self):
print("I am on!")
def turn_off(self):
print("I am off!")
class Laptop(ITechnique):
#concrete product
def display(self):
print("I'am a Laptop")
class Smartphone(ITechnique):
#concrete product
def display(self):
print("I'am a Smartphone")
class Tablet(ITechnique):
#concrete product
def display(self):
print("I'm a tablet!")
class IFactory:
@abstractmethod
def get_hardware():
pass
class SmartphoneFactory(IFactory):
def get_hardware(self):
return Smartphone()
class LaptopFactory(IFactory):
def get_hardware(self):
return Laptop()
class TabletFactory(IFactory):
def get_hardware(self):
return Tablet()
class Client():
def __init__(self, factory: IFactory) -> None:
self._hardware = factory.get_hardware()
def __getattribute__(self, name: str):
return getattr(self._hardware, name)
if __name__ == "__main__":
client_with_laptop = Client(LaptopFactory())
client_with_laptop.display()
client_with_tablet = Client(TabletFactory())
client_with_tablet.display()
client_with_smartphone = Client(SmartphoneFactory())
client_with_smartphone.display()
当我访问属性 _hardware 并删除 get_attribute 部分时(基本上,当我删除委托模式时),一切都会按预期工作。请参阅下面修改后的代码部分,该部分有效:
class Client():
def __init__(self, factory: IFactory) -> None:
self._hardware = factory.get_hardware()
if __name__ == "__main__":
client_with_laptop = Client(LaptopFactory())
client_with_laptop._hardware.display()
client_with_tablet = Client(TabletFactory())
client_with_tablet._hardware.display()
client_with_smartphone = Client(SmartphoneFactory())
client_with_smartphone._hardware.display()
任何人都可以帮我解释为什么会出现递归错误或如何修复它。我的目标是(1)根据客户端中使用的工厂拥有不同的设备,并且(2)能够从
_hardware
调用方法,而无需一直键入 client._hardware
而是直接从客户端对象调用它,例如client.display()
。问题不在于这在现实中是否是一种有用的方法;而在于。我只是想更好地理解该模式以及发生的错误。 :-)
from abc import abstractmethod
class ITechnique:
#abstract product
@abstractmethod
def display(self):
pass
def turn_on(self):
print("I am on!")
def turn_off(self):
print("I am off!")
class Laptop(ITechnique):
#concrete product
def display(self):
print("I'am a Laptop")
class Smartphone(ITechnique):
#concrete product
def display(self):
print("I'am a Smartphone")
class Tablet(ITechnique):
#concrete product
def display(self):
print("I'm a tablet!")
class IFactory:
@abstractmethod
def get_hardware():
pass
class SmartphoneFactory(IFactory):
def get_hardware(self):
return Smartphone()
class LaptopFactory(IFactory):
def get_hardware(self):
return Laptop()
class TabletFactory(IFactory):
def get_hardware(self):
return Tablet()
class Client():
def __init__(self, factory: IFactory) -> None:
self._hardware = factory.get_hardware()
def __getattribute__(self, name: str):
return getattr(self._hardware, name)
创建 Client 对象后,该对象具有 方法__getattribute__。在这个方法中你 然后继续调用该对象的 __getattribute__ 方法当您访问此对象的显示方法时。 这会导致即时递归。为了解决这个问题你需要 允许弄清楚需要做什么。 阅读 __getattr__ 和 __getattribute__ 的文档以确定 你想如何处理它。
发生递归错误是因为 Client 类中的 getattribute 方法在尝试访问 _hardware 的属性时触发了递归调用。发生这种情况是因为 getattribute 调用 getattr(self._hardware, name),然后它尝试在 _hardware 属性上再次调用 getattribute,从而导致无限递归。
要解决此问题,您可以通过重写 getattr 方法而不是 getattribute 来显式定义应将哪些属性委托给 _hardware 对象。以下是修改 Client 类的方法:
类客户端: def init(self, 工厂: IFactory) -> 无: self._hardware=factory.get_hardware()
def __getattr__(self, name: str):
return getattr(self._hardware, name)