代码之家  ›  专栏  ›  技术社区  ›  Georg Schölly Crazy Developer

在嵌套类中使用super()。

  •  22
  • Georg Schölly Crazy Developer  · 技术社区  · 15 年前

    想象一下:

    class A(object):
        class B(object):
            def __init__(self):
                super(B, self).__init__()
    

    这会产生一个错误:

    NameError: global name B is not defined.
    

    我试过了 A.B 但是它说 A 未定义。

    更新:

    我发现了问题。

    我上过这样的课:

    class A(object):
        class B(object):
            def __init__(self):
                super(B, self).__init__()
    
        someattribute = B()
    

    在这个范围内,还没有定义。

    3 回复  |  直到 15 年前
        1
  •  17
  •   Douglas Mayle    15 年前

    我不知道为什么A.B不适合你,因为它应该……以下是一些有效的shell输出:

    >>> class A(object):
    ...   class B(object):
    ...     def __init__(self):
    ...       super(A.B, self).__init__()
    ...   def getB(self):
    ...     return A.B()
    ... 
    >>> A().getB()
    <__main__.B object at 0x100496410>
    
        2
  •  5
  •   Cory Petosky    15 年前

    因为B可能永远不会被扩展,这应该是有效的:

    class A(object):
        class B(object):
            def __init__(self):
                super(self.__class__, self).__init__()
    
        3
  •  2
  •   Edward Loper    15 年前

    如果类A.B不太可能参与任何多重继承,那么最好对构造函数调用进行硬编码:

    class A(object):
        class B(object):
            def __init__(self):
                object.__init__(self)
    

    但是,如果您确实需要拥有super的全部功能,那么您可以通过定义一个自定义描述符来获得您想要的,该描述符将延迟初始化b属性:

    class LazyAttribute(object):
        def __init__(self, func, *args, **kwargs):
            self._func = func
            self._args = args
            self._kwargs = kwargs
            self._value = None
    
        def __get__(self, obj, type=None):
            if self._value is None:
                print 'created', self._value
                self._value = self._func(*self._args, **self._kwargs)
            return self._value
    
    class A(object):
        class B(object):
            def __init__(self):
                super(A.B, self).__init__()
    
        someattribute = LazyAttribute(B)
    

    这将导致B属性在第一次被访问时被实例化,然后在此后重新使用:

    >>> print A.someattribute
    created <__main__.B object at 0x00AA8E70>
    <__main__.B object at 0x00AA8E90>
    >>> print A().someattribute
    <__main__.B object at 0x00AA8E90>
    

    有关描述符的详细信息,请参见: http://users.rcn.com/python/download/Descriptor.htm