是否有任何Python等效于部分类?

Mat*_*und 37 python partial-classes

使用"新"样式类(我在python 3.2中)有没有办法将类分割为多个文件?我有一个很大的类(从面向对象的设计角度来看,它应该是一个单独的类,考虑耦合等,但是为了便于编辑类,分割几个文件会很好.

kin*_*all 40

如果您的问题确实只是在编辑器中使用大型类,那么我实际寻找的第一个解决方案是解决问题的更好方法.第二种解决方案是更好的编辑器,最好是具有代码折叠的编辑器.

也就是说,有几种方法可以将一个类分解为多个文件.Python允许您通过放置一个文件夹作为模块__init__.py,然后可以从其他文件导入文件.我们将在每个解决方案中使用此功能.首先创建一个名为的文件夹bigclass.

  1. 在文件夹中放入.py最终将构成您的类的各种文件.每个应包含最终类的函数和变量定义,而不是类.在__init__.py同一文件夹中写下以下内容将它们连接在一起.

    class Bigclass(object):
    
        from classdef1 import foo, bar, baz, quux
        from classdef2 import thing1, thing2
        from classdef3 import magic, moremagic
        # unfortunately, "from classdefn import *" is an error or warning
    
        num = 42   # add more members here if you like
    
    Run Code Online (Sandbox Code Playgroud)

    这样做的好处是最终会得到一个直接派生的单个类object,这在继承图中会很好看.

  2. 您可以使用多重继承来组合类的各个部分.在您的单个模块中,您将为类的一部分编写类定义Bigclass.然后在你的__init__.py写作:

    import classdef1, classdef2, classdef3
    
    class Bigclass(classdef1.Bigclass, classdef2.Bigclass, classdef3.Bigclass):
        num = 42   # add more members if desired
    
    Run Code Online (Sandbox Code Playgroud)
  3. 如果多重继承成为问题,您可以使用单继承:只需让每个类以链方式从另一个继承.假设您没有在多个类中定义任何内容,则顺序无关紧要.例如,classdef2.py就像:

    import classdef1
    class Bigclass(classdef1.Bigclass):
         # more member defs here
    
    Run Code Online (Sandbox Code Playgroud)

    classdef3将导入Bigclassclassdef2和添加到它,等等.你__init__.py只需导入最后一个:

    from classdef42 import Bigclass
    
    Run Code Online (Sandbox Code Playgroud)

我通常更喜欢#1,因为它更明确地指出您从哪些文件导入的成员,但这些解决方案中的任何一个都可以为您服务.

要在任何这些方案中使用该类,您只需使用文件夹名称作为模块名称即可导入它: from bigclass import Bigclass


wbe*_*rry 7

包含数百行的类定义确实"在野外"出现(我在流行的基于Python的开源框架中看到了一些),但我相信如果你仔细思考这些方法在做什么,就可以减少长度大多数课程都是可管理的.一些例子:

  • 寻找多次出现相同代码的地方.将该代码分解为自己的方法,并使用参数从每个地方调用它.
  • 不使用任何对象状态的"私有"方法可以作为独立函数从类中引出.
  • 仅在某些条件下调用的方法可能表明需要将这些方法放在子类中.

要直接解决您的问题,可以拆分类的定义.一种方法是通过定义类,然后将外部函数作为方法添加到类中来"修补"类.另一种方法是使用内置type函数"手动"创建类,在字典中提供其名称,任何基类及其方法和属性.但我不建议这样做只是因为定义会很长.在我看来,这种治疗方法比疾病更糟糕.


And*_*org 6

我之前玩弄过类似的东西.我的用例是抽象语法树中的节点的类层次结构,然后我想将所有例如prettyprinting函数放在一个单独的prettyprint.py文件中,但仍然将它们作为类中的方法.

我尝试过的一件事是使用装饰器将装饰函数作为属性放在指定的类上.在我的情况下,这意味着prettyprint.py包含许多def prettyprint(self)装饰不同的@inclass(...)

这样做的一个问题是必须确保子文件总是被导入,并且它们依赖于主类,这会产生循环依赖,这可能是混乱的.

def inclass(kls):
    """
    Decorator that adds the decorated function
    as a method in specified class
    """
    def _(func):
        setattr(kls,func.__name__, func)
        return func
    return _

## exampe usage
class C:
    def __init__(self, d):
        self.d = d

# this would be in a separate file.
@inclass(C)
def meth(self, a):
    """Some method"""
    print "attribute: %s - argument: %s" % (self.d, a)

i = C(10)
print i.meth.__doc__
i.meth(20)
Run Code Online (Sandbox Code Playgroud)


Cip*_*rta 6

您可以使用如下装饰器来做到这一点:

class Car(object):

    def start(self):
    print 'Car has started'


def extends(klass):
    def decorator(func):
      setattr(klass, func.__name__, func)
      return func
    return decorator

#this can go in a different module/file
@extends(Car)
def do_start(self):
    self.start()


#so can this
car = Car()
car.do_start()

#=> Car has started
Run Code Online (Sandbox Code Playgroud)

  • 非常有趣的方法!我只想指出,代码完成可能不适用于“do_start()”。尽管如此,我喜欢这个解决方案。:) (2认同)