代码之家  ›  专栏  ›  技术社区  ›  Nanda Kishore

如果内部类被定义为顶级类的属性,如何重写内部类方法

  •  0
  • Nanda Kishore  · 技术社区  · 15 年前

    我有这样一个代码片段

    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,而是根据自己的需求扩展它。

    3 回复  |  直到 15 年前
        1
  •  1
  •   EMP    15 年前

    如果没有以下特性,它似乎可以正常工作:

    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
  •  1
  •   Ants Aasma    15 年前

    失败的原因在于 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
  •  0
  •   Pieter Witvoet    15 年前

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