我想有某些属性&方法仅在参数满足某些条件时在类实例中可用。不同的情况并不是相互排斥的。我已经有了一个可行的解决方案(包括shadowwranger的建议):
class polygon():
def __new__(cls, vert, axis=None):
triangle = vert == 3
solidrev = axis is not None
if triangle and not solidrev:
return super().__new__(_triangle)
elif solidrev and not triangle:
return super().__new__(_solid)
elif solidrev and triangle:
return super().__new__(_triangle_solid)
else:
return super().__new__(cls)
def __init__(self, vert, axis=None):
self.polygon_attribute = 1
def polygon_method(self):
print('polygon')
class _triangle(polygon):
def __init__(self, vert, axis=None):
super().__init__(vert, axis)
self.triangle_attribute = 2
def triangle_method(self):
print('triangle')
class _solid(polygon):
def __init__(self, vert, axis):
super().__init__(vert, axis)
self.solid_attribute = 3
def solid_method(self):
print('solid of revolution')
class _triangle_solid(_triangle, _solid):
def __init__(self, vert, axis):
super().__init__(vert, axis)
属性的可用性&方法取决于实例参数:
- 属性&来自基类的方法应该始终可用。
- 如果第一个参数等于3,属性&子类_triangle中的方法应该是可用的。
- 如果定义了第二个参数,属性&子类_solid中的方法应该可用。 所有组合
:
P = polygon(2)
P = polygon(2,axis=0)
P = polygon(3)
P = polygon(3,axis=0)
是否有更优雅的方法来做到这一点?在理想情况下,我想去掉_triangle_solid类。另外,我不明白为什么在某些情况下需要为axis定义默认参数,而不是所有情况。
完整项目:https://github.com/gerritnowald/polygon
这是一个试图过度使用继承的例子。继承在逻辑上是有意义的,当有"子类和父类之间的关系。三角形是多边形,所以没有问题;这是一个合理的继承链。旋转实体虽然可能由多边形构建,但不是多边形,试图将其嵌入继承层次结构会产生问题。更糟糕的是,旋转固体甚至可能根本不能用多边形来定义。
我强烈建议你用一个属性来定义你的旋转实体,这个属性表示任何被旋转的东西来产生它,而不是作为那个旋转图形的子类。
话虽如此,polygon
本身不应该负责知道它的所有子类,如果它是,它仍然应该是三角形的父类。您的设计目前呈现有一个polygon
类,nothing是一个实例;__new__
返回的不是polygon
,这很令人困惑。您可以使用一种更安全的(如果仍然不是惯用的)OO方式编写层次结构,方法如下:
# Tweaked name; it's not just the base anymore; using PEP8 class name capitalization rules
class Polygon:
def __new__(cls, vert, *args, **kwargs): # Accept and ignore the arguments we don't care
# about, __init__ will handle them
if vert == 3:
return super().__new__(Triangle)
else:
return super().__new__(cls)
def __init__(self, vert, axis):
self.polygon_attribute = 1
def polygon_method(self):
print('polygon')
class Triangle(Polygon):
def __init__(self, vert, axis):
super().__init__(vert, axis)
self.triangle_attribute = 2
def triangle_method(self):
print('triangle')
t = Polygon(3, None)
p = Polygon(4, None)
print(type(t), type(p))
# Indicates t is a Triangle, p is a Polygon
上网试试!