如何使类继承自Python中的任何对象

Posted

技术标签:

【中文标题】如何使类继承自Python中的任何对象【英文标题】:How to make a class inherit from any object in Python 【发布时间】:2021-12-08 02:34:22 【问题描述】:

总结:

我想创建一个类,它在 init 中接收一个对象并成为该对象以及该类具有的一些额外功能。例如,Flexible 类:

class Flexible():
    def __init__(self, obj):
        self.obj = obj

    def be_flexible(self):
        print("Do something")

car = Flexible(Car('BMW'))
plane = Flexible(Plane('Boeing 747'))
car.drive()
car.park()
car.be_flexible()
plane.fly()
plane.be_flexible()

详情:

我有一个 Shape 类和许多继承自这个类的 Shapes。

class Shape():
    def __init__(self, x, y, color=(0, 0, 0)):
        self.x, self.y = x, y
        self.anchor_x, self.anchor_y = 0, 0
        self.rotation = 0
        self.color = color

class Circle(Shape):
    def __init__(self, x, y, r, **kwargs):
        super().__init__(x, y, **kwargs)
        self.r = r

class Rectangle(Shape):
    def __init__(self, x, y, w, h, **kwargs):
        super().__init__(x, y, **kwargs)
        self.w = w
        self.h = h

class Triangle(Shape):
    def __init__(self, x, y, x2, y2, x3, y3, **kwargs):
        super().__init__(x, y, **kwargs)
        self.x2 = x2
        self.y2 = y2
        self.x3 = x3
        self.y3 = y3

上面的代码被简化了,所有的对象都包含getter、setter以及各种改变形状的方法。

我想添加一个方法 toggle_anchor() 来显示/隐藏锚点。所有形状都应该能够访问此方法。通常我会在 Shape 类中添加它,但是这些类来自外部库,所以我无法修改它。

因此,我希望我能做这样的事情(注意,AnchorShape 内部有一个 Circle,它将被绘制以显示形状的锚点在哪里):

class AnchorShape():
    def __init__(self, object):
        self.object = object
        self.anchor_shape = Circle(self.object.anchor_x + self.object.x,
                                   self.object.anchor_y + self.object.y, 1)

    def toggle_anchor(self):
        ...

以下代码将在哪里工作:

circle = AnchorShape(Circle(x, y, r))
print(f"Created circle (radius:circle.r")
square = AnchorShape(Rectangle(x, y, s, s))
print(f"Created square (side:square.w)")
circle.toggle_anchor()
square.toggle_anchor()

我对其他方法持开放态度,我只是希望能够通过新功能正常使用形状。

我试图避免执行以下操作,因为这涉及大量代码重复:

class AnchorCircle(Circle):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.anchor_shape = Circle(self.anchor_x + self.x,
                                   self.anchor_y + self.y, 1)

    def toggle_anchor(self):
        ...

class AnchorRectangle(Rectangle):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.anchor_shape = Circle(self.anchor_x + self.x,
                                   self.anchor_y + self.y, 1)

    def toggle_anchor(self):
        ...

class AnchorTriangle(Triangle):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.anchor_shape = Circle(self.anchor_x + self.x,
                                   self.anchor_y + self.y, 1)

    def toggle_anchor(self):
        ...

Edit1:更正拼写错误并添加了更多细节。

【问题讨论】:

您在 sn-p 的最后部分调用 Circle 内的 AnchorRectangleAnchorTriangle。他们是错别字吗?另外,我想知道为什么 Circle 使用两个参数调用,而定义需要三个位置参数 (x,y,r)。 Circle 里面的AnchorShapes 用于绘制锚点。所以AnchorShape 总是有ShapeCircle 来显示锚点位置。另外,我在Circle 中添加了第三个参数,这是一个错字。 也许我没有正确解决您的问题,或者我只是创建了一个新类并将该通用功能添加到其中并使其他类也继承自新类。 @AjaySinghRana,我会这样做,但我使用的是已经存在的库 (pyglet),并且我想将锚点添加到 pyglet.shapes。因此,我不能对这些类进行更改,因为它们是已安装库的一部分(pip install pyglet),所以我不能“让其他类从新的类继承”。 你没有得到我,伙计,只是尝试创建一个新类class Feautre(pyglet.shapes),然后添加你想要的功能并从这个类继承。顺便说一句,等有人回答,否则你可能会毁了代码。 【参考方案1】:

你问的是一回事。您描述的需求是另一回事。

如果您只是查看某些概念,则可以通过多重继承和无代码冗余来解决您真正所说的需要。

只需创建一个 AnchorShape 类,它接受新的所需参数,然后 继续使用“super”,然后使用带有类声明和空主体的多重继承来声明您的特定类:

class AnchorShape(Shape):
    def __init__(self, *args, anchor_x=None, anchor_y=None, **kwargs):
        super().__init__(*args, **kwargs)
        self.anchor_shape = Circle(self.anchor_x + self.x,
                                   self.anchor_y + self.y, 1)

    def toggle_anchor(self):
        ...

class AnchorCircle(Circle, AnchorShape):
    pass

class AnchorRectangle(Rectangle, AnchorShape):
   pass

# and so on

您的问题是关于从对象(而不是从它们的类)创建动态类 - 这是可能的,但是使用工厂函数(不是类),这将调用 type 以编程方式创建一个类,并且然后返回该新类的实例。但它似乎真的不是你的实际用例。

【讨论】:

以上是关于如何使类继承自Python中的任何对象的主要内容,如果未能解决你的问题,请参考以下文章

通过定义默认私有构造函数使类不可继承

使类可迭代尊重继承

如何制作所有从一个基类继承的对象列表

javaSE继承和抽象类

12.面向对象(继承/super/接口/抽象类)

java学习--基础知识进阶第二天--笔记