pythonic 自定义方式 类

pythonic way to customize classes

我正在尝试寻找一种简洁的方法来为自定义 classes 使用继承。我有以下目录结构。

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

目标: 我希望通过导入 t_Custom 模块访问 t_Generic 的所有 classes,并允许在 [=42] 中进行必要的自定义=].

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

t_Generic.py 包含一些通用的 class,例如:

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 那样在自定义模块中导入所有通用 class 还是应该像选项 2 那样在自定义模块中创建一个继承的 class 并修改我想继承的那些?

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

这个问题的答案取决于你想要Level2.t_Custom范围内的类个数。一般来说,最好只将对象导入到您实际要使用的模块范围内。这使示波器保持整洁有序。

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

我还没有对此进行测试,但我认为它应该可以满足您的需求。考虑一下白板代码

首先,您需要在 t_Custom.py 中使用相对导入,然后导入通用 classes

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

我重命名了 classes 以避免模块命名空间中的任何冲突。

现在,要获得您想要的输出,请在 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"]

正如 Alex 在他的评论中提到的,通常认为 "Bad Thing" (TM) 毫无意义地重写基 class 的方法。仅当您想要修改或添加行为时才这样做。那么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"]