我正在使用面向对象的继承方法来解决问题,我想知道如何将'Duck Typing'原则应用于这个问题。
我有一个班级BoxOfShapes
,会使用Shapes
(Circle
,Square
和Rectangle
)
import numpy as np
class Shape(object):
def __init__(self,area):
self.area = area;
def dimStr(self):
return 'area: %s' % str(self.area)
def __repr__(self):
return '%s, %s' % (self.__class__.__name__, self.dimStr()) + ';'
class Circle(Shape):
def __init__(self,radius):
self.radius = radius
def dimStr(self):
return 'radius %s' % str(self.radius)
class Rectangle(Shape):
def __init__(self, width, height):
self.width = width
self.height = height
def dimStr(self):
return '%s x %s' % (str(self.width), str(self.height))
class Square(Rectangle):
def __init__(self, side):
self.width = side
self.height = side
class BoxOfShapes(object):
def __init__(self, elements):
self.elements = elements
def __repr__(self):
pass
listOfShapes = [Rectangle(10,13),Rectangle(9,5),Circle(12),Circle(8),Circle(36),Square(10)]
myBox = BoxOfShapes(listOfShapes)
print myBox
让我们看看__repr__()
的{{1}}方法。根据我的理解,鸭子打字实现就像是,
BoxOfShapes
因为这表示'只要他们实施def __repr__(self):
return str(self.elements)
或__str__()
,我就不在乎我拥有哪些元素。输出是
__repr__()
让我说我想要一个来自>>> print myBox
[Rectangle, 10 x 13;, Rectangle, 9 x 5;, Circle, radius 12;, Circle, radius 8;, Circle, radius 36;, Square, 10 x 10;]
的人类可读输出 - 我知道所有形状都是某些类型的,所以分类很好,它们是这样的:
BoxOfShapes
这是
的输出 def __repr__(self):
circles = [ el.dimStr() for el in self.elements if isinstance(el, Circle)]
squares = [ el.dimStr() for el in self.elements if isinstance(el, Square)]
rectangles = [el.dimStr() for el in self.elements if (isinstance(el, Rectangle) and not isinstance(el, Square)) ]
return 'Box of Shapes; Circles: %s, Squares: %s, Rectangles: %s;' % ( str(circles), str(squares), str(rectangles))
这更容易阅读,但我不再使用鸭子打字,现在我必须在我想到一种新的形状时改变我对>>> print myBox
Box of Shapes; Circles: ['radius 12', 'radius 8', 'radius 36'], Squares: ['10 x 10'], Rectangles: ['10 x 13', '9 x 5'];
的定义。
我的问题是(如何)在这种情况下应用鸭子打字?
答案 0 :(得分:1)
您已经为有效使用继承铺平了道路。您为每个形状定义type
方法。只需创建一个字典,将该类型映射到BoxOfShapes
实现中该类型的元素列表。
正如其他人所建议的那样,使用内置的type()
功能。如果需要形状名称的字符串表示形式,请使用单独的实例方法。
答案 1 :(得分:1)
这是一个解决方案
from collections import defaultdict
class BoxOfShapes(object):
def __init__(self, elements):
self.elements = elements
self.groupings = defaultdict(list)
for element in elements:
self.groupings[type(element)].append(element)
def __repr__(self):
return "Box of Shapes: %s;" % ", ".join(type(group[0]).__name__ + "s: " + str(group) for group in self.groupings.itervalues())
但这似乎并不理想。
更合适的repr
可能只是要返回len
的{{1}}。
self.elements
答案 2 :(得分:1)
这并不是关于鸭子打字,而是关于继承(例如,你可能会问关于Java的完全相同的问题,例如没有鸭子打字的概念)。
您要做的只是创建字典映射类型到实例列表。动态地做这件事很容易:
from collections import defaultdict
type_dict = defaultdict(list)
for element in self.elements:
type_dict[element.type()].append(element.dimStr())
return ','.join('%s: %s' for k, v in type_dict.items())