我正在尝试基于抽象基类定义许多类。这些类中的每一个基本上都为可视化包定义了一个单元格形状。单元由许多顶点(点)组成,每个子类将需要不同数量的点。每个类都可以被认为是固定数量的点坐标的容器。
例如,考虑基类Shape
,它只是一个坐标列表的容器:
class Shape(object):
"""Cell shape base class."""
def __init__(self, sequence):
self.points = sequence
@property
def points(self):
return self._points
@points.setter
def points(self, sequence):
# Error checking goes here, e.g. check that `sequence` is a
# sequence of numeric values.
self._points = sequence
理想情况下,我希望能够定义一个Square
类,其中points.setter
方法检查sequence
的长度为 4。此外,我希望用户无法实例化Shape
. 有没有办法可以定义Shape
为抽象基类?我尝试将形状的定义更改为以下内容:
import abc
class Shape(object):
"""Cell shape base class."""
__metaclass__ = abc.ABCMeta
def __init__(self, sequence):
self.points = sequence
@abc.abstractproperty
def npoints(self):
pass
@property
def points(self):
return self._points
@points.setter
def points(self, sequence):
# Error checking goes here...
if len(sequence) != self.npoints:
raise TypeError('Some descriptive error message!')
self._points = sequence
这需要子类来定义属性npoints
。然后我可以将一个类定义Square
为
class Square(Shape):
@property
def npoints(self):
return 4
但是,对于大量子类(并且要实现多个属性),这将是相当乏味的。我希望定义一个类工厂来为我创建我的子类,类似于:
def Factory(name, npoints):
return type(name, (Shape,), dict(npoints=npoints))
Triangle = Factory('Triangle', 3)
Square = Factory('Square', 4)
# etc...
这个类工厂函数是一种有效的方法,还是我破坏了这个npoints
属性?将调用替换为type
更详细的内容是否更好,例如:
def Factory(name, _npoints):
class cls(Shape):
@property
def npoints(self):
return _npoints
cls.__name__ = name
return cls
另一种方法是定义一个类属性_NPOINTS
并将npoints
属性更改Shape
为
@property
def npoints(self):
return _NPOINTS
但是,我失去了使用抽象基类的好处,因为:
- 我看不到如何使用
type
, 和 - 我不知道如何定义抽象类属性。
有没有人对实现这个抽象基类和类工厂函数的最佳方式有任何想法,甚至是一个更好的设计?