首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >实例化超类python中的子类

实例化超类python中的子类
EN

Stack Overflow用户
提问于 2015-11-01 14:28:43
回答 3查看 2.9K关注 0票数 6

是否可以在Python中使用已经实例化的超类?

我不知道该如何构造这个问题,所以让我举个例子。假设我有一个矩形类,我想要构建另一个类ColoredRectangle。但我不希望每个相同维度的ColoredRectangle成为自己的新Rectangle。因此,当我启动ColoredRectangle时,我会传递给它一个已经实例化的Rectangle

呃,我想

代码语言:javascript
运行
复制
r = Rectangle([1,2])
r_red = ColoredRectangle(r, "red")
r_blue = ColoredRectangle(r, "blue")

但是现在r_redr_blue应该能够获得所有矩形方法和属性。例如,假设Rectangle有一个area()属性。

代码语言:javascript
运行
复制
r.area
2
r_red.area
2

r_redr_blue应该“指向”同一个Rectangle。我知道我可以这样写:

代码语言:javascript
运行
复制
 class ColoredRectangle(Rectangle):

      def __init__(self, rectangle, color):
          self.color = color
          self.rectangle = rectangle

但那样我就得写

代码语言:javascript
运行
复制
  r_red.rectangle.area

这很难看。

EN

Stack Overflow用户

回答已采纳

发布于 2015-11-02 00:11:15

继承

继承在python中是一件很好的事情,我认为您不必求助于getattr黑客,如果需要,请向下滚动。

您可以强制类字典引用另一个对象:

代码语言:javascript
运行
复制
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对象:

代码语言:javascript
运行
复制
crect.width=10
print rect.width, rect.height
#10 5

这是关于元编程的精彩演讲,虽然它的标题暗示着Python3,但它也适用于python2.x:https://www.youtube.com/watch?v=sPiWg5jSoZI

getattr黑客

但是,如果出于任何原因,您希望多个ColoredRectangle引用相同的基本Rectangle,那么它们将相互冲突:

代码语言:javascript
运行
复制
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获取属性,但不相互干扰),您可以使用求助于getattr黑客,这也很有趣:

代码语言:javascript
运行
复制
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)

这将避免下列干扰:

代码语言:javascript
运行
复制
kain = ColoredRectangle(eve, color="blue")
abel = ColoredRectangle(eve, color="red")
print kain.color, abel.color
#blue red

关于__getattr____getattribute__

getattribute和getattr之间的一个关键区别是,只有在没有按照通常的方式找到属性时才调用getattr。它有利于实现丢失属性的回退,而且可能是您想要的两个属性中的一个。来源

由于只有未找到的属性将由__getattr__处理,所以您还可以部分更新代理,这可能会让人感到困惑:

代码语言:javascript
运行
复制
kain.width=10
print eve.area(), kain.area(), abel.area()
# 15 50 15

为了避免这种情况,您可以重写__setattr__

代码语言:javascript
运行
复制
def __setattr__(self, attr, value):
    if attr == "color":
        return super(ColoredRectangle,self).setattr(attr,value)
    raise YourFavoriteException
票数 6
EN
查看全部 3 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33463232

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档