我对Python没有太多经验。我正在尝试以一种功能风格进行编程,就像我以前从Java和JavaScript所习得的那样。
var result = getHeroes('Jedi')
.map(hero => { hero: hero, movies: getMovies(hero) })
.filter(x => x.movies.contains('A New Hope'));
我正在尝试在Python中执行类似的操作,但是无法获得相同的链接样式。我不得不将其分解为两个我不喜欢的语句:
tmp = ((hero, get_movies(hero)) for hero in get_heroes('jedi'))
result = ((hero, movies) for (hero, movies) in tmp if movies.contains('A New Hope')
我有两个问题:
谢谢。
答案 0 :(得分:4)
作为喜欢函数式编程的人,不要用Python编写函数式样式。
这条硬朗的规则有些牵强,并且肯定有多种方法可以使用map
,filter
和{{1 }}(在Python中称为reduce
),但您的功能代码看起来可能比罪恶的丑陋,在这种情况下,没有必要比命令式的和漂亮的东西更喜欢它。
functools.reduce
这可以通过列表理解来完成,但可读性可能较低。
result = []
for hero in get_heros("Jedi"):
movies = get_movies(hero)
for movie in movies:
if "A New Hope" in movies:
result.append((hero, movies))
答案 1 :(得分:2)
生成器表达式 是Pythonic方法,但是可以通过结合map
和filter
来实现功能性解决方案:
mapper = map(lambda x: (x, get_movies(x)), get_heroes('jedi'))
result = filter(lambda x: x[1].contains('A New Hope'), mapper)
答案 2 :(得分:1)
IMO,他们使用map
和filter
在python中(实际上不是pythonic)以一种功能样式实现此目的:
result = filter (
lambda x: x[1].contains('A New Hope'),
map(
lambda x: (hero, get_movies(hero)),
get_heroes('jedi')
)
)
pythonic的方式(不是很实用)是使用生成器表达式:
result = ((hero, get_movies(hero)) for hero in get_heroes("jedi") if "A new hope" in get_movies(hero))
答案 3 :(得分:1)
如果您愿意使用第三方库,我建议fn.py
及其语法糖来组成
from fn import F
result = (
F(map, lambda hero: dict(hero=hero, movies=getMovies(hero))) >>
(filter, lambda x: 'A New Hope' in x['movies']) >>
list
)(getHeroes('Jedi'))
尽管不希望有列表,但是您可以删除合成中的最后一个元素,尽管有状态的迭代器/生成器的功能不是很明显。 F
-对象包装可调用对象,并使部分应用程序和编写更加容易。 F
表达式链是一个可以多次使用的新函数。从经典意义上来说,这更接近于函数式编程:程序就是组合:
program = (
F(map, lambda hero: dict(hero=hero, movies=getMovies(hero))) >>
(filter, lambda x: 'A New Hope' in x['movies']) >>
list
)
result = program(getHeroes('Jedi'))
# or even
result = (F(getHeroes) >> program)('Jedi')