【问题标题】:nested classes in PythonPython中的嵌套类
【发布时间】:2012-02-05 05:02:42
【问题描述】:

Python 中处理类(嵌套等)看起来并不容易,令人惊讶地!我最近出现了以下问题,花了几个小时(尝试,搜索......)但没有成功。我阅读了大多数与 SO 相关的链接,但没有一个指出这里提出的问题!

#------------------------------------------------ A类: def __init__(self): self.a = 'a' 打印自我.a B(A)类: def __init__(self): 自我.b = 'b' A.a = 'a_b' 打印 self.b, A.a #------------------------------------------------ C类: A类: def __init__(self): self.a = 'a' 打印自我.a B(A)类: def __init__(self): 自我.b = 'b' A.a = 'a_b' 打印 self.b, A.a #------------------------------------------------ #------------------------------------------------ >>> c1 = A() 一种 >>> c1.a '一种' >>> c2 = B() b >>> c2.a, c2.b ('a_b', 'b') >>> c3 = C() >>> c4 = c3.A() 一种 >>> c4.a '一种' >>> c5 = c3.B() b a_b >>> c5.b 'b' >>> c5.a 回溯(最近一次通话最后): 文件“”,第 1 行,在 AttributeError:B 实例没有属性“a”

代码的问题在哪里? 在这两种情况下,似乎当 B(A) 被初始化时,A() 都没有被初始化。这个问题的解决方案是什么?请注意,在 B() 的 __init__() 中调用的术语 A.__init__() 不起作用!

更新:

几何类: 类曲线: def __init__(self,c=1): self.c = c #曲率参数 打印'曲率%g'%self.c 通过#一些代码 类线(曲线): def __init__(self): Geometry.Curve.__init__(self,0) #关键点 通过#一些代码 g = 几何() C = g.Curve(0.5) L = g.Line()

导致:

曲率 0.5 曲率 0

我在寻找什么。

【问题讨论】:

  • "... A.__init__() 在 B() 的 __init__() 中被调用不起作用!"图片或它没有发生。
  • 同上。你在B.__init__() 中拨打A.__init__() 的感觉如何?
  • @IgnacioVazquez-Abrams 现在找到了问题的解决方案。几个小时后就很棒了。您可以在问题的更新部分找到您的观点。
  • @soulcheck 请参阅我上面对 Ignacio Vazquez-Abrams 的评论。
  • @Supporter 如果您只是创建了一个名为“geometry”的模块而不是外部 Geometry 类,那将会简单得多。然后你得到完全相同的分组,但没有嵌套类的复杂性:import geometry as gc = g.Curve(0.5)l = g.Line()

标签: python class nested-class


【解决方案1】:

在方法中执行的代码在该方法的本地范围内运行。如果您访问的对象不在此范围内,Python 将在全局/模块范围内查找它,NOT 在类范围内或任何封闭类的范围内!

这意味着:

A.a = 'a_b'

C.B.__init__ 内部将设置全局A 类的类属性,而不是您可能想要的C.A。为此,您必须这样做:

C.A.a = 'a_b'

此外,如果您在子类中重写父方法,Python 将不会调用它们。你必须自己做。

作用域规则意味着如果你想在C.B.__init__中调用父类的__init__方法,它必须是这样的:

C.A.__init__(self)

不是这样的:

A.__init__(self)

这可能是你尝试过的。

【讨论】:

  • 谢谢。我可以用scoping rules关键点解决问题。完整的解决方案已作为更新添加。
【解决方案2】:

即使将嵌套类视为工厂,嵌套类似乎也很不合 Python。但是要回答您的问题:根本没有 c5.a (C.B 的实例)。在 C.B 的 init-method 中,您将属性 a 添加到 CLASS C.A,但不添加到 C.B!如果实例化,类 A 确实已经具有属性 a!但是 B 类(甚至类)的对象却没有!

您还必须记住,__init__ 不是 C++ 或 Java 中的构造函数! python 中的“真正的构造函数”是__new____init__ 只是初始化一个类的实例!

class A:
    c = 'class-attribute'
    def __init__(self):
        self.i = 'instance-attribute'

所以在这个例子中 c 是一个类属性,其中 i 是实例的一个属性。

更有趣的是,您尝试在子类实例化时向基类添加属性。您不会以这种方式获得“后期”继承属性。 您只需向 A 类添加一个附加属性,这让我感到惊讶,甚至可以工作。我猜你正在使用python 3.x?

这种行为的原因是什么?好吧,我想这与 python 的简洁特性有关,在 python 定义中是 executed(AFAIK)。

同样的原因:

def method(lst = []):

几乎是个坏主意。默认参数在定义的那一刻被绑定,并且您不会在每次调用该方法时都生成新的列表对象,而是重用相同的列表对象。

【讨论】:

  • 感谢您的回答。正如您在问题的更新部分中看到的那样,有时嵌套类使编程更加结构化且易于处理。
猜你喜欢
  • 2017-09-21
  • 1970-01-01
  • 1970-01-01
  • 2013-07-08
  • 2016-07-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-31
相关资源
最近更新 更多