5个调试函数
下面5个函数对于代码的调试和故障排除非常有用。
breakpoint
需要暂停代码的执行并进入Python命令提示符吗?你需要breakpoint!
调用breakpoint函数将使你进入pdb,即Python调试器。有很多关于PDB的教程和讲座:这里是一个简短的(https://pyvideo.org/pybay-2017/introduction-to-pdb.html ),这里是一个冗长的。(https://www.youtube.com/watch?v=P0pIW5tJrRM&feature=player_embedded )
这个内置函数是在Python 3.7中添加的,但如果你使用的是较老版本的Python,你可以使用import pdb ; pdb.set_trace()来获得相同的功能。
dir
dir函数可以用于两种情况:
1.查看所有局部变量的列表
2.查看特定对象上的所有属性列表
打开一个新的Python shell,然后创建一个新的变量x之后,我们就可以看到我们的局部变量:
如果我们把这个x列表传入到dir函数中,我们可以看到它的所有属性:
我们可以看到典型的列表方法(如append、pop、remove等更多),以及用于运算符重载的许多双下划线方法(特殊方法)。
vars
vars函数是两个相关内容的混合体:检查locals()和测试对象的__dict__属性。
当不带参数调用vars时,它等价于调用locals()内置函数(该函数显示所有局部变量及其值的一个字典)。
当使用一个参数调用它时,它会访问该对象上的__dict__属性(在许多对象上,该属性表示所有实例属性的一个字典)。
如果你曾经尝试使用my_object.__dict__,那你可以用vars来代替。
我通常在使用vars之前会先使用dir。
type
type函数将返回你传递给它的对象的类型。
一个类实例的类型是该类本身:
一个类的类型是它的元类,通常是type:
如果你曾经看到有人使用了__class__,那么你要知道他们可以使用更高级的type函数来代替:
type函数有时在实际代码中是很有用的(特别是带有继承和自定义字符串表示的面向对象代码),但在调试时也很有用。
请注意,在执行类型检查时,通常使用isinstance函数来代替type(也请注意,我们不倾向于在Python中进行类型检查,因为我们更喜欢练习鸭子类型)。
help
如果你在一个交互式Python shell中(我通常称之为Python REPL),可能正在使用breakpoint调试代码,并且你想知道某个对象、方法或属性是如何工作的,那么help函数就会派上用场。
实际上,你可能经常会从你最喜欢的搜索引擎中获得帮助,而不是使用help函数。但是如果你已经在Python REPL中,那么调用help(list.insert)要比在Google中查找list.insert方法文档快得多。
以后再学习
有一些内置函数你现在可能不需要,但最终你可能会用到。
我将提到另外14个内置函数,这些函数很容易了解,但是在你真正需要使用它们之前没有必要学习。
open
需要在Python中打开一个文件吗?那你你需要open函数!
如果你不直接处理文件?那么你可能不需要open函数!
你可能会觉得我将open函数放在这个部分有点奇怪,因为处理文件是很常见的事情。虽然大多数程序员会在某个时候使用open来读写文件,但是一些Python程序员,比如Django开发人员,可能不会经常使用open函数(如果有的话)。
一旦你需要处理文件,那你应该了解open函数。在那之前,请别担心。
顺便说一下,你可能想要查看pathlib来(它在Python标准库中)作为使用open函数的一个替代方法。我非常喜欢pathlib模块,所以我考虑过先介绍pathlib模块,然后再介绍内置的open函数来教授Python中的文件。
input
input函数提示用户输入,等待他们按下Enter键,然后返回用户输入的文本。
从标准输入中读取内容(这就是input函数所做的)是将输入获取到Python程序中的一种方法,但是也还有很多其它的方法! 你可以接受命令行参数、从配置文件读取、从数据库读取等等。
当你需要提示命令行程序的用户输入时,你需要了解这一点。在那之前,你不需要它。如果你已经编写Python有一段时间了,但是不了解这个函数,那么你可能永远都不需要它。
repr
需要一个对象的程序员可读的表示形式?那你需要repr函数!
对于很多对象来说,str和repr表示是相同的:
但对于某些对象,它们是不同的:
我们在Python REPL中看到的字符串表示使用repr函数,而print函数则依赖于str:
你将在日志记录、处理表达式和实现双下划线方法时看到repr函数被使用。
super
如果在Python中创建类,那你可能需要使用super。无论何时,当你从另一个Python类继承时,super函数都是非常重要的。
许多Python用户很少创建类。创建类不是Python的一个重要部分,尽管许多类型的编程都需要它。例如,如果不创建类,你就不能真正使用Django web框架。
如果你还不了解super,那么当你需要它的时候,你就会学习它。
property
property函数是一个装饰器和描述符(如果你非常好奇,只需要单击那些奇怪的术语去了解),当你初次了解它时,你可能会觉得它有点神奇。
这个装饰器允许我们创建一个属性,它总是包含特定函数调用的返回值。举个例子更容易理解。
下面是一个使用property的类:
下面是对Circle对象的diameter属性的一个访问:
如果你正在进行面向对象的Python编程(你正在创建一大堆类),在某些时候你可能会想要了解property。与其他面向对象的编程语言不同,我们使用property而不是getter方法和setter方法。
issubclass和 isinstance
issubclass函数检查一个类是否是一个或多个其他类的子类。
isinstance函数检查一个对象是否是一个或多个类的实例。
你可以把isinstance想象成是issubclass的代表:
如果你正在重载运算符(例如,自定义你的类上的+运算符功能),你可能需要使用isinstance,但是一般来说,我们在Python中尽量避免强类型检查,所以我们不会经常看到这些。
在Python中,我们通常更喜欢鸭子类型而不是类型检查。这些函数实际上比我上面提到的强类型检查函数(两者的行为都可以自定义)做的更多,所以实际上可以使用collections.abc.Iterable这样的抽象基类来实践一种isinstance支持的鸭子类型。但是这种情况也不多见(部分原因是我们倾向于在Python中使用异常处理和EAFP,而不是条件检查和LBYL)。
最后两段充满了令人困惑的术语,如果你有足够的兴趣,我可以在以后的文章中更详细地解释这些术语。
hasattr, getattr, setattr和 delattr
需要处理对象上的属性,但这个属性名称是动态的?那你需要hasattr、getattr、setattr和delattr。
假设我们有一个thing对象,我们想检查它的一个特定的值:
hasattr函数允许我们检查一个对象是否具有某个特定的属性(注意,hasattr有一些怪癖,不过大部分已经在Python3中解决了):
getattr函数允许我们检索该属性的值(如果该属性不存在,则使用可选的默认值):
setattr函数允许我们对该属性值进行设置:
delattr函数会删除该属性:
这些函数适用于元编程的特定风格,你可能不经常看到它们。
classmethod 和 staticmethod
classmethod和staticmethod装饰器有点神奇,就像 property装饰器一样。
如果你有一个应该在实例或类上可调用的方法,那你需要classmethod装饰器。工厂方法(等价于构造函数)是这种情况的一个常见用例:
要想出staticmethod的一个很好的用例有点困难,因为你几乎总是会使用模块级函数而不是静态方法。
上面的roman_to_int函数不需要访问实例或类,所以它甚至不需要是一个@classmethod。实际上没有必要将这个函数变成一个staticmethod(代替classmethod): staticmethod只是更加严格地表明我们不依赖于函数赖以生存的类这一事实。
我发现学习这些会让人们觉得他们需要它们,而实际上他们并不需要。如果你最终真的需要它们,你可以去查找。
next
next函数会返回迭代器中的下一项。
我以前已经写过迭代器(《for循环如何工作》以及《如何创建一个迭代器》),但是你可能会遇到一个非常简短的迭代器总结,包括:
enumerate 对象
zip 对象
reversed 函数的返回值
文件 (你从 open函数获得的东西 )
csv.reader 对象
生成器表达式
生成器函数
你可以将next看作是一种手动遍历一个迭代器去获取单个项,然后中断的方式。
也许最终会学的函数
我们已经介绍了将近一半的内置函数。
剩下的Python内置函数肯定不是无用的,只是它们有一些特殊用途。
我在本节中提到的这15个内置函数可能是你最终需要学习的内容,但也很有可能你在自己的代码中永远不会用到它们。
iter: 从一个可迭代对象获得一个迭代器:这个函数增强了for循环,当你在创建用于延迟循环的辅助函数时,它会非常有用。
callable: 如果参数是一个可调用对象,它会返回True(我在之前的文章《函数和可调用对象》中讨论过一点这个)
filter 和 map: 正如我之前在关于《过度使用lambda函数》的文章中所讨论的,我建议大家使用生成器表达式代替内置的map和filter函数。
id, locals, 和 globals: 这些是教授Python的很棒的工具,你可能已经见过它们,但是你在真正的Python代码中不会看到它们。
round: 如果你需要对一个数字进行修约,那你要查看这个函数。
divmod: 这个函数会同时执行地板除法(//)和取模运算(%)。
bin, oct, 和 hex: 如果你需要将一个数字显示为一个二进制、八进制或十六进制的字符串,那你将会用到这些函数。
abs: 当你需要取一个数字的绝对值时,你需要查看此函数。
hash: 依赖于用于测试可哈希性的hash函数的字典和集合, 不过你可能不会需要它,除非你正在实现一个灵活的重复数据删除算法。
object: 如果你需要创建唯一的默认值和标志值,这个函数(当然也是一个类)会非常有用。
你可能不会需要上面的所有内置函数,但是如果你编写Python代码的时间足够长,你可能会看到几乎所有。
你可能不需要这些
你不太可能需要这些内置函数。有些时候对于它们中的极少数来说确实会有合适的用途,但是如果你从没有了解过这些的话也没有任何影响。
ord 和 chr:它们对于教授ASCII码表和Unicode代码点来说非常有趣,但是我在我自己的代码中从来没有真正找到它们的一个用途。
exec 和 eval: 用于执行一个字符串,将其视为代码段。
compile:此函数与 exec 和 eval相关联
slice: 如果你正在实现__getitem__来创建一个自定义序列,那你可能需要这个函数(某些Python Morsels练习实际上会需要这个函数),但是除非你要创建自己的自定义序列,不然你可能永远不会看到slice。
bytes, bytearray和 memoryview: 如果你经常处理字节,你可能会用到它们中一些(在此之前只需要忽略它们)。
ascii:和 repr类似,只不过它会返回一个对象的ASCII码的表示形式;我还没有在我的代码中用到它。
frozenset: 类似于 set, 但是它是不可变的(并且是可哈希的!); 非常简洁,但是我在我的代码中还没有用到过。
__import__: 此函数实际上并不是让你使用的,你可以使用importlib来代替。
format: 此函数会调用用于字符串格式化(f-strings 和 str.format)的__format__ 方法; 你通常不需要直接调用这个函数。
pow: 乘方运算符(**)通常会代替这个函数....除非你正在执行模运算(或许你正在从零开始实现RSA 加密算法...?)
complex: 如果你不知道4j+3是有效的Python代码,那你可能不会用到complex函数。
还有更多要学的东西
Python中有69个内置函数(技术上来说只有42个是真正的函数)。
当你刚开始使用Python时,除了5个调试函数外,我建议你只关注你自己代码中的20个内置函数(10个常见的内置函数和10个经常被忽略的内置函数)。
然后,还有14个左右的内置函数,你可能会在以后学习它们(取决于你所使用的编程风格)。
然后是15个内置函数,你可能需要,也可能永远在你的代码中不会用到。有些人喜欢这些内置函数,而有些人从不使用它们: 当你在编码需求中变得更加具体时,你可能会发现自己需要更多的称心工具。
然后,我提到了最后15个你可能永远不会需要的内置函数(同样,很大程度上取决于你如何使用Python)。
你现在不需要学习所有的Python内置函数。慢慢来: 把注意力集中在前20个重要的内置函数上,然后当你最终需要它们的时候再去了解其他函数。
英文原文:https://treyhunner.com/2019/05/python-builtins-worth-learning/
译者:测试