codeye
2022/10/30阅读:22主题:默认主题
2022年,你还在犯这些Python错误吗?
2022年,你还在犯这些Python错误吗?
要成为一个更好的程序员,你需要修正的6个Python错误
不可否认,Python可能是最容易学习和使用的语言之一。它是一种高级、多用途的编程语言。这促使它非常受欢迎,并在最近几年看到了大量的增长,特别是随着数据科学的出现。
然而,无论一种语言多么容易使用,要写出好的代码仍然需要时间和实践。写好的代码和好的代码之间是有区别的,我想强调一些可能会让你成为更好的程序员的做法。
在我写Python代码的5年多时间里,我不断地学习新的东西和做法,随着时间的推移,这些东西使我成为一个更好的程序员。这些错误不会导致语法错误,但最终会导致逻辑错误或只是糟糕的代码。我并不回避承认我在过去犯了这些错误,旧代码就是一个证明。
-
使用 import *
你刚刚开始了一个数据科学项目,你真的很高兴能在你的项目中应用你所获得的所有新的Python技巧和工具。对于你的模型精度,你从sklearn.metrics中写了导入*,以获得该库所提供的所有很酷的评估指标。你刚刚犯了第一个错误!
这可能是我看到的Python程序员最常犯的错误,它可以告诉我这是一个写代码的新手还是有经验的人。虽然这看起来很方便,但这样做是一种极坏的做法,而且是有原因的。
你正在污染你的命名空间,因为它把模块中的所有东西都导入到命名空间中。这占用了内存,并可能导致你没有意识到的重写。由于这个原因,你自己名字空间中的函数和类可能会与你定义的或来自其他库的函数和类发生冲突,导致不可预见的逻辑错误。
这影响了代码的可读性,因为现在你代码中的某些函数和变量无法追溯到它们的来源。这意味着你代码中随机出现的sqrt()函数可能来自numpy、math甚至是你不知道的自定义函数。这也增加了调试的难度。
解决方案 - 确保你总是指定你从哪里导入什么。下面是一个例子。
import secrets
import string
import re
from wsgiref.util import request_uri
from http.client import responses
from rest_framework import viewsets, status
from rest_framework.response import Response
from rest_framework.permissions import AllowAny, IsAuthenticated
from rest_framework.decorators import permission_classes
-
使用 pip freeze
来存储需求
pip freeze
是最流行的python需求管理命令之一。它经常被用来将你的项目的需求存储到文本文件中。许多Python初学者使用它来管理他们的虚拟环境。然而,它有一整套的问题,包括循环依赖和版本控制。
另外有一篇非常详细的文章,介绍了使用pip freeze的问题以及你可以使用的可能解决方案。
停止对你的Python项目使用 "pip freeze" 讨论为什么 "pip freeze "在管理Python依赖关系时没有那么酷。
我个人的建议是,在这个问题上改用pipreqs。
-
编写没有 Main
的Python脚本 由于Python是一种脚本语言,你可以在读-评-印循环(REPL)模式下编写和执行它。比如说
# test_function.py
def function1():
print("Hello world")
function1()
这段代码将在使用python test_function.py命令从CLI调用该函数时执行。然而,现在如果你想在一个不同的文件中导入相同的函数作为一个模块,例如jupyter笔记本,这将会发生什么。
导入没有主函数的模块 (图片由作者提供) 基本上,当函数被导入时,函数内部的代码会自动运行。如果是上面描述的简单函数,这可能没问题,但如果代码中包含了计算量很大的任务,那么即使在导入时,代码也会继续运行。这就是为什么编写__main__对Python脚本很重要。
# test_function.py
def function1():
print("Hello world")
function1()
定义 main 脚本
if __name__ == '__main__':
# 只在以脚本形式运行时执行
# execute only if run as a script
function1()
上面的代码保证了与CLI相同的功能,但在导入时不会作为模块运行,除非专门运行。(如下图所示)
以脚本形式运行的功能(图片由作者提供)
-
使用 assert
语句作为守护条件
assert关键字是检查条件和执行失败的最常用方法之一。它对调试代码非常有用,因为它可以让你测试代码中的条件是否返回True,如果不是,程序将引发AssertionError
。
然而,有一个很大的注意事项--当Python解释器用-O(优化)标志调用时,断言语句会从字节码中删除。所以,如果断言语句在生产代码中被用于验证,那么它们根本就不会被执行。这可能导致逻辑错误和安全漏洞的巨大空间。因此,我们应该只在测试内部使用断言语句。在生产中,我们可以切换到AssertionError
。
不正确的方法:断言条件,消息 正确的方法:
if not condition:
raise AssertionError
#如果不是条件。
# 提出AssertionError
-
正确使用 isinstance()
和type()
在Python的代码中,有很多地方我们必须检查对象的数据类型或类别。这方面的常用方法是 type() 和 isinstance() 。这两个方法都被广泛使用,重要的是要确保我们了解在什么地方使用什么,以及注意事项。
这两个方法中的任何一个都可以用来检查Python中一个对象的类型。isinstance也检查继承性,而type不检查继承性。当你检查派生类时,这就变得很重要。请看下面的例子。
type vs isinstance (图片来自作者) 在上面的例子中,当我们使用 type 时,int 和 bool 被视为不同的数据类型,但当我们使用 isinstance 时,它们被视为相同的,因为 bool 在 Python 中实际上是从 int 继承的。
因此,理解你正在测试/检查的内容并相应地使用正确的类型检查器是很重要的。你可以在这里阅读更多关于这两种方法之间的区别。
-
不正确地使用函数默认参数
一个常见的误解(最近也被我澄清了)是你传递给函数的默认参数在每次函数被调用时都会被重置为它的指定默认值。请看这个例子。
def func(list1=[]):
# 这里l1是一个默认参数,设置为[]
list1.append("Temp")
return list1
让我们看看当我们多次调用func时会发生什么。
多次调用该函数时的输出。(图片由作者提供) 上面的结果可能让你感到震惊,但这是一个非常合乎逻辑的结果。在python中,一个函数的默认值只在定义该函数时被评估一次。其他每一个函数调用实例都将使用最初定义的默认参数的定义。因此,list1 首先被评估为 [] ,然后每次都会对原始列表进行追加操作。
这个问题在可变数据类型中会遇到,解决这个问题的方法是使用none语句,在函数内部评估列表,如下所示。
def func(lst=None):
if lst is None:
lst = []
lst.append("Temp")
return lst
新函数定义的输出 总结
作者介绍