在这篇文章中,将探讨一些实用的编程技巧,旨在帮助数据科学家和Python爱好者编写更优质、更清晰的代码。这些技巧不仅个人在日常生活中使用,而且它们极大地提升了编程风格。因此,希望能够与大家分享这些技巧,以便每个人都能从中学习。将学到如何编写易于扩展且易于维护的高质量Python脚本。
虽然循环遍历一个小列表可能不是什么大问题,但想象一下,当需要遍历一个大型数据集时,将无法知道代码是否已经完成,这是不公平的,对吧?因此,为了消除是否处于无限循环或仅仅是耗时任务的疑虑,请使用tqdm库来显示进度条。
from tqdm import tqdm
for i in tqdm(range(100000000), desc="遍历循环"):
pass
上述代码将生成一个进度条,并显示循环执行情况以及其他详细信息,例如每秒迭代速度和完成循环所需的总时间。"DESC"参数允许传递一个合适的描述来显示循环。
类型提示意味着明确声明Python函数的所有参数。这些在日常工作中非常有用,几乎总是使用它们。知道吗?可以在Python函数定义中指定返回类型。虽然不经常使用它,但它存在,并且可以被认为是一个好的编码标准。以下代码演示了这一点:
from pandas import DataFrame
from typing import List
def update_df(df: DataFrame, classifier: str, accuracy: float, split_size: float = 0.5, remarks: List[str] = []) -> DataFrame:
new_row = {'Classifier': classifier, 'Accuracy': accuracy, 'split_size': split_size, 'Remarks': remarks}
df = df.append(new_row, ignore_index=True)
return df
df = DataFrame(columns=["Classifier", "Accuracy", "split_size", "Remarks"])
df = update_df(df, "KNN", 88, 0.1)
df = update_df(df, "SVM", 90, remarks=["再次检查"])
df = update_df(df, "LR", 80, 0.8, remarks=["参数调整", "过拟合"])
df
上述函数返回一个数据框,可以在现有的数据框中追加新行。这里的代码可能看起来有点奇怪,但应该考虑以下几点关于上述代码:
"->"符号在函数定义后定义了函数将返回的值类型。在这种情况下,函数返回一个pandas数据框。这也被称为其他编程语言中的返回类型。
任何函数的默认值都可以以"参数:类型 = 值"的格式定义,例如在上述函数中,"split: float = 0.5"为split变量设置了默认值0.5,数据类型为浮点数。
Python中默认的函数返回类型与其他语言中的"void"不同,是"None"。
如果想要有混合类型的返回,例如,根据工作,一个函数可以打印一些东西或返回一个值。该函数也可以是整数或浮点数值。在这种情况下,可以使用Python的"Union"功能,如下所示:
# 对于所有Python版本都有效,从Python 3.10开始弃用
from typing import Union
def func(val: int = 0) -> Union[None, int]:
pass
# 在Python 3.10及以上版本,不需要union关键字,可以直接使用“或”操作符。示例:
def func(val: int = 0) -> None | int:
pass
可以在函数定义中尽可能具体地进行类型提示。例如,在例子中,对于“Remarks”,指定它将是一个列表,列表将是“str”或字符串格式。这里应该记住一件事,Python不提供内置的类型错误检查类型提示,传递一个整数列表不会产生错误。至少在3.10及以下版本中目前是这样。因此,需要编写手动错误检查代码。
可以想象一个场景,用户可以传递一个未公开或不确定数量的参数,或者想要输入目录路径,这些路径可以通过用户输入是1个或50个不同的路径。显然,编写“def func(para1, para2…)”可能不是最佳行动方案,在这种情况下,可以使用“args”和“kwargs”。应该记住这两个关键字的目的。
Args用于指定未知数量的位置参数。
Kwargs用于指定未知数量的关键字参数。
import os
def count_files_in_dir(project_root_dir, *fpaths: str):
for path in fpaths:
rel_path = os.path.join(project_root_dir, path)
print(path, ":", len(os.listdir(rel_path)))
count_files_in_dir("../usr", "games", "include", "local", "bin")
注意:这里在计算Google Collab目录中的文件数量。
在函数调用中,实际上传递了5个参数,函数定义期望一个强制性的位置参数,其余的都被“*fpaths”吸收,然后可以计算文件数量。吸收的技术术语实际上是“参数打包”。
经常编写的代码可能缺乏适当的格式化或有时会变得混乱。尾随空格、额外的逗号、未排序的导入语句以及缩进中的空间等都可能是一个麻烦的问题。当然可以手动解决所有这些问题,但如果使用pre-commit钩子,可以节省大量时间。
这些钩子可以使用一行代码“pre-commit run”进行自动格式化。
需要创建自己的“pre-commit-config.yaml”文件,其中包含所有想要遵循的格式化规则的信息。在执行pre-commit run之前,应该使用git add将文件分阶段,否则所有文件都将被跳过。
几乎使用VS-Code处理所有事情,它非常有帮助,但有了这些扩展,可以提高生产力,个人认为这些扩展非常有用。它们如下:
- Bracket Pair Colorizer - 将匹配的括号配对成相同的颜色
- Path Intellisense - 允许自动完成文件名
- PythonDocstring Generator - 允许为Python生成文档字符串
- Python Indent - 允许代码在多行运行时正确缩进
- Python Type Hint - 允许在编写函数时自动完成类型提示
- TODO Tree - 将所有TODO集中在一起,这些TODO作为注释并包含TODO这个词
- Pylance - 有助于代码补全和参数建议
def func():
'''这是一个文档字符串的示例函数'''
pass
func.__doc__