ZetCode

Python Funcy

最后修改:2025 年 2 月 15 日

在本文中,我们将展示如何在 Python 中使用 funcy 库。 Funcy 提供了一系列函数式编程实用工具,可以更轻松地处理集合、字典和函数。

funcy 库对于以函数式风格过滤、转换和组合数据等任务特别有用。

Distinct (去重)

以下示例演示了如何使用 distinct 函数从列表中删除重复元素。

main.py
from funcy import distinct

words = ['sky', 'war', 'water', 'war', 'sky', 'cup', 'cup', 'atom']

distilled = distinct(words)
print(list(distilled))

在此程序中,distinct 函数用于从 words 列表中删除重复元素。

distilled = distinct(words)

distinct 函数返回输入列表中唯一元素的迭代器。

$ python main.py
['sky', 'war', 'water', 'cup', 'atom']

Split (分割)

以下示例演示了如何使用 split 函数根据条件将列表分成两部分。

main.py
from funcy import split

values = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

evens, odds = split(lambda e: e % 2 == 0, values)

print(list(evens))
print(list(odds))

在此程序中,split 函数用于将 values 列表分为偶数和奇数。

evens, odds = split(lambda e: e % 2 == 0, values)

split 函数根据提供的条件将列表分成两部分。

$ python main.py
[2, 4, 6, 8, 10]
[1, 3, 5, 7, 9]

Flatten (扁平化)

以下示例演示了如何使用 flatten 函数来扁平化嵌套列表。

main.py
from funcy import flatten

nested_list = [[1, 2], [3, 4], [5]]
flat_list = flatten(nested_list)
print(list(flat_list))

在此程序中,flatten 函数用于将 nested_list 扁平化为单个列表。

flat_list = flatten(nested_list)

flatten 函数返回嵌套列表中元素的迭代器。

$ python main.py
[1, 2, 3, 4, 5]

Merge With (合并)

以下示例演示了如何使用 merge_with 函数来合并多个字典并组合它们的值。

main.py
from funcy import merge_with

# Sales data for different stores and online
store1_sales = {
    'Product A': 120,
    'Product B': 80
}
store2_sales = {
    'Product A': 150,
    'Product C': 60
}
online_sales = {
    'Product B': 110,
    'Product C': 90
}

# Merge sales data, summing up sales for each product
total_sales = merge_with(sum, store1_sales, store2_sales, online_sales)

print(total_sales)

在此程序中,merge_with 函数用于合并多个字典并对它们的值求和。

total_sales = merge_with(sum, store1_sales, store2_sales, online_sales)

merge_with 函数合并字典并将 sum 函数应用于为相同键组合值。

$ python main.py
{'Product A': 270, 'Product B': 190, 'Product C': 150}

Walk Values & Walk Keys (遍历值 & 遍历键)

以下示例演示了如何使用 walk_valueswalk_keys 函数来转换字典值和键。

main.py
from funcy import walk_values, walk_keys

# Sample data with inconsistent text cases
data = {
    'Name': 'Alice',
    'Email': 'ALICE@EXAMPLE.COM',
    'City': 'NeW YoRk'
}

# Normalize the text to lowercase
normalized_values = walk_values(str.lower, data)
print("Normalized values:", normalized_values)

# Normalize the text to lowercase
normalized_keys = walk_keys(str.lower, data)
print("Normalized keys:", normalized_keys)

在此程序中,walk_valueswalk_keys 函数用于将字典值和键规范化为小写。

normalized_values = walk_values(str.lower, data)

walk_values 函数将 str.lower 函数应用于字典中的所有值。

normalized_keys = walk_keys(str.lower, data)

walk_keys 函数将 str.lower 函数应用于字典中的所有键。

$ python main.py
Normalized values: {'Name': 'alice', 'Email': 'alice@example.com', 'City': 'new york'}
Normalized keys: {'name': 'Alice', 'email': 'ALICE@EXAMPLE.COM', 'city': 'NeW YoRk'}

Split By (按条件分割)

以下示例演示了如何使用 split_by 函数根据条件将列表分成两部分。

main.py
from collections import namedtuple
from funcy import split_by

City = namedtuple('City' , 'id name population')

c1 = City(1, 'Bratislava', 432000)
c2 = City(2, 'Budapest', 1759000)
c3 = City(3, 'Prague', 1280000)
c4 = City(4, 'Warsaw', 1748000)
c5 = City(5, 'Los Angeles', 3971000)
c6 = City(6, 'Edinburgh', 464000)
c7 = City(7, 'Presov', 82930)
c8 = City(8, 'Kosice', 228000)
c9 = City(9, 'Zilina', 81220)

cities = [c1, c2, c3, c4, c5, c6, c7, c8, c9]
cities.sort(key=lambda c: c.population)

low_pop, high_pop = split_by(lambda c: c.population < 1000_000, cities)
print(list(low_pop))
print(list(high_pop))

在此程序中,split_by 函数用于根据人口将 cities 列表分成两部分。

low_pop, high_pop = split_by(lambda c: c.population < 1000_000, cities)

split_by 函数根据提供的条件将列表分成两部分。

$ python main.py
[City(id=7, name='Presov', population=82930), City(id=9, name='Zilina', population=81220), 
 City(id=8, name='Kosice', population=228000), City(id=6, name='Edinburgh', population=464000), 
 City(id=1, name='Bratislava', population=432000)]
[City(id=3, name='Prague', population=1280000), City(id=4, name='Warsaw', population=1748000), 
 City(id=2, name='Budapest', population=1759000), City(id=5, name='Los Angeles', population=3971000)]

Select Keys & Select Values (选择键 & 选择值)

以下示例演示了如何使用 select_keysselect_values 函数来过滤字典的键和值。

main.py
from funcy import select_keys, select_values

animals = {'donkeys': 3, 'horses': 2, 'chickens': 15,
           'dogs': 2, 'cats': 5, 'elephants': 2}

res = select_values(lambda e: e > 2, animals)
print(res)

res = select_keys(lambda e: e.startswith('do'), animals)
print(res)

res = {k: v for k, v in filter(lambda e: e[1] > 2, animals.items())}
print(res)

res = {k: v for k, v in filter(
    lambda e: e[0].startswith('do'), animals.items())}
print(res)

在此程序中,select_valuesselect_keys 函数用于过滤字典值和键。

res = select_values(lambda e: e > 2, animals)

select_values 函数根据提供的条件过滤字典值。

res = select_keys(lambda e: e.startswith('do'), animals)

select_keys 函数根据提供的条件过滤字典键。

$ python main.py
{'donkeys': 3, 'chickens': 15, 'cats': 5}
{'donkeys': 3, 'dogs': 2}
{'donkeys': 3, 'chickens': 15, 'cats': 5}
{'donkeys': 3, 'dogs': 2}

Count By (按条件计数)

以下示例演示了如何使用 count_by 函数来计算列表中值的出现次数。

main.py
from dataclasses import dataclass
from funcy import count_by

@dataclass
class User:
    name: str
    age: int
    occupation: str

users = [
    User(name='Alice', age=25, occupation='pilot'),
    User(name='Bob', age=30, occupation='driver'),
    User(name='Charlie', age=35, occupation='teacher'),
    User(name='David', age=40, occupation='teacher'),
    User(name='Paul', age=44, occupation='teacher'),
    User(name='Eva', age=25, occupation='driver'),
    User(name='Frank', age=30, occupation='teacher'),
    User(name='Mary', age=31, occupation='accountant')
]

# Count users by age group
occupation_counts = count_by(lambda user: user.occupation, users)

print(dict(occupation_counts))

在此程序中,count_by 函数用于计算每个职业中的用户数量。

occupation_counts = count_by(lambda user: user.occupation, users)

count_by 函数根据提供的函数计算值的出现次数。

$ python main.py
{'pilot': 1, 'driver': 2, 'teacher': 4, 'accountant': 1}

函数组合

以下示例演示了如何使用 rcomposecompose 函数来组合多个函数。

main.py
from funcy import rcompose, compose

def square(x):
    return x * x

def increment(x):
    return x + 1

def cube(x):
    return x * x * x

val = 5

fchain = rcompose(square, increment, cube)
print(fchain(val))
print(cube(increment(square(val))))

print('---------------------------------------------')

fchain = compose(square, increment, cube)
print(fchain(val))
print(square(increment(cube(val))))

在此程序中,rcomposecompose 函数用于组合多个函数。

fchain = rcompose(square, increment, cube)

rcompose 函数以相反的顺序(从右到左)组合函数。

fchain = compose(square, increment, cube)

compose 函数按顺序(从左到右)组合函数。

$ python main.py
17576
17576
---------------------------------------------
15876
15876

来源

Python Funcy - 文档

在本文中,我们展示了如何使用 funcy 库在 Python 中进行函数式编程任务。

作者

我叫 Jan Bodnar,是一位充满热情的程序员,拥有丰富的编程经验。 自 2007 年以来,我一直在撰写编程文章。 迄今为止,我已经撰写了 1,400 多篇文章和 8 本电子书。 我拥有超过十年的编程教学经验。

列出所有 Python 教程