4

我对编程很陌生,但仍在学习我的技巧。如果这个问题太初级,请道歉。

我觉得澄清我的问题有点困难,所以这里有一个我想要完成的示例:假设 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 中嵌套类的正确语法。

感谢您的帮助,对于这个基本问题,我深表歉意。

编辑:我的代码中有一些重要的拼写错误,我刚才已经更正了。对于任何不便,我深表歉意。

4

2 回答 2

3

嵌套类只是一个定义存在于另一个范围内的类。它们通常在 Python 中并不是那么有用。但是,可以做任何你想做的事情,并从多个类中派生出一个类的属性。两个主要方法是mixins/多重继承组合

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的属性,我们就让它继承自两者:。ABclass X(A, B)

  • 每个都__init__接受*args, **kwargs作为参数;我们的super()调用X将命名参数传递给 and 的初始化器AB因此我们需要它能够接受(然后忽略)其他初始化器的参数。也就是说,我们同时传递a和 ,bA.__init__只使用a

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

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

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)
    )
于 2012-05-22T06:24:56.843 回答
1

You're looking for inheritance.

Also, I notice that you are missing that python is case sensitive. This means that a and A are NOT the same variable

 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

Hope this helps

于 2012-05-22T05:10:43.320 回答