Python中嵌套类的正确语法?

2024-04-19 05:50:36 发布

您现在位置:Python中文网/ 问答频道 /正文

我对编程还是个新手,还在学习我的诀窍。如果这个问题太简单,请道歉。在

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

 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中嵌套类的正确语法。在

谢谢你的帮助,我为这个基本问题道歉。在

编辑:我的代码中有一些关键的错误,我刚才已经纠正了。给您带来不便,我深表歉意。在


Tags: nameselfa2initdefa1语法b2
2条回答

你在寻找遗产。在

另外,我注意到您忽略了python是区分大小写的。这意味着a和{}不是同一个变量

 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

希望这有帮助

嵌套类只是一个定义存在于另一个范围内的类。它们在Python中通常没有那么有用。然而,您可以随心所欲地从多个类的属性中派生出一个类的属性;两个主要方法是mixins/multiple inheritancecomposition。在

混合方法如下:

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作为参数;我们在X中的super()调用将命名参数传递给AB的初始化者,因此我们需要它能够接受(然后忽略)其他初始化器的参数。也就是说,我们将ab都传递到A.__init__中,但只使用a

  • 仔细阅读super()对于理解Python的继承是必不可少的。

但是,多重继承可能很难管理过去的简单示例,因此通常建议您使用组合

^{pr2}$

您可以看到这消除了对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知道A和{}除了它们的接口之外的任何信息。这使得封装更容易:如果合适的话,现在可以将A和{}粘贴到它们自己的模块中。为了方便起见,您还可以使用工厂函数:

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

相关问题 更多 >