我试图找出一种干净的方法来为自定义类使用继承。我有以下目录结构。
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
答案 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
导入,那么它实际上取决于您希望在那里公开的内容。