列表和元祖的使用优化
python3 -m timeit 'x=(1,2,3,4,5,6)'
20000000 loops, best of 5: 9.97 nsec per loop
python3 -m timeit 'x=[1,2,3,4,5,6]'
5000000 loops, best of 5: 50.1 nsec per loop两三个元素,使用 tuple,元素多一点使用 namedtuple。
# option A
empty_list = list()
# option B
empty_list = []区别主要在于 list() 是一个 function call,Python 的 function call 会创建 stack,并且进行一系列参数检查的操作,比较 expensive,反观 [] 是一个内置的 C 函数,可以直接被调用,因此效率高。
>>> dis.dis(lambda : dict())
1 0 LOAD_GLOBAL 0 (dict)
3 CALL_FUNCTION 0 (0 positional, 0 keyword pair)
6 RETURN_VALUE
>>> dis.dis(lambda : {})
1 0 BUILD_MAP 0
3 RETURN_VALUE
>>> %timeit dict()
133 ns ± 2.95 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
>>> %timeit {}
74.6 ns ± 3.07 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)字符串拼接优化
Python 字符串直接进行 + 操作,是 O(n) 复杂度,n 为字符串长度。但是下面几个方法可以更快。
# method 1
s = ''
for n in range(0, 100000):
s += str(n)
# method 2
l = []
for n in range(0, 100000):
l.append(str(n))
s = ' '.join(l)
# method 3
s = " ".join(map(str, range(0, 10000)))方式三性能最优。其次,数目少的时候,+= 快,数目非常大的时候,join 更快。
for 一行语句
attributes = ['name', 'dob', 'gender']
values = [
['jason', '2000-01-01', 'male'],
['mike', '1999-01-01', 'male'],
['nancy', '2001-02-01', 'female']
]
# expected output:
[{'name': 'jason', 'dob': '2000-01-01', 'gender': 'male'},
{'name': 'mike', 'dob': '1999-01-01', 'gender': 'male'},
{'name': 'nancy', 'dob': '2001-02-01', 'gender': 'female'}]
# 一行语句
[dict(zip(attributes, value)) for value in values]函数
回顾了 global 和 nonlocal 和闭包函数。
- global 可以在函数内部修改全局变量
- nonlocal 在嵌套函数中声明一个非局部变量,可以在内部函数中访问和修改外部函数的变量。
函数式编程
关于 map()、filter() 和 reduce()三个函数,需要注意的是:
- map()在 Python 2.x 返回的是一个列表;而在 Python 3.x 中返回一个 map 类,可以看成是一个迭代器。
- filter()在 Python 2.x 中返回的是过滤后的列表, 而在 Python 3.x 中返回的是一个 filter 类,可以看成是一个迭代器,有惰性运算的特性, 相对 Python2.x 提升了性能, 可以节约内存。
- reduce() 函数在 Python3 中已经被从全局名字空间里移除了,它现在被放置在 functools 模块里,如果想要使用它,则需要通过引入 functools 模块来调用 reduce() 函数。
numbers = [1, 2, 3, 4, 5]
squared_numbers = map(lambda x: x**2, numbers)
print(list(squared_numbers))
numbers = [1, 2, 3, 4, 5, 6]
even_numbers = filter(lambda x: x % 2 == 0, numbers)
print(list(even_numbers))
from functools import reduce
numbers = [1, 2, 3, 4, 5]
sum_of_numbers = reduce(lambda x, y: x + y, numbers)
print(sum_of_numbers)成员变量的访问性
_xxx单下划线,只有类对象和子类对象自己能访问到这些变量,需通过类提供的接口进行访问;__xxx类中的私有变量/方法名,只有类对象自己能访问,连子类对象也不能访问到这个数据。
如果是私有变量,可以强行访问,但是不推荐。Python 没有完全限制访问私有。
class A:
__a = 1
class B(A):
pass
b = B()
print(b._A__a)Python 常量缓存
Python 内部会对 -5 到 256 的整型维持一个数组,起到一个缓存的作用。这样,每次你试图创建一个 -5 到 256 范围内的整型数字时,Python 都会从这个数组中返回相对应的引用,而不是重新开辟一块新的内存空间。
'==' 操作符却不同,执行 a == b 相当于是去执行 a.__eq__(b)
assert
在Python中,assert 语句用于调试目的,它允许你检查程序中的条件,并在条件为 False 时触发异常(默认是 AssertionError)。如果你希望在运行Python程序时忽略所有的 assert 语句,可以使用 Python 的 -O(优化)标志来启动解释器。当使用 -O 标志时,Python 会忽略所有的 assert 语句,并且还会生成 .pyo 文件(优化后的字节码文件),而不是标准的 .pyc 文件。
以下是如何使用 -O 标志的例子:
python -O your_script.py或者,如果你使用的是 Python 3.x 版本,命令可能会这样写:
python3 -O your_script.py当你以优化模式运行脚本时,所有的 assert 语句将被当作无操作(no-op)处理,即它们不会被执行,也不会产生任何效果。
需要注意的是,忽略 assert 语句应该仅限于生产环境中,因为 assert 是一种有用的调试工具,在开发和测试阶段不应该被忽略。assert 语句可以帮助开发者快速找到代码中的逻辑错误,确保程序按照预期工作。在发布或部署应用程序之前,你应该移除或禁用所有不应用于生产的断言。
此外,如果需要更细粒度地控制哪些 assert 语句生效或忽略,可能需要重构代码,使用条件语句或其他机制来替代 assert,并根据配置或环境变量来决定是否执行这些检查。
dis 函数
dis 函数查看字节码。