type
status
date
slug
summary
tags
category
icon
password
tips:文章内容均来自对于Python-100-Days的学习
列表的使用
列表删除数据时,可以使用:
- remove()
- pop()
- del item[k]
使用 Python 中的
del
关键字后面跟要删除的元素,这种做法跟使用 pop
方法指定索引删除元素没有实质性的区别,但后者会返回删除的元素,前者在性能上略优,因为 del
对应的底层字节码指令是 DELETE_SUBSCR
,而 pop
对应的底层字节码指令是 CALL_METHOD
和 POP_TOP
。使用列表生成式创建列表不仅代码简单优雅,而且性能上也优于使用
for-in
循环和 append
方法向空列表中追加元素的方式。为什么说生成式有更好的性能呢,那是因为 Python 解释器的字节码指令中有专门针对生成式的指令(LIST_APPEND
指令);而 for
循环是通过方法调用(LOAD_METHOD
和 CALL_METHOD
指令)的方式为列表添加元素,方法调用本身就是一个相对比较耗时的操作。元组和列表的比较
这里还有一个非常值得探讨的问题,Python 中已经有了列表类型,为什么还需要元组这样的类型呢?这个问题对于初学者来说似乎有点困难,不过没有关系,我们先抛出观点,大家可以一边学习一边慢慢体会。
- 元组是不可变类型,不可变类型更适合多线程环境,因为它降低了并发访问变量的同步化开销。关于这一点,我们会在后面讲解并发编程的时候跟大家一起探讨。
- 元组是不可变类型,通常不可变类型在创建时间上优于对应的可变类型。我们可以使用
timeit
模块的timeit
函数来看看创建保存相同元素的元组和列表各自花费的时间,timeit
函数的number
参数表示代码执行的次数。下面的代码中,我们分别创建了保存1
到9
的整数的列表和元组,每个操作执行10000000
次,统计运行时间。
输出:
说明:上面代码的执行结果因软硬件系统而异,在我目前使用的电脑上,执行 10000000次创建列表的操作时间是 0.635秒,而执行 10000000次创建元组的操作时间是 0.078秒,显然创建元组更快且二者时间上有数量级的差别。大家可以在自己的电脑上执行这段代码,把你的执行结果放到评论区,看看谁的电脑更厉害。
当然,Python 中的元组和列表类型是可以相互转换的,我们可以通过下面的代码来完成该操作。
列表和元组都是容器型的数据类型,即一个变量可以保存多个数据,而且它们都是按一定顺序组织元素的有序容器。
列表是可变数据类型,元组是不可变数据类型,所以列表可以添加元素、删除元素、清空元素、排序反转,但这些操作对元组来说是不成立的。
列表和元组都可以支持拼接运算、成员运算、索引运算、切片运算等操作,
推荐使用列表的生成式语法来创建列表,它不仅好用而且效率很高。
Tips
print的时候可以控制输出内容的颜色
rich库,产出美化的输出
Python 的字节码指令中有
ROT_TWO
和 ROT_THREE
这样的指令可以直接实现这个操作,效率是非常高的。但是如果有多于三个变量的值要依次互换,这个时候是没有直接可用的字节码指令的,需要通过打包解包的方式来完成变量之间值的交换.两个值或者三个值的交换可以直接用逗号实现.
以
r
或 R
开头的字符串,这种字符串被称为原始字符串,意思是字符串中的每个字符都是它本来的含义,没有转义字符。集合的成员运算在性能上要优于列表的成员运算,这是集合的底层存储特性决定的
集合底层使用了哈希存储(散列存储),对哈希存储不了解的读者可以先看看“Hello 算法”网站对哈希表的讲解,感谢作者的开源精神。
lambda函数
fac = lambda n: functools.reduce(operator.mul, range(2, n + 1), 1)
reduce
函数是 Python 标准库 functools
模块中的函数,它可以实现对一组数据的归约操作,类似于我们之前定义的 calc
函数,第一个参数是代表运算的函数,第二个参数是运算的数据,第三个参数是运算的初始值。很显然,reduce
函数也是高阶函数,它和 filter
函数、map
函数一起构成了处理数据中非常关键的三个动作:过滤、映射和归约。偏函数
偏函数是指固定函数的某些参数,生成一个新的函数,这样就无需在每次调用函数时都传递相同的参数。在 Python 语言中,我们可以使用
functools
模块的 partial
函数来创建偏函数。例如,int
函数在默认情况下可以将字符串视为十进制整数进行类型转换,如果我们修修改它的 base
参数,就可以定义出三个新函数,分别用于将二进制、八进制、十六进制字符串转换为整数,代码如下所示。partial
函数的第一个参数和返回值都是函数,它将传入的函数处理成一个新的函数返回。通过构造偏函数,我们可以结合实际的使用场景将原函数变成使用起来更为便捷的新函数,不知道大家有没有觉得这波操作很有意思。函数高级应用
装饰器
用一个函数”装饰”另一个函数并且为它提供额外的能力.装饰器本身是一个函数,参数是被装饰的函数,返回值是带有被装饰功能的函数.
record_time
函数的参数 func
代表了被装饰的函数,内部的 wrapper
函数是具有装饰功能的函数,执行被装饰的函数 func
,然后返回函数执行的返回值.实际执行的其实是 wrapper
函数,被装饰的 func
函数版本.语法糖
语法糖意为在编程语言中添加的某种语法,其对于语言的功能没有影响,但是使用更加方便,可读性更强.
在使用装饰器函数的时候,可以通过
@装饰器函数
的方式来将装饰器函数直接放在被装饰的函数上,以达到装饰函数的目的.如果在代码的某些地方,我们想去掉装饰器的作用执行原函数,那么在定义装饰器函数的时候,需要做一点点额外的工作。Python 标准库
functools
模块的 wraps
函数也是一个装饰器,我们将它放在 wrapper
函数上,这个装饰器可以帮我们保留被装饰之前的函数,这样在需要取消装饰器时,可以通过被装饰函数的 __wrapped__
属性获得被装饰之前的函数。装饰函数的使用示例:
lru_cache
函数是一个装饰器函数,我们将其置于上面的函数 fib1
之上,它可以缓存该函数的执行结果从而避免在递归调用的过程中产生大量的重复运算.lru_cache
函数有一个非常重要的参数叫 maxsize
,它可以用来定义缓存空间的大小,默认值是128。