Python:相互依赖的类
我试图创建一组类,其中每个类都有相应的类的“数组”版本。但是,我需要两个类相互了解。下面是一个工作示例来演示我正在尝试做的事情。但这需要在每个类中复制一个“to_数组”。在我的实际示例中,还有其他更复杂的方法需要复制,即使唯一的区别是“BaseArray”、“PointArray”或“LineArray”。BaseArray类的方法类似地只有“BaseObj”、“PointObj”或“LineObj”不同 这是我的尝试,它引起了一个错误,这是可以理解的。我知道为什么会出现名称错误,因此我理解为什么这不起作用。我展示这个是为了明确我想做什么Python:相互依赖的类,python,python-2.7,inheritance,Python,Python 2.7,Inheritance,我试图创建一组类,其中每个类都有相应的类的“数组”版本。但是,我需要两个类相互了解。下面是一个工作示例来演示我正在尝试做的事情。但这需要在每个类中复制一个“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
设置为泛型。尽管如此,这样分配类属性感觉很不自然,因为直到文件后面的某个地方才完全定义类。直到这个赋值发生,这个类才真正完成,如果添加了新的类型,这也很容易忘记。谢谢你的输入。实际用例确实需要“数组”类型对其包含的每种类型的对象都是唯一的,并且它们有许多方法只适用于这些类型本身。