【发布时间】:2018-01-12 19:07:08
【问题描述】:
我真的很喜欢 Python 生成器。特别是,我发现它们正是连接到 Rest 端点的正确工具——我的客户端代码只需要在连接端点的生成器上进行迭代。但是,我发现 Python 的生成器没有我想要的那样富有表现力。通常,我需要过滤从端点获得的数据。在我当前的代码中,我将一个谓词函数传递给生成器,它将谓词应用于它正在处理的数据,并且仅当谓词为 True 时才产生数据。
我想转向生成器的组合 - 例如 data_filter(datasource( ))。这是一些演示代码,显示了我尝试过的内容。很清楚为什么它不起作用,我想弄清楚的是什么是最有表现力的解决方案:
# Mock of Rest Endpoint: In actual code, generator is
# connected to a Rest endpoint which returns dictionary(from JSON).
def mock_datasource ():
mock_data = ["sanctuary", "movement", "liberty", "seminar",
"formula","short-circuit", "generate", "comedy"]
for d in mock_data:
yield d
# Mock of a filter: simplification, in reality I am filtering on some
# aspect of the data, like data['type'] == "external"
def data_filter (d):
if len(d) < 8:
yield d
# First Try:
# for w in data_filter(mock_datasource()):
# print(w)
# >> TypeError: object of type 'generator' has no len()
# Second Try
# for w in (data_filter(d) for d in mock_datasource()):
# print(w)
# I don't get words out,
# rather <generator object data_filter at 0x101106a40>
# Using a predicate to filter works, but is not the expressive
# composition I am after
for w in (d for d in mock_datasource() if len(d) < 8):
print(w)
【问题讨论】:
-
你觉得内置的
filter()怎么样? -
好建议 - 如果我使用谓词函数,我会编写 filter(data_predicate, mock_datasource())。但是,我确实更喜欢可以编写生成组合的方法,例如 f(g(x))
-
@Kevin 在这种情况下
filter调用lambda现在你有一个笨拙的表达式。filter在过滤功能已经存在时很好(比如str.isdigit、None用于测试真值等, -
@Jean-FrançoisFabre,同意,
filter是“有时”的解决方案。这就是为什么我没有努力围绕它建立一个完整的答案:-P -
filter在 python 2 中对字符串非常有用,因为它节省了对str.join的需求。现在快乐消失了:)
标签: python generator function-composition