可以从嵌套类定义实现继承吗?

时间:2013-12-20 16:41:59

标签: python class inheritance scope

令我惊讶的是,这段代码给出了后续错误(Python 2.7.3):

class Foo(object):
    class Bar(object):
        pass
    class Baz(object):
        class InnerBar(Bar):
            pass

结果:

Enthought Python Distribution -- www.enthought.com
Version: 7.3-2 (64-bit)

Python 2.7.3 |EPD 7.3-2 (64-bit)| (default, Apr 11 2012, 17:52:16)
[GCC 4.1.2 20080704 (Red Hat 4.1.2-44)] on linux2
Type "credits", "demo" or "enthought" for more information.
Hello
>>> class Foo(object):
...     class Bar(object):
...         pass
...     class Baz(object):
...         class InnerBar(Bar):
...             pass
...
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 4, in Foo
  File "<stdin>", line 5, in Baz
NameError: name 'Bar' is not defined

我怀疑这与同等Bar = type(...) class任务的特定执行有关,但即便如此,为什么Bar不能通过Baz来实现1}}?

有没有办法为这种精确的实现方法解决这个问题(因为我不想放松Bar在{{1}内定义的class Foo的约束} Foo中的类中的其他类可能希望从Bar继承。

我想到的特定用例是模仿一些数据库结构,以创建一个更面向对象的设计,它反映了数据服务项目中的模式。大部分代码都是自动生成的Python派生自一个在XSD上执行检查的程序,因此在类中定义类是一种模仿XSD复杂类型的某些东西的自然方式,但是还具有添加的能力,也可以说它们何时是其他复杂的类型等等。这就是为什么我犹豫是否要在Foo之外拉一个类以便以后继承。

2 个答案:

答案 0 :(得分:3)

这里没有关闭。执行嵌套代码时,类的主体是父作用域。

就嵌套作用域中的代码而言,只存在全局和本地作用域,Foo类主体可以访问的名称空间。

请参阅Naming and Binding documentation

  

如果定义发生在功能块中,则范围将扩展到定义块中包含的任何块,除非包含的块为名称引入了不同的绑定。类块中定义的名称范围仅限于类块

强调我的。

这里的解决方法是使用嵌套函数来生成可以访问的范围:

class Foo(object):
    def produce_nested_scope():
        class Bar(object):
            pass
        class Baz(object):
            class InnerBar(Bar):
                pass
        return Bar, Baz
    Bar, Baz = produce_nested_scope()
    del produce_nested_scope

演示:

>>> class Foo(object):
...     def produce_nested_scope():
...         class Bar(object):
...             pass
...         class Baz(object):
...             class InnerBar(Bar):
...                 pass
...         return Bar, Baz
...     Bar, Baz = produce_nested_scope()
...     del produce_nested_scope
... 
>>> Foo.Bar
<class '__main__.Bar'>
>>> Foo.Baz
<class '__main__.Baz'>

答案 1 :(得分:1)

这是一个可怕的黑客:

class Foo(object):
    def hack(dest):
        class Bar(object):
            pass
        class Baz(object):
            class InnerBar(Bar):
                pass

        dest.update(locals())
    hack(locals())
>>> Foo.Bar
<class '__main__.Bar'>
>>> Foo.Baz.InnerBar
<class '__main__.InnerBar'>