关于python:在很多类上定义相同的方法覆盖:DRY?

Defining same method override on lots of classes: DRY?

假设我有大量由大型库代码库的import定义的类,出于可维护性的原因,我不想随意使用这些类。它们都继承自baseclass,baseclass包含一个我想要扩充的方法。我认为以下是可行的解决方案

1
2
3
4
5
6
7
8
9
10
11
class MyMixin(object):
   def method( self, args):  
      ... # 1. a few lines of code copied from BaseClass's def of method
      ... # 2. some lines of my code that can't go before or after the copied code
      ... # 3. and the rest of the copied code

class MyAbcClass( MyMixin, AbcClass):
   pass
# many similar lines
class MyZzzClass( MyMixin, ZzzClass):
   pass

问题。比如说,有没有一种方法可以获取("MyXxxClass", XxxClass)元组的列表,并编写定义myxxxclasses的代码?它是否足以理解它胜过上述的重复?


使用三个arg type定义类,然后在模块的全局字典中设置它们:

1
2
3
todefine = [('MyAbcClass', AbcClass), ...]
for name, base in todefine:
    globals()[name] = type(name, (MyMixin, base), {})

如果要定义的名称遵循您给定的固定模式(`"my"+基类名称),则可以通过动态构造要定义的名称来减少重复:

1
2
3
4
todefine = [AbcClass, ...]
for base in todefine:
    name ="My" + base.__name__
    globals()[name] = type(name, (MyMixin, base), {})

如果您试图包装给定模块中的所有类,甚至可以通过自省模块以编程方式生成todefine,避免显式列出这些类(如果您知道模块有或没有__all__,您可以使用适当的方法,而不是尝试其中一种方法并默认另一种方法):

1
2
3
4
5
6
7
8
9
10
11
import inspect
try:
    # For modules that define __all__, we want all exported classes
    # even if they weren't originally defined in the module
    todefine = filter(inspect.isclass, (getattr(somemodule, name) for name in somemodule.__all__))
except AttributeError:
    # If __all__ not defined, heuristic approach; exclude private names
    # defined with leading underscore, and objects that were imported from
    # other modules (so if the module does from itertools import chain,
    # we don't wrap chain)
    todefine = (obj for name, obj in vars(somemodule).items() if not name.startswith('_') and inspect.isclass(obj) and inspect.getmodule(obj) is somemodule)