如何在inheritan中有效地使用duck类型

2024-09-23 14:27:14 发布

您现在位置:Python中文网/ 问答频道 /正文

我使用面向对象的继承方法来解决一个问题,我想知道如何将“Duck-Typing”原则应用到这个问题上。在

我有一个类BoxOfShapes,它将用ShapesCircleSquare和{})的列表实例化

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__()__repr__()方法。据我所知,duck类型的实现应该类似于

^{pr2}$

因为这意味着“我不在乎我有什么元素,只要它们实现__str__()或{}。结果是

>>> 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'];

它更容易阅读,但我不再使用duck类型,现在我必须随时更改BoxOfShapes的定义,只要我想出一种新的形状。在

我的问题是(如何)在这种情况下应用duck类型?在


Tags: selfreturninitdefareaelementselclass
3条回答

这并不是关于duck类型,而是关于继承的一般问题(例如,您可以对Java提出完全相同的问题,Java没有duck类型的概念)。在

您只需创建一个字典,将类型映射到实例列表。动态地执行此操作相当容易:

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())

您已经为有效地使用继承铺平了道路。为每个形状定义一个type方法。只需创建一个字典,将该类型映射到BoxOfShapes实现中该类型的元素列表。在

正如其他人建议的那样,使用内置的type()函数。如果需要形状名称的字符串表示形式,请使用单独的实例方法。在

这是一个解决方案

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可能只是返回self.elementslen。在

^{pr2}$

相关问题 更多 >