【问题标题】:How to override inner class methods if the inner class is defined as a property of the top class如果内部类被定义为顶级类的属性,如何覆盖内部类方法
【发布时间】:2010-04-23 08:07:14
【问题描述】:

我有一个这样的代码 sn-p

class A(object):
    class b:
        def print_hello(self):
            print "Hello world"
    b = property(b)

我想覆盖内部类b(请不要担心小写名称)行为。比如说,我想添加一个新方法或者我想更改一个现有方法,例如:

class C(A):
    class b(A.b):
        def print_hello(self):
            print "Inner Class: Hello world"
    b = property(b)

现在,如果我将C 的对象创建为c = C(),并调用c.b,我会得到TypeError: 'property' object is not callable error。我将如何通过这个并调用扩展内部类的print_hello?免责声明:我不想更改A 类的代码。

更新:基类“A”试图模拟我在其中一个开源 api 中看到的类。所以这就是为什么我不想更改核心 api,而是根据自己的需要对其进行扩展。

【问题讨论】:

  • 正如 Evgeny 所说,对 property() 的调用应该做什么?使用您的原始代码,您甚至无法在没有错误的情况下执行 A().b。如果您要尝试描述您要实现的目标,而不是向我们提供可能会有所帮助的破碎解决方案。

标签: python inheritance inner-classes


【解决方案1】:

我不太确定为什么要将内部类定义为外部类的属性。 (我不是 Python 专家,所以也许有一个我不知道的原因)。

没有这些属性似乎可以正常工作:

class A(object):
    class b:
        def print_hello(self):
            print "A Hello world"

class C(A):
    class b(A.b):
        def print_hello(self):
            print "C Hello world"


outer = C()
inner = outer.b()
inner.print_hello() # prints "C Hello world"

【讨论】:

    【解决方案2】:

    这个失败的原因是由于b = property(b)行A.b不是你定义的类,而是一个属性对象。我实际上有点惊讶它在创建类时没有失败。如果您使用A.b.fget 作为基类,它会起作用。但正确的答案是:不要那样做。 Python 没有任何常规意义上的内部类,在类定义范围内定义的类与常规类没有什么不同。事实上,这段代码的最终结果完全相同:

    class A(object):
        pass
    
    class b(object):
        def print_hello(self):
            print("Hello world")
    
    A.b = property(b)
    

    我不确定您想要实现的具体目标是什么。如果我理解正确,您有一个父类,该类具有返回另一个类的实例的属性,并且您希望拥有一个具有返回另一个类的子类实例的属性的子类。要对返回的类进行子类化,您需要获取对该类的引用以将其用作基础。然后,您可以重写该属性以返回子类的实例。如果您使用从实例中查找类的属性,则实际上不需要覆盖属性定义:

    class A(object):
        class B(object):
            def print_hello(self):
                print("Hello from A.B")
        b = property(lambda self: self.B())
    
    class C(A):
        class B(A.B):
           def print_hello(self):
               print("Hello from C.B")
    
    A().b.print_hello()
    C().b.print_hello()
    

    【讨论】:

      【解决方案3】:

      每当您访问 A 的“b”属性时,对 A 实例的引用都会传递给 getter - 然后将其作为参数传递给 b 的构造函数。这从一开始就破坏了你的构造,因为 b 的(默认)构造函数不接受任何额外的参数。

      看起来您的 C 类不起作用,因为它的内部“b”类继承自 A 的“b”属性对象。

      我很好奇您为什么要在这里拥有一处房产——它只会让事情变得复杂。事实上,删除它可以让您在每个实例的基础上用另一个类替换 A 的内部“b”类,而根本不必求助于继承。你能给我们更多的信息吗?这种结构背后的意图和目的是什么?

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-12-10
        • 2013-11-09
        • 2021-11-28
        • 2011-11-27
        • 2012-08-02
        • 2023-03-13
        • 2021-10-04
        • 2016-08-17
        相关资源
        最近更新 更多