继承
继承在 python 中是一件非常好的事情,我认为你不必求助于getattr hacks,如果你想要这些,请向下滚动。
您可以强制类字典引用另一个对象:
class Rectangle(object):
def __init__(self, width, height):
self.width = width
self.height = height
def area(self):
return self.width * self.height
class ColoredRectangle(Rectangle):
def __init__(self, rect, color):
self.__dict__ = rect.__dict__
self.color = color
rect = Rectangle(3, 5)
crect = ColoredRectangle(rect, color="blue")
print crect.width, crect.height, crect.color
#3 5 blue
这两个将引用同一个Rectangle 对象:
crect.width=10
print rect.width, rect.height
#10 5
这是一个关于元编程的精彩演讲,虽然它的标题暗示了 Python3,但它也适用于 python 2.x:David Beazley - Python3 Metaprogramming
getattr黑客攻击
但是,如果出于任何原因,您希望多个 ColoredRectangle 引用同一个基 Rectangle,那么这些将相互冲突:
eve = Rectangle(3, 5)
kain = ColoredRectangle(eve, color="blue")
abel = ColoredRectangle(eve, color="red")
print eve.color, kain.color, abel.color
#red red red
如果您想要不同的“代理对象”,它们可以从基础Rectangle 获取属性但不会相互干扰,您必须求助getattrhacking,也很有趣:
class ColoredRectangle(Rectangle):
def __init__(self, rect, color):
self.rect = rect
self.color = color
def __getattr__(self,attr):
return getattr(self.rect,attr)
eve = Rectangle(3, 5)
这样可以避免干扰:
kain = ColoredRectangle(eve, color="blue")
abel = ColoredRectangle(eve, color="red")
print kain.color, abel.color
#blue red
关于__getattr__ 与__getattribute__:
getattr 和 getattribute 之间的主要区别在于
getattr 仅在没有以通常方式找到该属性时才被调用。它有利于实现缺失属性的后备,
并且可能是您想要的两个之一。 source
因为__getattr__ 只会处理未找到的属性,所以您也可以部分更新您的代理,这可能会造成混淆:
kain.width=10
print eve.area(), kain.area(), abel.area()
# 15 50 15
为避免这种情况,您可以覆盖 __setattr__:
def __setattr__(self, attr, value):
if attr == "color":
return super(ColoredRectangle,self).setattr(attr,value)
raise YourFavoriteException