71 个解决日常问题的 Python 代码片段
如果您是第一次访问,建议您先去看看我们定期维护的原帖。目前,它包含超过 100 个按类别和复杂程度排列的片段。此外,还有一个方便您快速浏览的目录。
如果你关注我一段时间了,你就会知道我会定期发布一些解决日常问题的 Python 代码片段。好吧,我想我最终会把所有这些回复汇总到一篇长篇文章中,并附上所有这些资源的链接。
提前声明,我打算将本文中的所有代码片段移植到 Jupyter Notebook 中。如果您对这类项目感兴趣,请前往GitHub 仓库。非常感谢您的帮助!
日常问题
在本节中,我们将探讨各种常见的场景以及如何用 Python 代码解决它们。具体来说,我将简要解释这个问题,并列出一系列 Python 代码解决方案。然后,我会提供我拥有的所有资源的链接。
反转字典
有时我们有一个字典,希望能够翻转它的键和值。当然,我们会担心“如何处理重复的值?”以及“如果值不可哈希怎么办?”,不过,在简单的情况下,有以下几种解决方案:
my_dict = {
'Izuku Midoriya': 'One for All',
'Katsuki Bakugo': 'Explosion',
'All Might': 'One for All',
'Ochaco Uraraka': 'Zero Gravity'
}
# Use to invert dictionaries that have unique values
my_inverted_dict = dict(map(reversed, my_dict.items()))
# Use to invert dictionaries that have unique values
my_inverted_dict = {value: key for key, value in my_dict.items()}
# Use to invert dictionaries that have non-unique values
from collections import defaultdict
my_inverted_dict = defaultdict(list)
{my_inverted_dict[v].append(k) for k, v in my_dict.items()}
# Use to invert dictionaries that have non-unique values
my_inverted_dict = dict()
for key, value in my_dict.items():
my_inverted_dict.setdefault(value, list()).append(key)
# Use to invert dictionaries that have lists of values
my_dict = {value: key for key in my_inverted_dict for value in my_inverted_dict[key]}
如需更多解释,请查看我的文章“如何在 Python 中反转字典”。文章详细分析了每种解决方案、它们的性能指标以及适用场景。此外,我还有一个 YouTube 视频也涵盖了同样的主题。
对两个列表的元素求和
假设你有两个列表,你想将它们按元素合并成一个列表。换句话说,你想将第一个列表的第一个元素添加到第二个列表的第一个元素,并将结果存储在一个新列表中。有几种方法可以做到这一点:
ethernet_devices = [1, [7], [2], [8374163], [84302738]]
usb_devices = [1, [7], [1], [2314567], [0]]
# The long way
all_devices = [
ethernet_devices[0] + usb_devices[0],
ethernet_devices[1] + usb_devices[1],
ethernet_devices[2] + usb_devices[2],
ethernet_devices[3] + usb_devices[3],
ethernet_devices[4] + usb_devices[4]
]
# Some comprehension magic
all_devices = [x + y for x, y in zip(ethernet_devices, usb_devices)]
# Let's use maps
import operator
all_devices = list(map(operator.add, ethernet_devices, usb_devices))
# We can't forget our favorite computation library
import numpy as np
all_devices = np.add(ethernet_devices, usb_devices)
如果您想了解更深入的解释,请查看我的文章“如何在 Python 中对两个列表的元素求和”,其中甚至包含一个有趣的挑战。同样,您也可以从我关于同一主题的 YouTube 视频中获取一些有用的信息。
检查文件是否存在
Python 的一大优点是文件管理非常简单。与 Java 不同,Python 内置了文件读写语法。因此,检查文件是否存在相当简单:
# Brute force with a try-except block (Python 3+)
try:
with open('/path/to/file', 'r') as fh:
pass
except FileNotFoundError:
pass
# Leverage the OS package (possible race condition)
import os
exists = os.path.isfile('/path/to/file')
# Wrap the path in an object for enhanced functionality
from pathlib import Path
config = Path('/path/to/file')
if config.is_file():
pass
与往常一样,您可以在我的文章“如何在 Python 中检查文件是否存在”中了解有关这些解决方案的更多信息,其中介绍了三种解决方案和性能指标。
将两个列表转换为字典
之前我们讨论了如何在 Python 中对两个列表求和。事实证明,我们可以用两个列表做很多事情。例如,我们可以尝试将一个列表映射到另一个列表,从而创建一个字典。
与许多此类问题一样,也存在一些问题。例如,如果两个列表的大小不同怎么办?同样,如果键不唯一或可哈希怎么办?话虽如此,在简单的情况下,有一些直接的解决方案:
column_names = ['id', 'color', 'style']
column_values = [1, 'red', 'bold']
# Convert two lists into a dictionary with zip and the dict constructor
name_to_value_dict = dict(zip(column_names, column_values))
# Convert two lists into a dictionary with a dictionary comprehension
name_to_value_dict = {key:value for key, value in zip(column_names, column_values)}
# Convert two lists into a dictionary with a loop
name_value_tuples = zip(column_names, column_values)
name_to_value_dict = {}
for key, value in name_value_tuples:
if key in name_to_value_dict:
pass # Insert logic for handling duplicate keys
else:
name_to_value_dict[key] = value
再次强调,你可以在我的文章“如何在 Python 中将两个列表转换为字典”中找到每个解决方案的解释以及更多信息。如果你是一个视觉型的人,你可能会更喜欢我的 YouTube 视频,其中也涵盖了如何将列表映射到字典。
检查列表是否为空
如果你之前学习过 Java 或 C 等静态类型语言,那么 Python 中缺少静态类型可能会让你感到困扰。当然,不知道变量的类型有时会让人感到沮丧,但也有好处。例如,我们可以通过列表的类型灵活性来检查列表是否为空——以及其他方法:
my_list = list()
# Check if a list is empty by its length
if len(my_list) == 0:
pass # the list is empty
# Check if a list is empty by direct comparison (only works for lists)
if my_list == []:
pass # the list is empty
# Check if a list is empty by its type flexibility **preferred method**
if not my_list:
pass # the list is empty
如果您想了解有关这三种解决方案的更多信息,请查看我的文章“如何在 Python 中检查列表是否为空”。如果您遇到困难,请查看我的 YouTube 视频,其中涵盖了同一主题。
克隆列表
我在编程中最喜欢的主题之一就是复制数据类型。毕竟,在我们生活的这个基于引用的世界里,复制数据类型从来都不是一件容易的事,对于 Python 来说也是如此。幸运的是,如果我们想复制一个列表,有几种方法可以做到:
my_list = [27, 13, -11, 60, 39, 15]
# Clone a list by brute force
my_duplicate_list = [item for item in my_list]
# Clone a list with a slice
my_duplicate_list = my_list[:]
# Clone a list with the list constructor
my_duplicate_list = list(my_list)
# Clone a list with the copy function (Python 3.3+)
my_duplicate_list = my_list.copy() # preferred method
# Clone a list with the copy package
import copy
my_duplicate_list = copy.copy(my_list)
my_deep_duplicate_list = copy.deepcopy(my_list)
# Clone a list with multiplication?
my_duplicate_list = my_list * 1 # do not do this
说到克隆,了解浅拷贝和深拷贝的区别非常重要。幸运的是,我有一篇关于这个主题的文章。
最后,您可以在我的文章“如何在 Python 中克隆列表”中找到有关上述解决方案的更多信息。此外,您可能还会发现我的相关 YouTube 视频“ 7 种使用 Python 复制列表的方法(以匹兹堡企鹅队为例) ”很有价值。
检索列表的最后一项
既然我们讨论的是列表,那就来谈谈如何获取列表的最后一项。在大多数语言中,这涉及到一些复杂的数学表达式来计算列表的长度。如果我告诉你 Python 中还有几个更有趣的解决方案呢?
my_list = ['red', 'blue', 'green']
# Get the last item with brute force using len
last_item = my_list[len(my_list) - 1]
# Remove the last item from the list using pop
last_item = my_list.pop()
# Get the last item using negative indices *preferred & quickest method*
last_item = my_list[-1]
# Get the last item using iterable unpacking
*_, last_item = my_list
与往常一样,您可以从我的文章“如何在 Python 中获取列表的最后一项”中了解有关这些解决方案的更多信息,其中包含挑战、性能指标和YouTube 视频。
创建 Python 脚本快捷方式
有时,当您创建脚本时,您希望能够通过单击按钮方便地运行它。幸运的是,有几种方法可以做到这一点。
首先,我们可以使用以下设置创建 Windows 快捷方式:
\path\to\trc-image-titler.py -o \path\to\output
同样,我们也可以使用以下代码创建批处理文件:
@echo off
\path\to\trc-image-titler.py -o \path\to\output
最后,我们可以使用以下代码创建一个 bash 脚本:
#!/bin/sh
python /path/to/trc-image-titler.py -o /path/to/output
如果您需要更多解释,请参阅文章“如何使用参数创建 Python 脚本快捷方式”。
对字符串列表进行排序
排序是计算机科学中一项常见的任务,要求你知道如何实现。尽管大多数课程都非常注重排序算法,但没有人真正告诉你排序实际上有多复杂。例如,对数字进行排序很简单,但对字符串进行排序呢?我们如何确定一个合适的顺序?幸运的是,Python 中有很多方法:
my_list = ["leaf", "cherry", "fish"]
# Brute force method using bubble sort
my_list = ["leaf", "cherry", "fish"]
size = len(my_list)
for i in range(size):
for j in range(size):
if my_list[i] < my_list[j]:
temp = my_list[i]
my_list[i] = my_list[j]
my_list[j] = temp
# Generic list sort *fastest*
my_list.sort()
# Casefold list sort
my_list.sort(key=str.casefold)
# Generic list sorted
my_list = sorted(my_list)
# Custom list sort using casefold (>= Python 3.3)
my_list = sorted(my_list, key=str.casefold)
# Custom list sort using current locale
import locale
from functools import cmp_to_key
my_list = sorted(my_list, key=cmp_to_key(locale.strcoll))
# Custom reverse list sort using casefold (>= Python 3.3)
my_list = sorted(my_list, key=str.casefold, reverse=True)
如果您对这些解决方案的工作原理感到好奇,或者您只是想知道一些潜在的风险,请查看我的文章“如何在 Python 中对字符串列表进行排序”。
解析电子表格
Python 最有趣的用例之一是数据科学。然而,不幸的是,这意味着需要处理大量各种格式的原始数据,例如文本文件和电子表格。幸运的是,Python 内置了许多实用程序来读取不同的文件格式。例如,我们可以轻松地解析电子表格:
# Brute force solution
csv_mapping_list = []
with open("/path/to/data.csv") as my_data:
line_count = 0
for line in my_data:
row_list = [val.strip() for val in line.split(",")]
if line_count == 0:
header = row_list
else:
row_dict = {key: value for key, value in zip(header, row_list)}
csv_mapping_list.append(row_dict)
line_count += 1
# CSV reader solution
import csv
csv_mapping_list = []
with open("/path/to/data.csv") as my_data:
csv_reader = csv.reader(my_data, delimiter=",")
line_count = 0
for line in csv_reader:
if line_count == 0:
header = line
else:
row_dict = {key: value for key, value in zip(header, line)}
csv_mapping_list.append(row_dict)
line_count += 1
# CSV DictReader solution
import csv
with open("/path/to/dict.csv") as my_data:
csv_mapping_list = list(csv.DictReader(my_data))
在本例中,我们尝试将输出结果保存在一个字典列表中。如果您想了解更多关于其工作原理的信息,请查看完整的文章“如何在 Python 中解析电子表格”。
对字典列表进行排序
有了字典列表后,你可能想按某种特定顺序组织它们。例如,如果字典的键是日期,我们可以尝试按时间顺序对它们进行排序。幸运的是,排序是另一个相对轻松的任务:
csv_mapping_list = [
{ "Name": "Jeremy", "Age": 25, "Favorite Color": "Blue" },
{ "Name": "Ally", "Age": 41, "Favorite Color": "Magenta" },
{ "Name": "Jasmine", "Age": 29, "Favorite Color": "Aqua" }
]
# Custom sorting
size = len(csv_mapping_list)
for i in range(size):
min_index = i
for j in range(i + 1, size):
if csv_mapping_list[min_index]["Age"] > csv_mapping_list[j]["Age"]:
min_index = j
csv_mapping_list[i], csv_mapping_list[min_index] = csv_mapping_list[min_index], csv_mapping_list[i]
# List sorting function
csv_mapping_list.sort(key=lambda item: item.get("Age"))
# List sorting using itemgetter
from operator import itemgetter
f = itemgetter('Name')
csv_mapping_list.sort(key=f)
# Iterable sorted function
csv_mapping_list = sorted(csv_mapping_list, key=lambda item: item.get("Age"))
所有这些解决方案以及更多内容都在我的文章“如何在 Python 中对字典列表进行排序”中概述。
编写列表推导
我最喜欢聊的 Python 话题之一就是列表推导式。作为一个从小接触 Java、C/C++ 和 C# 等语言的人,在接触 Python 之前,我从未见过类似列表推导式的东西。现在,我对它简直着迷了。因此,我整理了一系列示例:
# Define a generic 1D list of constants
my_list = [2, 5, -4, 6]
# Duplicate a 1D list of constants
[item for item in my_list]
# Duplicate and scale a 1D list of constants
[2 * item for item in my_list]
# Duplicate and filter out non-negatives from 1D list of constants
[item for item in my_list if item < 0]
# Duplicate, filter, and scale a 1D list of constants
[2 * item for item in my_list if item < 0]
# Generate all possible pairs from two lists
[(a, b) for a in (1, 3, 5) for b in (2, 4, 6)]
# Redefine list of contents to be 2D
my_list = [[1, 2], [3, 4]]
# Duplicate a 2D list
[[item for item in sub_list] for sub_list in my_list]
# Duplicate an n-dimensional list
def deep_copy(to_copy):
if type(to_copy) is list:
return [deep_copy(item) for item in to_copy]
else:
return to_copy
与往常一样,您可以在我的文章“如何用 Python 编写列表推导式”中找到对所有这些代码的更正式的解释。另外,我还有一个 YouTube 视频,其中分享了列表推导式的几个示例。
合并两个字典
在本系列文章中,我们大量讨论了如何处理列表和字典等数据结构。这次也不例外。具体来说,我们将讨论如何合并两个字典。当然,合并两个字典会带来风险。例如,如果存在重复的键怎么办?幸运的是,我们有解决方案:
yusuke_power = {"Yusuke Urameshi": "Spirit Gun"}
hiei_power = {"Hiei": "Jagan Eye"}
powers = dict()
# Brute force
for dictionary in (yusuke_power, hiei_power):
for key, value in dictionary.items():
powers[key] = value
# Dictionary Comprehension
powers = {key: value for d in (yusuke_power, hiei_power) for key, value in d.items()}
# Copy and update
powers = yusuke_power.copy()
powers.update(hiei_power)
# Dictionary unpacking (Python 3.5+)
powers = {**yusuke_power, **hiei_power}
# Backwards compatible function for any number of dicts
def merge_dicts(*dicts: dict):
merged_dict = dict()
for dictionary in dicts:
merge_dict.update(dictionary)
return merged_dict
如果您有兴趣,我有一篇文章专门讨论这个主题,名为“如何在 Python 中合并两个字典”,其中介绍了四种解决方案以及性能指标。
格式化字符串
无论我们是否愿意承认,我们经常会为了快速调试而将打印语句埋藏在代码中。毕竟,一个合适的打印语句可以节省你很多时间。然而,实际显示我们想要的内容并不总是那么容易或方便。幸运的是,Python 有很多格式化选项:
name = "Jeremy"
age = 25
# String formatting using concatenation
print("My name is " + name + ", and I am " + str(age) + " years old.")
# String formatting using multiple prints
print("My name is ", end="")
print(name, end="")
print(", and I am ", end="")
print(age, end="")
print(" years old.")
# String formatting using join
print(''.join(["My name is ", name, ", and I am ", str(age), " years old"]))
# String formatting using modulus operator
print("My name is %s, and I am %d years old." % (name, age))
# String formatting using format function with ordered parameters
print("My name is {}, and I am {} years old".format(name, age))
# String formatting using format function with named parameters
print("My name is {n}, and I am {a} years old".format(a=age, n=name))
# String formatting using f-Strings (Python 3.6+)
print(f"My name is {name}, and I am {age} years old")
请记住,这些解决方案不必与 print 语句一起使用。换句话说,您可以随意在需要的地方使用类似 f 字符串的解决方案。
与往常一样,您可以在我的文章“如何在 Python 中格式化字符串”中找到所有这些解决方案的解释以及更多内容。如果您想查看这些代码片段的实际操作,请查看我的 YouTube 视频“以我的猫为主角,用 Python 格式化字符串的 6 种方法”。
在同一行打印
与格式化字符串类似,有时你只需要在 Python 中在同一行打印。根据该print
命令当前的设计,它会自动在字符串末尾添加一个换行符。幸运的是,有几种方法可以解决这个问题:
# Python 2 only
print "Live PD",
# Backwards compatible (also fastest)
import sys
sys.stdout.write("Breaking Bad")
# Python 3 only
print("Mob Psycho 100", end="")
与往常一样,如果您计划使用其中任何一种解决方案,请查看题为“如何在 Python 中在同一行打印”的文章,了解更多用例和注意事项。
测试性能
最后,有时你只想比较几段代码。幸运的是,Python 提供了一些简单的选项:
# Brute force solution
import datetime
start_time = datetime.datetime.now()
[(a, b) for a in (1, 3, 5) for b in (2, 4, 6)]
# example snippet
end_time = datetime.datetime.now()
print end_time - start_time
# timeit solution
import timeit
min(timeit.repeat("[(a, b) for a in (1, 3, 5) for b in (2, 4, 6)]"))
# cProfile solution
import cProfile
cProfile.run("[(a, b) for a in (1, 3, 5) for b in (2, 4, 6)]")
再次,如果您想了解更多详细信息,请查看题为“如何对 Python 代码进行性能测试”的文章。
分享你自己的问题
如你所见,这篇文章及其相关系列文章已经相当长了。话虽如此,我还是很乐意继续扩充它们。因此,你应该考虑分享一些你自己遇到的问题。毕竟,有些东西你经常在谷歌搜索。为什么不和我们分享一下呢?
与此同时,欢迎关注我的新闻邮件、访问我的商店、订阅我的 YouTube 频道以及/或者成为我的赞助人,帮助扩充我的收藏。此外,欢迎您浏览以下相关文章:
除此之外,感谢您的光临!感谢您的支持。
文章“71 个 Python 代码片段解决日常问题”最先出现在The Renegade Coder上。
文章来源:https://dev.to/therenegadecoder/71-python-code-snippets-for-everyday-problems-1mep