我有一个包含成员对象的类。我想像调用容器类的方法一样调用成员的方法。
下面的示例说明了我想要做的事情(但是在不同的上下文中)。
假设我们有两个类代表两种不同的产品:Toys和Shoes。每个类都有两个方法,比方说,weight()和description(),它们明显地返回项的权重和项的描述。
现在,我想将这些产品放在单独的框中,-每个框将包含单个Toy或单个Shoe。
我仍然希望能够访问weight()和description()方法,但是我希望它们成为Box实例的成员。另外,我不希望具体实现weight()和description()类中的方法,因为每当向Toy和Shoe添加新方法时,我都不希望在Box类中实现更多的方法。
下面是一个让我高兴的“最终结果”的例子:
# Define our products
product1 = Toy('plastic gun', 200)
product2 = Shoe('black leather shoes', 500)
# Now place them in boxes
box1 = Box(product1, box_code='A1234')
box2 = Box(product2, box_code='V4321')
# I want to know the contents of the boxes
box1.description()
box2.description()
# Desired results
>> plastic gun
>> black leather shoes我的实现理念是这样的。
class Product():
def __init__(self, description, weight):
self.desc = description
self.wght = weight
def description(self):
return self.desc
def weight(self):
return self.weight
class Toy(Product):
pass
class Shoe(Product):
pass
class Box(object):
def __init__(self, product, box_code):
self.box_code = box_code
self.product = product
def __getattribute__(self, name):
# Any method that is accessed in the Box instance should be replaced by
# the correspondent method in self.product
return self.product.__getattribute__(name)不过,这不管用!如果运行第一个代码块中所示的“期望”示例,就会得到无限递归。那么,这种优雅的方式是如何做到的呢?
请注意,Box有自己的参数box_code,将来我可能希望在Toy和Shoes中添加新的方法(例如,促进代码或其他什么),而不必修改类Box。
好了,伙计们,我急切地等待你们的答复。
更新:感谢Interjay和Mike的帮助,回答问题。
我只需用__getattribute__替换Box类中的方法__getattr__,它就像Interjay所建议的那样工作得很好。类框的修正定义是:
class Box(object):
def __init__(self, product, box_code):
self.box_code = box_code
self.product = product
def __getattr__(self, name):
# Any method that is accessed in the Box instance should be replaced by
# the correspondent method in self.product
return self.product.__getattribute__(name)更新:使用__setattr__完成示例
在纠正了getattr方法的问题后,我注意到当我想设置一个属性时,我的类没有达到我想要的行为。例如,如果我尝试:
box1.desc = 'plastic sword'没有更改product1的描述(它是在box1中封装的),而是在box1中创建了一个名为"desc“的新成员。为了解决这个问题,我必须定义__setattr__函数,如下所示:
def __setattr__(self, name, value):
setattr(self.product, name, value)但是,仅仅添加这个函数就会创建一个递归调用,因为在__init__中,我尝试分配self.product = product‘,它调用函数__setattr__,函数__setattr__找不到成员self.product,所以再次调用函数__setattr__,递归地无限调用。
为了避免这个问题,我必须更改__init__方法,以便使用类的字典分配新成员。然后,类Box的完整定义是:
class Box(object):
def __init__(self, product, box_code):
self.__dict__['product'] = product
self.box_code = box_code
def __getattr__(self, name):
# Any method that is accessed in the Box instance should be replaced by
# the correspondent method in self.product
return getattr(self.product, name)
def __setattr__(self, name, value):
setattr(self.product, name, value)有趣的是..。如果我首先定义成员self.product,如上面所示,程序正常工作。但是,如果我尝试首先定义成员self.box_code,程序再次遇到递归循环问题。有人知道为什么吗?
发布于 2009-11-27 20:34:02
使用__getattr__而不是__getattribute__。如果使用__getattribute__,则在计算self.product时将得到无限递归。
只有在没有找到属性时才调用__getattr__,因此不会导致这种情况。
https://stackoverflow.com/questions/1810526
复制相似问题