ITPub博客

首页 > 数据库 > 数据库开发技术 > 10个令人相见恨晚的Python高效编程技巧!

10个令人相见恨晚的Python高效编程技巧!

原创 数据库开发技术 作者:jackzhang 时间:2024-09-01 15:29:17 0 删除 编辑

Python是一门多功能编程语言,因其简单易学而闻名。今天我将向大家分享10个热门的Python技巧,助力你编写出更加高效和Pythonic的代码。

1. 列表推导式(List Comprehensions)

列表推导式(List Comprehensions)是创建列表的一种简单、简洁且优雅的方法,只需要使用一行代码即可。一般的方法需要通过循环且多行代码才可完成。

# 传统方法
names: list[str] = ['Jack', 'John', 'Stefan', 'Bob', 'Elon Musk', 'Bill Gates']
long_names_ta: list[str] = list()
for name in names:
    if len(name) > 4:
        long_names_ta.append(name)
print(f'Long names for traditional approach: {long_names_ta}')
# Long names for traditional approach: ['Stefan', 'Elon Musk', 'Bill Gates']

# 列表推导式
long_names_lc: list[str] = [name for name in names if len(name) > 4]
print(f'Long names for list comprehension: {long_names_lc}')
# Long names for list comprehension: ['Stefan', 'Elon Musk', 'Bill Gates']

通过上面的示例可以看出,相较于使用循环方式(4行代码),列表推导式创建列表(1行代码)更简洁,且更加Pythonic。

在处理集合以及对数据执行转换、过滤或映射时,此技巧可以节省更多时间。因为Python中的内部优化,列表推导式不仅更简洁,而且通常更快。

2. 使用 zip() 并行迭代

zip() 函数可以允许你并行迭代多个列表,这可以显著简化代码。它将每个列表中的元素一一配对。

names: list[str] = ['Jack', 'Smith', 'John', 'William']
genders: list[str] = ['Male', 'Female', 'Male', 'Female']
print(f"{'name'.ljust(7)}\t{'gender'.rjust(7)}")
print('-'*15)
for name, gender in zip(names, genders):
    print(f'{name.ljust(7)}\t{gender.rjust(7)}')

输出:

name     gender
---------------
Jack       Male
Smith    Female
John       Male
William  Female

注意,如果 zip() 函数中的列表长度如果不一致,则配对结果以最短列表为准。此外,zip() 函数可以接受2个以上列表参数。

# 长度不一致
names: list[str] = ['Jack', 'Smith', 'John', 'William']
genders: list[str] = ['Male', 'Female', 'Male']
print(f"{'name'.ljust(7)}\t{'gender'.rjust(7)}")
print('-'*15)
for name, gender in zip(names, genders):
    print(f'{name.ljust(7)}\t{gender.rjust(7)}')
    
# 接受2个以上的参数
names: list[str] = ['Jack', 'Smith', 'John', 'William']
genders: list[str] = ['Male', 'Female', 'Male', 'Female']
ages: list[int] = [18, 19, 20, 21]
addresses: list[str] = ['London', 'Paris', 'Berlin', 'Los Angeles']
print(f"{'name'.center(7)}\t{'gender'.center(7)}\t"
      f"{'age'.center(3)}\t{'address'.center(11)}")
print('-'*30)
for name, gender, age, address in zip(names, genders, ages, addresses):
    print(f'{name.center(7)}\t{gender.center(7)}\t'
          f'{str(age).center(3)}\t{address.center(11)}')

输出:

  name   gender age   address  
------------------------------
  Jack    Male   18    London  
 Smith   Female  19    Paris   
  John    Male   20    Berlin  
William  Female  21 Los Angeles

3. 字典推导式(Dictionary Comprehensions)

Python除了支持列表推导式外,同样支持字典推导式,允许你以更简短和更具可读性的方式创建字典。

  • 简单的字典推导式

    numbers = [1, 2, 3, 4, 5]
    square_dict = {num: num ** 2 for num in numbers}
    print(square_dict)  # {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
  • 带条件的字典推导式

    square_dict = {num: num ** 2 for num in numbers if num % 2 == 0}
    print(square_dict)  # {2: 4, 4: 16}
  • 通过其他字典创建字典

    original_dict = {'a': 1, 'b': 2, 'c': 3}
    inverted_dict = {value: key for key, value in original_dict.items()}
    print(inverted_dict)    # {1: 'a', 2: 'b', 3: 'c'}

4. enumerate() 迭代同时获取索引和值

对可迭代对象(列表或元组)进行迭代,除了值以外,有时候还需要其索引,这个目的可以通过 enumerate() 函数实现,该函数可以同时返回索引和值。

names: list[str] = ['John', 'Jack', 'William']
for index, name in enumerate(names):
    print(f'{index}: {name}')

输出:

0: John
1: Jack
2: William

这个技巧可以帮助你避免手动进行索引管理,并且让你的代码更高效且更具可读性。

5. collections.defaultdict 的强大

defaultdict 是Python内置字典的一个子类,用于简化处理字典中没有的键。当访问一个缺失的键时,defaultdict 将使用默认值自动创建该键。

from collections import defaultdict

# 值的默认类型为列表,意味着缺失键将会以一个空列表作为其默认值
default_dict: dict = defaultdict(list)
print(default_dict)

# 添加一个缺失键
default_dict['name'].append('Jack')
default_dict['name'].append('John')
print(default_dict)
print(default_dict['age'])
print(default_dict)

输出:

defaultdict(<class 'list'>, {})
defaultdict(<class 'list'>, {'name': ['Jack', 'John']})
[]
defaultdict(<class 'list'>, {'name': ['Jack', 'John'], 'age': []})

从上面的示例可以看出,当访问一个不存在的键时,默认返回一个空列表,且会将会以空列表为值将缺失键添加到原始字典中。当然,通过 setdefault() 方法也可以达到相似的目的,只不过该方法默认以 None 为值将缺失键添加到原字典中。

print(default_dict.setdefault('city'))
print(default_dict)

输出:

None
defaultdict(<class 'list'>, {'name': ['Jack', 'John'], 'age': [], 'city': None})

这在处理元素集合(如元素分组或频率计数)时特别有用。

6. 命名元组(Named Tuples)

Python的 collections.namedtuple 可以使用命名字段创建类似元组的对象。它为定义类提供了一种轻量级的替代方案,同时为你的数据提供一种清晰的结构。

from collections import namedtuple

Point = namedtuple('Point', ['x', 'y'])
p = Point(1, 2)
print(f'x = {p.x}, y = {p.y}')  # x = 1, y = 2

由于可以通过字段名称而不是索引来引用字段,因此,可以提高代码的可读性,使代码更加一目了然。

7. itertools 实现内存高效的迭代

itertools 模块提供了一组用于处理迭代器的快速(内存效率高)工具,它包括 count(), cycle(), repeat(), chain() 等函数。

其中一个强大且实用的技巧就是使用 itertools.combinations() 和 itertolls.permutations() 通过集合生成组合和排列,而无需自己实现逻辑。

import itertools

numbers: list[int] = [1, 2, 3]
combinations: list[tuple] = list(itertools.combinations(numbers, 2))
permutations: list[tuple] = list(itertools.permutations(numbers, 2))
print(combinations) # [(1, 2), (1, 3), (2, 3)]
print(permutations) # [(1, 2), (1, 3), (2, 1), (2, 3), (3, 1), (3, 2)]

在处理庞大的数据集或需要有效的循环结构时,itertools 是一个必不可少的工具。

8. 上下文管理器 with 语句的妙用

上下文管理器可以更有效地管理文件处理或数据库连接等资源,with 语句可确保确保资源在使用后自动清理,从而简化资源管理。

# 没有上下文管理器
file = open('example.txt', 'r')
content = file.read()
file.close()

# 有上下文管理器
with open('example.txt', 'r') as file:
    content = file.read()

它降低了已打开资源泄露的风险,使代码更安全、更高效。它们对文件处理、数据库连接管理或锁机制特别有用。

9. lambda:单行代码函数

lambda 函数也称匿名函数,因其不使用 def 关键字定义且没有函数名。它允许你动态创建小型匿名函数。如果你需要一个简短的函数来执行特定任务(例如排序或过滤列表)时,lambda 函数就特别有用。

pairs: list[tuple[int, str]] = [(1, 'one'), (2, 'two'), (3, 'three')]
pairs.sort(key=lambda x: x[1])
print(pairs)    # [(1, 'one'), (3, 'three'), (2, 'two')]

在上面的示例中,我们通过lambda 函数,以元组中的第二个元素为键对列表进行排序。

lambda 函数非常适合简化代码,但只适合逻辑简单的场景(为了保持简洁性和可读性)。在使用pandas处理表格时,就经常使用lambda 函数对单列的值进行数据转换或处理。

import pandas as pd

data_df: pd.DataFrame = pd.read_excel(r'example.xlsx')
city_ranking: pd.DataFrame = pd.read_excel(r'city_ranking.xlsx')
city_ranking_dict: dict = city_ranking.set_index('城市')['排名'].to_dict()
data_df['城市排名'] = data_df['城市'].apply(lambda x: city_ranking_dict[x])

10. f-string:高效实用的字符串格式化

f-字符串是在Python 3.6中引入的,它提供了一种更高级、更简洁、更有效的字符串格式化方法,在我以前的文章中也一直在使用这个技巧,通过花括号(引用变量或表达式),它可以将变量或表达式合并到字符串字面值中。

name: str = 'Alice'
age: int = 28
print(f'name: {name}, age: {age}')  # name: Alice, age: 28

f-字符串比旧的格式化技术(如 str.format() 或 % 运算符)表现更好,尤其是在处理大量变量插值时,它们的可读性也更强。

总结

今天的分享就到此结束啦,感谢你的阅读,希望对你有所帮助!


推荐阅读👇👇👇

Python必知必会:令人相见恨晚的10个Python类技巧(二)

Python必知必会:令人相见恨晚的10个Python类技巧(一)

5个良好的Python编程习惯,助你成为Python高手!

Python编程技巧:在函数参数中请停止使用“x=[]”

9个令人相见恨晚的Python字典技巧,让你写出更优雅、更Pythonic的代码!

- END -

🌟 如果你喜欢这篇文章并且愿意支持我的话,你可以:🌟

  • 👍👍👍 点赞文章
  • ⤴️⤴️⤴️ 转发文章
  • ⚛️⚛️⚛️ 点击在看
  • 🧑‍🤝‍🧑🧑‍🤝‍🧑🧑‍🤝‍🧑 让文章被推荐给更多人,找到更多志同道合的伙伴
  • 👏👏👏 欢迎给我留言

关注我,第一时间接收更多关于Python、数据分析和机器学习的深入分析和最新趋势。我们一起探索数据的力量,解锁AI的潜能。你的每一次互动都是对我的极大鼓励,也是我们共同成长的动力!

👇👇👇 关注并开启星标提醒,让知识与技能的火花不断在你的职业道路上燃烧吧!

原文作者:数据派探险家;如有侵权,请联系管理员删除。

请登录后发表评论 登录
全部评论

注册时间:2017-12-19

  • 博文量
    119
  • 访问量
    55942