代码之家  ›  专栏  ›  技术社区  ›  nigel222

在许多类上定义相同的方法重写:DRY?

  •  2
  • nigel222  · 技术社区  · 10 年前

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

    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的代码?它是否足够容易理解,能够击败上面的重复?

    1 回复  |  直到 10 年前
        1
  •  1
  •   ShadowRanger    10 年前

    使用三个参数 type 定义类,然后将它们设置为 the module's global dictionary :

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

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

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

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

    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)