在namedtuple上有定製迭代器的pythonic方法嗎?在namedtuple上定製迭代器
自定義迭代器似乎需要索引屬性。通常,一個namedtuple有一個「__slots__ =()
」聲明,它可以避免動態字典的開銷並減少屬性查找的延遲。但是,這會破壞迭代器(AttributeError: 'Path' object has no attribute '_iidx'
)。將_iidx
添加到插槽結果nonempty __slots__ not supported
上下文:我將與大量的貝塞爾樣條一起工作。每個樣條由一系列「結點」和控制點對組成。通過評論__slots__ =()
聲明,我的代碼有效。但是,以每個實例動態字典爲代價。與其他所有內容相比,屬性查找中字典的開銷可能可以忽略不計,但它看起來並不是pythonic。
class Path(namedtuple('Path', "knots ctrl_pts")):
# __slots__ =()
@property
def SVG(self):
s = 'M %s' % self.knots[0].bare
for cps, k in self:
s += ' C %s %s' % (cps.bare, k.bare)
return s
def __iter__(self):
self._iidx = 0
return self
def __next__(self):
if self._iidx == len(self.ctrl_pts):
raise StopIteration
i = self._iidx
self._iidx += 1
return (self.ctrl_pts[i], self.knots[i+1])
SVG方法使用迭代器來製作SVG格式化平凡。這:
print('<path d="%s" stroke="black" stroke-width="1" fill="blue" />'
% path.SVG)
結果:
<path d="M 318.9 179.4 C 279.1 177.6 199.2 270.3 222.4 298.1 C 245.5
326.0 371.6 289.1 420.4 297.0 C 469.2 304.9 440.6 357.6 399.6 352.4
C 388.5 350.9 389.7 345.0 400.4 347.6 C 440.1 357.4 469.4 309.2 419.6
303.0 C 369.8 296.7 240.9 332.5 217.6 301.9 C 194.4 271.2 276.9 174.1
319.1 174.6 C 330.3 174.7 329.9 179.9 318.9 179.4" stroke="black"
stroke-width="1" fill="blue" />
但它也是微不足道的Gtk.DrawingArea的on_draw(self, wid, cr):
使用方法:
path = self.coords.outline_path
cr.set_source_rgb(*LT_BLUE)
cr.move_to(*path.knots[0])
for (c,k) in path:
cr.curve_to(*c.P1, *c.P2, *k)
cr.fill_preserve()
cr.set_source_rgb(*BLACK)
cr.stroke()
注: '節' 是一個List[Point]
and'ctrl_pts'is a List[ControlPoints]
:
class Point(namedtuple('Point', "x y")):
__slots__ =()
"""<bunch of stuff not shown>"""
@property
def bare(self):
return '%.1f %.1f' % (self.x, self.y)
class ControlPoints(namedtuple('ControlPoints', "P1 P2")):
__slots__ =()
@property
def bare(self):
return '%s %s' % (self.P1.bare, self.P2.bare)
我對python非常陌生,我確信這可以通過更pythonic的方式來完成。
爲什麼你不使用'__slots__'? – BrenBarn
不能在namedtuple上使用非空'__slots__'。它導致'非空__slots__不支持' –
我說過你爲什麼不*使用'__slots__'。爲什麼不接受'__dict__'? – BrenBarn