pythonic方式来定制类

时间:2015-01-12 23:16:45

标签: python python-2.7

我试图找出一种干净的方法来为自定义类使用继承。我有以下目录结构。

inheritTest.py
Level1
    __init__.py
    t_Generic.py
Level2
    __init__.py
    t_Custom.py

目标:我希望通过导入t_Custom模块来访问t_Generic的所有类,并允许在t_Custom中进行所需的自定义。

上面的两个 init .py文件中没有任何内容。

t_Generic.py包含一些类似的通用类:

class A(object):
    def __init__(self):
        self.hello = "Hello! I am Mr.A from t_generic"
    def someOtherMethod(self):
        pass

class B(object):
    def __init__(self):
        self.hello = "Hello! I am Mr.B from t_generic"
    def someOtherMethod(self):
        pass

class C(object):
    def __init__(self):
        self.hello = "Hello! I am Mr.C from t_generic"
    def changeHello(self):
        pass

实验t_Custom.py如下:

import Level1.t_Generic

#Override any Generic classes in this module.

#Option 1: Let's get Generic A so it lives in this scope as A
from Level1.t_Generic import A

#Option 2: Let's create B and inherit from Generic, make future custom changes here
class B(Level1.t_Generic.B):
    def __init__(self):
        super(B,self).__init__()


#I really want to inherit from C and change it's behavior
class C(Level1.t_Generic.C):
    def __init__(self):
        super(C,self).__init__()
    def changeHello(self):
        self.hello = "Hello! I am Mr.C modified in t_Custom"

问题:这样做的pythonic方法是什么?我应该像在选项1中那样导入Custom模块中的所有泛型类,还是应该在Option中创建一个继承的类,如同在Option 2中一样,并修改我想要继承的类?

inheritTest.py中的用例示例:

import Level2.t_Custom

a = Level2.t_Custom.A()
b = Level2.t_Custom.B()
c = Level2.t_Custom.C()

print a.hello
print b.hello
print c.hello
c.changeHello()
print c.hello

输出:

Hello! I am Mr.A from t_generic
Hello! I am Mr.B from t_generic
Hello! I am Mr.C from t_generic
Hello! I am Mr.C modified in t_Custom

2 个答案:

答案 0 :(得分:2)

我没有测试过这个,但我认为它应该做你想要的。考虑一下白板代码

首先,您需要在t_Custom.py中使用相对导入,然后导入泛型类

from ..Level1 import t_Generic
from t_Generic import A as GenericA
from t_Generic import B as GenericB
from t_Generic import C as GenericC

我重命名这些类以避免模块命名空间中的任何冲突。

现在,要在t_Custom.py(复制原始代码)中获得所需的输出

A = GenericA # Just re-export the generic A class

class B(GenericB):
    def __init__(self):
        super(B,self).__init__()

#I really want to inherit from C and change it's behavior
class C(GenericC):
    def __init__(self):
        super(C,self).__init__()
    def changeHello(self):
        self.hello = "Hello! I am Mr.C modified in t_Custom"

然后,尝试避免从模块中导出t_Generic.A等

__all__ = ["A","B","C"]

正如亚历克斯在他的评论中提到的,它通常被认为是“坏事”(TM)无意义地覆盖基类的方法。只有在您想要修改或添加行为时才这样做。然后t_Custom.py变得更像这样:

from ..Level1 import t_Generic
from t_Generic import A as GenericA
from t_Generic import B as GenericB
from t_Generic import C as GenericC

A = GenericA # Just re-export the generic A class
B = GenericB # I'll subclass when I know what I want to do to it

#I really want to inherit from C and change it's behavior
class C(GenericC):
    def changeHello(self):
        self.hello = "Hello! I am Mr.C modified in t_Custom"

__all__ = ["A","B","C"]

答案 1 :(得分:0)

此问题的答案取决于Level2.t_Custom范围内您想要的课程数量。通常,最好只将对象导入到您实际要使用的模块范围内。这使得范围保持整洁有序。

但是如果该模块打算在别处使用,则可能需要将Level1.t_Generic中的所有对象导入范围并添加自定义类。例如,如果其他人(或您自己)只从Level2.t_Custom导入,那么它实际上取决于您希望在那里公开的内容。