Python中嵌套类的正确语法?

时间:2012-05-22 05:07:11

标签: python class

我对编程很新,还在学习我的绳索。如果这个问题过于简单,请道歉。

我觉得澄清我的问题有点困难,所以这里是我想要完成的一个例子:假设a是X类的一个实例,并且应该具有属性a1,a2,a3,b1,b2, b3,c1,c2和c3。我想将a1到a3,b1到b3和c1到c3放到它们自己的嵌套在X下的类A,B,C中以便于使用。这样做的正确语法是什么?

 class X:
    def __init__ (self, name, A, B, C):
        self.name = name
        self.A = A
        self.B = B
        self.C = C
    class A (X):
       def _init_ (self, name, a1, a2, a3):
           self.name = name
           self.a1 = a1
           self.a2 = a2
           self.a3 = a3
    class B (x):
       def _init_ (self, name, b1, b2, b3):
           self.name = name
           self.b1 = a1
           self.b2 = a2
           self.b3 = a3
    class C (X):
       def _init_ (self, name, c1, c2, c3):
           self.name = name
           self.c1 = a1
           self.c2 = a2
           self.c3 = a3

由于这完全是基于猜测而构建的,我99.9%肯定这是错的,但我不确定接下来我应该做些什么来做对。我试过搜索“嵌套类”的答案,但我找到的答案并没有真正澄清我的立场。

请在Python中解释嵌套类的正确语法。

感谢您的帮助,以及对此基本问题的道歉。

编辑:我的代码中有一些重要的拼写错误我刚刚纠正过。对于给您带来的任何不便,我深表歉意。

2 个答案:

答案 0 :(得分:2)

嵌套类只是其定义存在于另一个范围内的类。它们通常在Python中并不是那么有用。但是,它可以做你想要的,并从许多类中获得一个类的属性;两个主要方法是 mixins / multiple inheritance composition

mixin方法是这样的:

class A(object):
    def __init__(self, a=None, *args, **kwargs):
        self.a = a
        super(A, self).__init__(*args, **kwargs)

class B(object):
    def __init__(self, b=None, *args, **kwargs):
        self.b = b
        super(B, self).__init__(*args, **kwargs)

class X(A, B):
    def __init__(self, *args, **kwargs):
        super(X, self).__init__(*args, **kwargs)

x = X(a='foo', b='bar')
print x.a, x.b
  • 由于X要具有AB的属性,我们会继承它们:class X(A, B)

  • 每个__init__接受*args, **kwargs作为参数;我们在super()中的X电话会将命名参数传递给AB的初始化者,因此我们需要它能够接受(然后忽略)<的参数em>其他初始化者。也就是说,我们将ab都传递到A.__init__,但只使用a

  • 阅读super()对理解Python的继承至关重要。

但是,多次继承可能很难通过简单的示例进行管理,因此通常建议您改为使用 composition

class A(object):
    def __init__(self, a):
        self.a = a

class B(object):
    def __init__(self, b):
        self.b = b

class X(object):
    def __init__(self, a, b):
        self.A = A(a)
        self.B = B(b)

x = X('foo', 'bar')
print x.A.a, x.B.b

您可以看到这消除了super()调用的需要以及初始化器上的任何特殊参数处理,使其更加清晰。这里我们采用两个参数,然后在内部构造相关的类并将它们附加到X实例。这使得属性查找更加尴尬,但有一些方法可以简化:

class X(object):
    # <etc>
    @property
    def a(self):
        return self.A.a

也可以覆盖__getattr__并进行一些动态查找,而不是手动编码每个属性。

class X(object):
    # <etc>
    def __getattr__(self, item):
        for component in (getattr(self, c) for c in ['A', 'B']):
            if hasattr(component, item):
                return getattr(component, item)

另一个选择是自己传递组合实例:

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

x = X(A('foo'), B('bar'))
print x.A.a, x.B.b

这消除了X除了接口之外对AB一无所知的任何需求。这使封装更容易:如果合适,您现在可以将AB粘贴到自己的模块中。为方便起见,您还可以使用工厂功能:

def make_X(a, b):
    return X(
        A(a), 
        B(b)
    )

答案 1 :(得分:1)

你正在寻找继承。

另外,我注意到你错过了python是区分大小写的。这意味着aA不是同一个变量

 class X:
    def __init__ (self, name, a, b, c):
        self.name = name
        self.a = a

class A (X):
   def _init_ (self, name, a1, a2, a3):
       self.name = name
       self.a1 = a1
       self.a2 = a2
       self.a3 = a3

class B (A):
   def _init_ (self, name, a1, a2, a3):
       self.name = name
       self.b1 = a1
       self.b2 = a2
       self.b3 = a3

class C (A):
   def _init_ (self, name, a1, a2, a3):
       self.name = name
       self.c1 = a1
       self.c2 = a2
       self.c3 = a3

希望这有帮助