如何在Python中访问另一个对象的方法,该方法是对象属性之一?

4

我想知道当使用组合时,是否可以访问“超级”类实例的属性,如果可以,应该如何访问


下面提供的示例仅用于提供思路,并在进一步说明上建立共同基础。

我希望直接从对象“door”(DoorElement类型)中访问MiniVan实例的“id”属性。


我的代码

class Car:
    def __init__(self, _id):
        self.id = _id


class CarElement:
    def __init__(self, name):
        self.name = name

    def get_car_id(self):
        # Body which will access value of attribute "id"
        return car_id


class MiniVan(Car):
    def __init__(self, _id):
        super(MiniVan, self).__init__(_id)
        self.door = DoorElement('door')
        self.engine = EngineElement('engine')


class DoorElement(CarElement):
    def __init__(self, name):
        super(DoorElement, self).__init__(name)


class EngineElement(CarElement):
    def __init__(self, name):
        super(EngineElement, self).__init__(name)


def main():
    mini_van = MiniVan(123)
    id_from_door = mini_van.door.get_car_id()
    id_from_engine = mini_van.engine.get_car_id()
    print(id_from_door) # Expected output 123
    print(id_from_engine) # Expected output 123


if __name__ == '__main__':
    main()

预期结果:

  • 打印出两次 "123"

尝试的方法:

  1. 在创建对象时传递所需属性

我知道我可以定义带有传递“car_id”的 init 方法,但出于某些原因,如果可能的话,我希望避免这样做。如果不行,我可能会选择这样做。

  1. 设置类属性,然后从 CarElement 类内的 classmethod 调用它,例如:
@classmethod
def get_id(cls):
    return Car.id

但是这种解决方案的问题在于,我可以为Car类创建许多子类(MiniVan、Truck等),而我仍希望它能正常工作。

  1. 尝试使用描述符
def __get__(self, instance, owner):
    return instance.id

但我可能理解有误,根据我对清晰代码的理解,getter应该返回类的实例而不是任何属性。


附加信息

  • 我始终会将CarElement(或子类)的实例用作Car(或子类)的实例的属性 - 不同的用法将被视为使用错误
  • 可以有许多不同的Car类的子类,但始终采用继承方式(Car <- RacingCar(Car) <- FormulaOneCar(RacingCar)),而不使用组合方式

你显然在这个问题上花了很多心思,但我建议你首先解释一下你想要的输出是什么,然后再向我们展示你尝试过的解决方案。 - Aran-Fey
@Aran-Fey,感谢您的反馈。我已经编辑了问题。 - Mariusz
1
我建议在创建汽车元素时添加一个通用的“所有者”或“父级”。这样可以拥有子组件,例如汽车门把手。汽车只是根“对象”,没有所有者。任何基于类而不是实例关系的解决方案都会遇到问题,在我看来。 - JL Peyret
@JLPeyret,您能提供一个例子吗?因为我不确定是否真正理解了您的想法。 - Mariusz
1个回答

0
为了让你的代码正常工作,你需要用car_id初始化所有的CarElement。目前,你遇到的错误是由于该方法范围内缺少这样的变量引起的。我提出的变更意见如下:
class CarElement:
    def __init__(self, name, car_id):
        self.name = name
        self.car_id = car_id

    def get_car_id(self):
        # Body which will access value of attribute id
        return self.car_id

我看不到任何其他神奇的方法。


1
与其存储汽车的ID,最好是拥有对汽车对象的引用。这样你就可以访问到汽车的所有属性和方法。 - Aran-Fey
是的,我确实看到这个输出完全没有意义。我知道,我可以通过将该值作为属性传递来初始化对象,但问题是是否有其他方法可以访问它。 - Mariusz
正如答案所述:不行。你的尝试看起来像是把C++对象模型强加到Python上。它们是不同且不兼容的。Python对象模型要简单得多。 - sophros
@sophros 根据我使用 page_objects 库的经验,完全按照描述(将应用程序中的视图作为继承自 PageObject 的类,并将元素定义为 PageElement 类的实例)进行操作,我认为可以实现这样的访问。在附加的链接中,我们在调用已实例化视图的属性时,直接通过 PageObject(self.w)传递的 SeleniumWebDriver 属性来访问 PageElement 属性。 - Mariusz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接