Python:过滤器可迭代 class
Python: Filter iterable class
是否有一个 Iterable
对象可以容纳的 hook/dunder 以便内置 filter
函数可以扩展到 Iterable
类 (不仅仅是实例)?
当然可以自己写一个自定义的filter_iter
函数,比如:
def filter_iter(filt_func: callable, collection_cls: type):
name = 'Filtered' + collection_cls.__name__ # would this automatic scheme lead to namespace conflicts?
wrapped_cls = type(name, (collection_cls,), {'_filt_func': staticmethod(filt_func)})
def __iter__(self):
yield from filter(self._filt_func, super(wrapped_cls, self).__iter__())
wrapped_cls.__iter__ = __iter__
return wrapped_cls
这会产生预期的效果。例如,
from collections import Collection, Iterable
class Chunker(Iterable):
def __init__(self, source: Iterable, chk_size: int=2):
self._source = source
self._chk_size = chk_size
def __iter__(self):
yield from zip(*([iter(self._source)] * self._chk_size))
chunker = Chunker(range(12), 2)
assert list(chunker) == [(0, 1), (2, 3), (4, 5), (6, 7), (8, 9), (10, 11)]
FilteredChunker = filter_iter(lambda x: sum(x) % 3 == 0, Chunker)
filtered_chunker = FilteredChunker(range(12))
assert list(filtered_chunker) == [(4, 5), (10, 11)]
但是,就像有一个 __iter__
钩子决定如何迭代一个对象(例如,list
在对象上调用时应该如何表现),是否有一种 __filter__
钩子来确定 filter
在调用该对象时应该如何表现?
如果不是,过滤迭代的最佳实践或标准是什么?
与 list
(例如 __iter__
)不同,filter
没有这样的钩子。后者只是迭代器协议的一个应用,本身并不是一个单独的协议。
为了不让您空手而归,这是您提议的 filtered_iter
的更简洁版本,它动态地子class 给定的 class,组成其 __iter__
方法与 filter
.
def filter_iter(p, cls):
class _(cls):
def __iter__(self):
yield from filter(p, super().__iter__())
return _
是否有一个 Iterable
对象可以容纳的 hook/dunder 以便内置 filter
函数可以扩展到 Iterable
类 (不仅仅是实例)?
当然可以自己写一个自定义的filter_iter
函数,比如:
def filter_iter(filt_func: callable, collection_cls: type):
name = 'Filtered' + collection_cls.__name__ # would this automatic scheme lead to namespace conflicts?
wrapped_cls = type(name, (collection_cls,), {'_filt_func': staticmethod(filt_func)})
def __iter__(self):
yield from filter(self._filt_func, super(wrapped_cls, self).__iter__())
wrapped_cls.__iter__ = __iter__
return wrapped_cls
这会产生预期的效果。例如,
from collections import Collection, Iterable
class Chunker(Iterable):
def __init__(self, source: Iterable, chk_size: int=2):
self._source = source
self._chk_size = chk_size
def __iter__(self):
yield from zip(*([iter(self._source)] * self._chk_size))
chunker = Chunker(range(12), 2)
assert list(chunker) == [(0, 1), (2, 3), (4, 5), (6, 7), (8, 9), (10, 11)]
FilteredChunker = filter_iter(lambda x: sum(x) % 3 == 0, Chunker)
filtered_chunker = FilteredChunker(range(12))
assert list(filtered_chunker) == [(4, 5), (10, 11)]
但是,就像有一个 __iter__
钩子决定如何迭代一个对象(例如,list
在对象上调用时应该如何表现),是否有一种 __filter__
钩子来确定 filter
在调用该对象时应该如何表现?
如果不是,过滤迭代的最佳实践或标准是什么?
与 list
(例如 __iter__
)不同,filter
没有这样的钩子。后者只是迭代器协议的一个应用,本身并不是一个单独的协议。
为了不让您空手而归,这是您提议的 filtered_iter
的更简洁版本,它动态地子class 给定的 class,组成其 __iter__
方法与 filter
.
def filter_iter(p, cls):
class _(cls):
def __iter__(self):
yield from filter(p, super().__iter__())
return _