有任何Python等价于分部类吗?

有任何Python等价于分部类吗?,python,partial-classes,Python,Partial Classes,使用“新”样式的类(我使用的是python 3.2)有没有办法将一个类拆分为多个文件?我有一个很大的类(从面向对象的设计角度来看,它应该是一个单独的类,考虑到耦合等等,但是为了便于编辑类,最好分割几个文件。我没有使用过它,但声称添加了对部分类的支持 似乎还有其他一些方法可以自己实现 您可以将类的各个部分实现为单独文件中的mixin,然后将它们全部导入到某个地方并对它们进行子类化 或者,您可以在某个地方实现类的每个方法,然后在一个中心文件中导入它们,并将它们指定为类的属性,以创建整个对象。如下所示

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

我没有使用过它,但声称添加了对部分类的支持

似乎还有其他一些方法可以自己实现

您可以将类的各个部分实现为单独文件中的mixin,然后将它们全部导入到某个地方并对它们进行子类化

或者,您可以在某个地方实现类的每个方法,然后在一个中心文件中导入它们,并将它们指定为类的属性,以创建整个对象。如下所示:

a、 py:

b、 py:

c、 py:

如果您真的愿意,您甚至可以自动执行此过程—循环使用模块
a
b
提供的所有函数,然后将它们作为属性添加到
C
上。尽管这可能太过分了


可能还有其他(可能更好)的方法,但这些是突然出现在脑海中的两种方法。

包含数百行的类定义确实“在野外”出现(我在流行的基于Python的开源框架中看到了一些),但我相信,如果您仔细考虑这些方法的作用,将有可能将大多数类的长度减少到可管理的程度。一些示例:

  • 寻找同一代码多次出现的地方。将该代码分解成它自己的方法,并在每个地方使用参数调用它
  • 不使用任何对象状态的“Private”方法可以作为独立函数带出类
  • 只有在特定条件下才应该调用的方法可能表示需要将这些方法放在子类中

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

首先,我想说的是,这种复杂的事情可能不是一个好主意,仅仅为了找到你的在课堂上放置更容易-最好添加评论、突出显示部分等。但是,我认为有两种方法可以做到这一点:

  • 将类写入多个文件中,然后将它们作为文本读入,将它们连接起来,并生成
    exec
    结果字符串

  • 在每个文件中创建一个单独的类,然后将它们作为mixin继承到一个主类中。但是,如果您已经在子类化另一个类,这可能会导致MRO问题。您可以通过为主类创建一个元类手动解决MRO来解决这一问题,但这可能会变得混乱


  • 最简单的方法是第一种选择。

    如果你的问题真的只是在编辑器中处理一个大类,那么我实际上要寻找的第一种解决方案是更好的解决问题的方法。第二种解决方案是更好的编辑器,最好是带有代码折叠的编辑器

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

  • 在文件夹中放置最终将构成您的类的各种
    .py
    文件。每个文件都应包含最终类的函数和变量定义,而不是类。在同一文件夹中的
    \uuuuuu init\uuuuuuuuuupy
    中编写以下内容将它们连接在一起

    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
    
    这样做的好处是,您最终得到了一个直接从
    对象
    派生的类,这在继承图中看起来很不错

  • 您可以使用多重继承来组合类的各个部分。在各个模块中,您可以使用类的各个部分为
    Bigclass
    编写一个类定义。然后在
    \uuuuu init\uuuuuuuuuuupy
    中编写:

    import classdef1, classdef2, classdef3
    
    class Bigclass(classdef1.Bigclass, classdef2.Bigclass, classdef3.Bigclass):
        num = 42   # add more members if desired
    
  • 如果多重继承成为一个问题,您可以使用单一继承:只需让每个类以链式方式从另一个类继承。假设您不在多个类中定义任何内容,顺序无关紧要。例如,
    classdef2.py
    将类似于:

    import classdef1
    class Bigclass(classdef1.Bigclass):
         # more member defs here
    
    classdef3
    将从
    classdef2
    导入
    Bigclass
    ,并添加到其中,依此类推。您的
    \uuuuuuu init\uuuuuuuuuuuuuuuuuuuuuuuuupy
    将只导入最后一个:

    from classdef42 import Bigclass
    
  • 我通常更喜欢#1,因为它更明确地说明了要从哪些文件导入哪些成员,但这些解决方案中的任何一个都可以为您工作


    要在这些场景中使用该类,您可以使用文件夹名作为模块名导入它:
    from bigclass import bigclass

    我以前也曾尝试过类似的方法。我的用例是抽象语法树中节点的类层次结构,然后我想将所有例如prettyprinting函数放在分离prettyprint.py文件,但仍将其作为类中的方法

    我尝试过的一件事是使用一个装饰器,将装饰过的函数作为指定类的一个属性。在我的例子中,这意味着prettyprint.py包含大量
    def prettyprint(self)
    都用不同的
    @inclass(…)

    这样做的一个问题是,必须确保始终导入子文件,并且子文件已被删除
    import classdef1, classdef2, classdef3
    
    class Bigclass(classdef1.Bigclass, classdef2.Bigclass, classdef3.Bigclass):
        num = 42   # add more members if desired
    
    import classdef1
    class Bigclass(classdef1.Bigclass):
         # more member defs here
    
    from classdef42 import Bigclass
    
    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)
    
    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