在实例化超类的 python 中进行子类化
Subclassing in python of instantiated superclass
是否可以使用已经实例化的 superclass 在 Python 中进行 subclass?
我不太清楚如何提出问题,所以让我举个例子。假设我有一个 class 矩形,我想构建另一个 class ColoredRectangle。但我不希望相同维度的每个 ColoredRectangle
都成为自己的新 Rectangle
。因此,当我启动 ColoredRectangle
时,我会向它传递一个已经实例化的 Rectangle
.
也就是说,我想要
r = Rectangle([1,2])
r_red = ColoredRectangle(r, "red")
r_blue = ColoredRectangle(r, "blue")
但是现在r_red
和r_blue
应该可以得到所有的矩形方法和属性了。例如,假设 Rectangle
有一个 area()
属性。
r.area
2
r_red.area
2
r_red
和r_blue
应该"point"到相同的Rectangle
。我知道我可以这样写:
class ColoredRectangle(Rectangle):
def __init__(self, rectangle, color):
self.color = color
self.rectangle = rectangle
但是我不得不写
r_red.rectangle.area
太丑了
Owerwrite all attributes by rectangle 属性。他们在 __dict__
属性.
import copy
class Rectangle(object):
def __init__(self, area):
self.area = area
class ColoredRectangle(Rectangle):
def __init__(self, rectangle, color):
self.__dict__ = copy.deepcopy(rectangle.__dict__)
self.color = color
您似乎要求做的是将属性访问重定向到基础 Rectangle
对象。 __getattr__
方法可以为您做到这一点。
class ColoredRectangle(object):
def __init__(self, rectangle, color):
self.color = color
self.rectangle = rectangle
def __getattr__(self,attr):
return getattr(self.rectangle,attr)
继承
继承在 python 中是一件很棒的事情,我认为您不必求助于 getattr
hack,如果您需要这些,请向下滚动。
您可以强制 class 字典引用另一个object:
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
object:
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
如果你想要不同的"proxy objects",它可以从基础Rectangle
获取属性但又不会互相干扰,你有求助于getattr
黑客,这也很有趣:
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__
:
A key difference between getattr and getattribute is that
getattr is only invoked if the attribute wasn't found the usual ways. It's good for implementing a fallback for missing attributes,
and is probably the one of two you want. 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
是否可以使用已经实例化的 superclass 在 Python 中进行 subclass?
我不太清楚如何提出问题,所以让我举个例子。假设我有一个 class 矩形,我想构建另一个 class ColoredRectangle。但我不希望相同维度的每个 ColoredRectangle
都成为自己的新 Rectangle
。因此,当我启动 ColoredRectangle
时,我会向它传递一个已经实例化的 Rectangle
.
也就是说,我想要
r = Rectangle([1,2])
r_red = ColoredRectangle(r, "red")
r_blue = ColoredRectangle(r, "blue")
但是现在r_red
和r_blue
应该可以得到所有的矩形方法和属性了。例如,假设 Rectangle
有一个 area()
属性。
r.area
2
r_red.area
2
r_red
和r_blue
应该"point"到相同的Rectangle
。我知道我可以这样写:
class ColoredRectangle(Rectangle):
def __init__(self, rectangle, color):
self.color = color
self.rectangle = rectangle
但是我不得不写
r_red.rectangle.area
太丑了
Owerwrite all attributes by rectangle 属性。他们在 __dict__
属性.
import copy
class Rectangle(object):
def __init__(self, area):
self.area = area
class ColoredRectangle(Rectangle):
def __init__(self, rectangle, color):
self.__dict__ = copy.deepcopy(rectangle.__dict__)
self.color = color
您似乎要求做的是将属性访问重定向到基础 Rectangle
对象。 __getattr__
方法可以为您做到这一点。
class ColoredRectangle(object):
def __init__(self, rectangle, color):
self.color = color
self.rectangle = rectangle
def __getattr__(self,attr):
return getattr(self.rectangle,attr)
继承
继承在 python 中是一件很棒的事情,我认为您不必求助于 getattr
hack,如果您需要这些,请向下滚动。
您可以强制 class 字典引用另一个object:
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
object:
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
如果你想要不同的"proxy objects",它可以从基础Rectangle
获取属性但又不会互相干扰,你有求助于getattr
黑客,这也很有趣:
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__
:
A key difference between getattr and getattribute is that getattr is only invoked if the attribute wasn't found the usual ways. It's good for implementing a fallback for missing attributes, and is probably the one of two you want. 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