2016-09-28 29 views
1

我在Python中有一个简单的mixin结构。代码应该是自我解释:如何改进Python中的mixin结构?

class Base: 
    def __init__(self): 
     pass 

class MixinA: 
    def __init__(self): 
     self.x = 0 
     self.y = 1 
    def a(self): 
     print('A: x = ' + str(self.x) + ', y = ' + str(self.y)) 

class MixinB: 
    def __init__(self): 
     self.x = 2 
     self.z = 3 
    def b(self): 
     print('B: x = ' + str(self.x) + ', z = ' + str(self.z)) 

class MyFirstMix(MixinA, MixinB, Base): 
    def __init__(self): 
     Base.__init__(self) 
     MixinB.__init__(self) 
     MixinA.__init__(self) 

class MySecondMix(MixinA, Base): 
    def __init__(self): 
     Base.__init__(self) 
     MixinA.__init__(self) 

我想改善这一点,所以这导致了3个问题/问题:

  1. MixinAMixinB都有一个成员x。有没有办法确定,每个班级只能看到自己的x据我所知:不,不是。
  2. 为混合类中的每个mixin调用构造函数有点麻烦。有没有办法自动调用所有的构造函数或做一些具有相同效果的东西?
  3. 有没有一种方法可以动态地混入一些内联的东西,而不需要明确地创建一个类?我正在寻找一个语法,如:mix = Base() with MixinA

如果我的建议结构是完全错误的,我也打开其他建议如何处理mixin。

+0

[在Python中阻止函数重写](http://stackoverflow.com/questions/3948873/prevent-function-overriding-in-python)可能的重复。您可以使用此处提及的类似技术来防止重写实例属性。 –

+0

@NoctisSkytower:那么,问题2和3的含义是什么? – Michael

+0

那些可能并可能应该作为单独的问题发布。 –

回答

0

当您的继承方案开始受到这些问题的困扰时,应该考虑使用名为组合的技术来代替。关于主题here的可读介绍。 Wikipedia example的可访问性稍差,但如果可以处理其他编程语言,也很有用。 This StackExchange question也提供有用的讨论。

在最简单的,而不是一类从SomeParent继承和在Mixin类混合,你不是有SomeParent实例各创建Mixin一个实例,并用它来访问mixin类的功能。

0

对于Python类固有的,我相信有一些你需要知道的技巧:

  1. 类在python2和python3有很大的不同。 Python2支持旧式类,但python3仅支持新式类。简单地说:在python3中,即使你没有明确地使用它,类也总是固有于基类object。检查Difference-between-Old-New-Class

  2. 方法解析顺序(MRO)。这决定派生类如何搜索固有成员和函数。见MRO

  3. super功能。结合MRO,您可以轻松调用父成员或函数,而无需明确知道父类的名称。见Super

现在来找你的问题:

  1. MixinA和MixinB都有一个成员x。有没有办法确定,每个班级只能看到自己的x?

我不放弃理解你的意思。当你引用一个类的成员时,你必须通过它的实例或类来引用它。所以instance_of_MixinA.xinstance_of_MixinB.x是分开的。如果你正在谈论类MyFirstMix(MixinA, MixinB, Base),这取决于如何调用__init__函数。在您的代码中,您首先通过MixinB填充x,然后将其值重置为MixinA

  1. 调用混合类中每个mixin的构造函数有点麻烦。有没有办法自动调用所有的构造函数或做一些具有相同效果的东西。

您的称谓使它不可能。你必须调用所有的构造函数。

  1. 有没有一种方法可以动态混入一些内联的东西,而不需要显式地创建一个类?

我不确定。但我可以给你一些建议:尽量外__init__成员时,高清类(python3,如果使用python2照顾super):

class Base: 
    def __init__(self): 
     pass 


class MixinA: 
    x = 0 
    y = 1 


class MixinB: 
    x = 2 
    z = 3 

    def b(self): 
     print('B: x = ' + str(self.x) + ', z = ' + str(self.z)) 


class MyFirstMix(MixinA, MixinB, Base): 
    def __init__(self): 
     super().__init__() 


class MySecondMix(MixinA, Base): 
    def __init__(self): 
     super().__init__() 

__init__的行为变量,从内部变量退出不同:外变量属于类,并且将为此类的所有实例填充,而内部变量仅属于实例(在定义类时由self引用),并且只有在调用__init__时才会填充。这就是为什么你不能使用super来调用所有的构造函数--- super只能称为优先级父项__init__。见variables-outsite-inside-init

这是一个很好的解决Mixin类。在以上代码中,MyFirstMix内部人员MixinAMixinB其成员均为班级成员(__init__以外)。因此MyFirstMix的实例将固有所有类别成员MixinAMixinB而不呼叫__init__。这里的MixinAMixinB自己的同类成员x,但MRO确定当MyFirstMix的实例参考x,应该从MixinA返回。

希望这会有所帮助。谢谢!