【问题标题】:What is a clean alternative to casting in order to call a hidden class method in python?为了在python中调用隐藏的类方法,有什么干净的替代方法?
【发布时间】:2020-07-20 12:43:50
【问题描述】:

我有两个具有一些共享结构的项目,但项目的具体要求不同。为了解决这个问题,我创建了两个基类:

class AbstractBaseClassA:
    def __init__(self) -> None:
        # do something
        pass


class AbstractBaseClassB:
    def __init__(self, a: AbstractBaseClassA) -> None:
        self.a = a
        # do something

我有几个抽象方法,做一些项目之间共享的工作,但现在想进入项目细节。因此,我创建了另外两个类:

class ProjectSpecificClassA(AbstractBaseClassA):
    def __init__(self) -> None:
        super().__init__()
        # do something

    def someOtherMethod(self) -> None:
        # do something
        pass


class ProjectSpecificClassB(AbstractBaseClassB):
    def __init__(self, a: ProjectSpecificClassA) -> None:
        super().__init__(a)
        # do something
        self.a.someOtherMethod()  # <-- unresolved attribute reference

现在,在ProjectSpecificClassB的最后一行,我想调用ProjectSpecificClassA的一个项目特定函数,但是由于AbstractBaseClassB的继承,这个方法是未知的。在像 Java 这样的语言中,这就是我将 self.a 转换为 ProjectSpecificClassA 的地方,但由于 python 不支持转换,我正在寻找替代方案。我知道,从技术上讲,上述解决方案有效,但我想知道是否有一个 cleaner 解决方案也被 linter / 预编译器认可?

【问题讨论】:

  • 什么组件引发了错误?它是运行时异常吗?那么确切的错误信息是什么?还是它是一条 linter 消息,然后是哪个应用程序引发了错误,而确切的消息又是什么?
  • ProjectSpecificClassB 及其祖先类与分配给self.a 的值的方法查找无关,self.aProjectSpecificClassA 的一个实例。请提供minimal reproducible example 以及演示实际问题的堆栈跟踪。
  • 这就是我在最后一句中暗示的内容:“错误”(而是警告)是通过检查我的 IDE(带有 python 插件的 IntelliJ 想法)产生的。同样,我知道提供的代码有效,但似乎可能有更清洁的解决方案。 | @SergeBallesta 我知道 python 是动态的,是让它变得灵活和伟大的原因之一,但我认为可能有一种方法可以编写同样的代码,但以一种不太动态的方式。

标签: python python-3.x inheritance casting type-safety


【解决方案1】:

Python 是动态的。这意味着someOtherMethod 将在运行时被搜索,并且会被找到,因为a 实际上是一个ProjectSpecificClassA 对象。

在 Java 中需要强制转换,就像在 C++ 中一样,因为方法是在编译时搜索的,因此编译器必须知道在哪里找到它。

Python 比这更宽容。如果您不使用__slots__ 之类的特殊处理来防止动态属性创建,则可以将方法添加到特定对象并使用它。你可以这样使用你的类:

a = ProjectSpecificClassA()
b = ProjectSpecificClassB(a)
b.a.special = lambda x: 2 * x
ProjectSpecificClassB.special = lambda self: self.a.special(3)

assert (b.special() == 6)

【讨论】:

    猜你喜欢
    • 2021-09-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-11
    • 2019-03-27
    • 2013-07-27
    相关资源
    最近更新 更多