Python:相互依赖的类

Python:相互依赖的类,python,python-2.7,inheritance,Python,Python 2.7,Inheritance,我试图创建一组类,其中每个类都有相应的类的“数组”版本。但是,我需要两个类相互了解。下面是一个工作示例来演示我正在尝试做的事情。但这需要在每个类中复制一个“to_数组”。在我的实际示例中,还有其他更复杂的方法需要复制,即使唯一的区别是“BaseArray”、“PointArray”或“LineArray”。BaseArray类的方法类似地只有“BaseObj”、“PointObj”或“LineObj”不同 这是我的尝试,它引起了一个错误,这是可以理解的。我知道为什么会出现名称错误,因此我理解为什

我试图创建一组类,其中每个类都有相应的类的“数组”版本。但是,我需要两个类相互了解。下面是一个工作示例来演示我正在尝试做的事情。但这需要在每个类中复制一个“to_数组”。在我的实际示例中,还有其他更复杂的方法需要复制,即使唯一的区别是“BaseArray”、“PointArray”或“LineArray”。BaseArray类的方法类似地只有“BaseObj”、“PointObj”或“LineObj”不同

这是我的尝试,它引起了一个错误,这是可以理解的。我知道为什么会出现名称错误,因此我理解为什么这不起作用。我展示这个是为了明确我想做什么

# ------------------
# Base object types
# ------------------
class BaseObj(object):
    ArrayClass = BaseArray
    def __init__(self, obj):
        self.obj = obj
    def to_array(self):
        # By using the "ArrayClass" class attribute here, I can have a single
        # "to_array" function on this base class without needing to
        # re-implement this function on each subclass
        return self.ArrayClass([self])
    # In the actual application, there would be other BaseObj methods that
    # would use self.ArrayClass to avoid code duplication

class Point(BaseObj):
    ArrayClass = PointArray

class Line(BaseObj):
    ArrayClass = LineArray

# ------------------
# Array object types
# ------------------
class BaseArray(object):
    BaseType = BaseObj
    def __init__(self, items):
        self.items = [self.BaseType(i) for i in items]
    # In the actual application, there would be other BaseArray methods that
    # would use self.BaseType to avoid code duplication

class PointArray(BaseArray):
    BaseType = Point

class LineArray(BaseArray):
    BaseType = Line

# ------------------
# Testing....
# ------------------

p = Point([1])
print(p)
pa = p.to_array()
print(pa)
print(pa.items)
一种可能的解决方案是只将所有类的“ArrayClass”定义为None,然后在定义了“array”版本之后,您可以像下面这样对原始类进行修补:

BaseObj.ArrayClass = BaseArray
Point.ArrayClass = PointArray
Line.ArrayClass = LineArray

这是可行的,但感觉有点不自然,我怀疑有更好的方法来实现这一点。如果有必要的话,我的用例将最终成为一个(不幸的)仍然使用Python2.7的程序的插件,因此我需要一个使用Python2.7的解决方案。理想情况下,相同的解决方案可以在2.7和3+版本中工作。

这里是一个使用装饰器的解决方案。我更喜欢这种方式,而不是类属性赋值(“monkey patch”,我称之为“monkey patch”),因为它使事情更加自洽和清晰。我对此很满意,但仍然对其他想法感兴趣

# ------------------
# Base object types
# ------------------
class BaseObj(object):
    ArrayClass = None
    def __init__(self, obj):
        self.obj = obj
    def to_array(self):
        # By using the "ArrayClass" class attribute here, I can have a single
        # "to_array" function on this base class without needing to
        # re-implement this function on each subclass
        return self.ArrayClass([self])
    # In the actual application, there would be other BaseObj methods that
    # would use self.ArrayClass to avoid code duplication

    @classmethod
    def register_array(cls):
        def decorator(subclass):
          cls.ArrayClass = subclass
          subclass.BaseType = cls
          return subclass
        return decorator

class Point(BaseObj):
    pass

class Line(BaseObj):
    pass

# ------------------
# Array object types
# ------------------
class BaseArray(object):
    BaseType = None
    def __init__(self, items):
        self.items = [self.BaseType(i) for i in items]
    # In the actual application, there would be other BaseArray methods that
    # would use self.BaseType to avoid code duplication

@Point.register_array()
class PointArray(BaseArray):
    pass

@Line.register_array()
class LineArray(BaseArray):
    pass

# ------------------
# Testing....
# ------------------

p = Point([1])
print(p)
pa = p.to_array()
print(pa)
print(pa.items)

下面是一个使用装饰器的解决方案。我更喜欢这种方式,而不是类属性赋值(“monkey patch”,我称之为“monkey patch”),因为它使事情更加自洽和清晰。我对此很满意,但仍然对其他想法感兴趣

# ------------------
# Base object types
# ------------------
class BaseObj(object):
    ArrayClass = None
    def __init__(self, obj):
        self.obj = obj
    def to_array(self):
        # By using the "ArrayClass" class attribute here, I can have a single
        # "to_array" function on this base class without needing to
        # re-implement this function on each subclass
        return self.ArrayClass([self])
    # In the actual application, there would be other BaseObj methods that
    # would use self.ArrayClass to avoid code duplication

    @classmethod
    def register_array(cls):
        def decorator(subclass):
          cls.ArrayClass = subclass
          subclass.BaseType = cls
          return subclass
        return decorator

class Point(BaseObj):
    pass

class Line(BaseObj):
    pass

# ------------------
# Array object types
# ------------------
class BaseArray(object):
    BaseType = None
    def __init__(self, items):
        self.items = [self.BaseType(i) for i in items]
    # In the actual application, there would be other BaseArray methods that
    # would use self.BaseType to avoid code duplication

@Point.register_array()
class PointArray(BaseArray):
    pass

@Line.register_array()
class LineArray(BaseArray):
    pass

# ------------------
# Testing....
# ------------------

p = Point([1])
print(p)
pa = p.to_array()
print(pa)
print(pa.items)

这不是真正的猴子补丁,这只是将属性分配给类的一种正常方式。除了该属性之外,
BaseArray
的不同子类是否真的做了不同的事情?因为这样定义一些通用容器对我来说更有意义,比如
BaseArray
(array不是一个好名字,但无论如何)让我们把它叫做
class-array(object)
,然后在
array中。那么,为什么要继承而不是组合呢?那么在
BaseObject
中,您可以为所有子类定义
to\u array
,只需ass
返回数组(type(self),[self])
。一般来说,我非常怀疑不必要的类型层次结构。Python是一种duck类型的语言,即使您使用注释和第三方静态类型检查器,您也可以将
Array
设置为泛型。尽管如此,这样分配类属性感觉很不自然,因为直到文件后面的某个地方才完全定义类。直到这个赋值发生,这个类才真正完成,如果添加了新的类型,这也很容易忘记。谢谢你的输入。实际用例确实需要“数组”类型对它包含的每种类型的对象都是唯一的,并且它们有许多方法只适用于这些类型本身。这不是真正的猴子补丁,这只是将属性分配给类的一种正常方式。除了该属性之外,
BaseArray
的不同子类是否真的做了不同的事情?因为这样定义一些通用容器对我来说更有意义,比如
BaseArray
(array不是一个好名字,但无论如何)让我们把它叫做
class-array(object)
,然后在
array中。那么,为什么要继承而不是组合呢?那么在
BaseObject
中,您可以为所有子类定义
to\u array
,只需ass
返回数组(type(self),[self])
。一般来说,我非常怀疑不必要的类型层次结构。Python是一种duck类型的语言,即使您使用注释和第三方静态类型检查器,您也可以将
Array
设置为泛型。尽管如此,这样分配类属性感觉很不自然,因为直到文件后面的某个地方才完全定义类。直到这个赋值发生,这个类才真正完成,如果添加了新的类型,这也很容易忘记。谢谢你的输入。实际用例确实需要“数组”类型对其包含的每种类型的对象都是唯一的,并且它们有许多方法只适用于这些类型本身。