函数式编程的pythonic风格
我对Python没有太多经验。我正试图以一种功能性的风格编写代码,就像我习惯于从Java和JavaScript编写代码一样函数式编程的pythonic风格,python,functional-programming,Python,Functional Programming,我对Python没有太多经验。我正试图以一种功能性的风格编写代码,就像我习惯于从Java和JavaScript编写代码一样 var result = getHeroes('Jedi') .map(hero => { hero: hero, movies: getMovies(hero) }) .filter(x => x.movies.contains('A New Hope')); 我试图在Python中做一些类似的事情,但我无法获得相同的链接样式。我不得不把它分解成两种
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')
我有两个问题:
在python中,他们使用
map
和filter
以函数式的方式(实际上不是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))
作为一个热爱函数式编程的人,不要用Python编写函数式编程 这条硬性的规则有点笨拙,当然有一些方法可以使用典型的函数工具,如
map
、filter
、和reduce
(在Python中称为functools.reduce
),来完成您想要完成的任务,但很可能您的函数代码看起来比sin更丑陋,在这种情况下,没有理由喜欢它,而不是一些必要的、漂亮的东西
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))
这可以通过列表理解来完成,但可能可读性较差
result = [(hero, movies) for hero in get_heros("Jedi")
for movies in [get_movies(hero)] if "A New Hope" in movies]
如果您愿意使用第三方库,我建议您使用
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')
实际上,javascript看起来功能性不强。好吧,你可以做功能性的,但很可能你的合作者会因此而憎恨你(:如果你也和一个功能性的人一起工作,那就千方百计去做(:@Joey Mallone既不是JavaScript/Java,但OP希望这样写你的嵌套
for
-循环示例是任何东西,但不是Pythonic。生成器表达式和理解有什么问题吗?@EliKorvigo这些表达式可以简洁,但这种逻辑所需的嵌套理解很麻烦。实际上我的逻辑是错误的——他想要(英雄,电影)如果是“新希望”在电影中
。我同意@AdamSmith的观点:嵌套列表理解比显式嵌套列表更难理解loops@AdamSmith我想第二条路是我想要的,谢谢you@AdamSmith我个人会在for循环中使用列表comp,即get_heros(“绝地”):results.extend中的英雄的([get_movies(hero)中的电影对电影(如果电影中有“新希望”)
生成器和生成器表达式(包括列表理解等)实际上是函数式编程的典型-FWIW,列表理解来自Haskell。这是一种真诚的方法,实际上可以是python和函数式的。我认为它会“看”如果您命名正在构建的函数,然后将其单独应用于数据,则效果更好。
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')