【未完待续】Python 笔记
Python 笔记
记录一下 Python 的学习。
[TOC]
1. 格式化输出 str.format()
# https://www.runoob.com/python3/python3-inputoutput.html
table = {'Google': 1, 'Runoob': 2, 'Taobao': 3}
print('Runoob: {Runoob:d}; Google: {Google:d}; Taobao: {Taobao:d}'.format(**table))
import math
print('常量 PI 的值近似为 {0:.3f}。'.format(math.pi))
Runoob: 2; Google: 1; Taobao: 3
常量 PI 的值近似为 3.142。
2. 交换两个数据的值
使用 x, y = y, x
import dis
def swap1():
x = 2333
y = 6666
x, y = y, x
dis.dis(swap1)
4 0 LOAD_CONST 1 (2333)
2 STORE_FAST 0 (x)
5 4 LOAD_CONST 2 (6666)
6 STORE_FAST 1 (y)
6 8 LOAD_FAST 1 (y)
10 LOAD_FAST 0 (x)
12 ROT_TWO
14 STORE_FAST 0 (x)
16 STORE_FAST 1 (y)
18 LOAD_CONST 0 (None)
20 RETURN_VALUE
def swap2():
x = 2333
y = 6666
temp = x
x = y
y = temp
dis.dis(swap2)
2 0 LOAD_CONST 1 (2333)
2 STORE_FAST 0 (x)
3 4 LOAD_CONST 2 (6666)
6 STORE_FAST 1 (y)
4 8 LOAD_FAST 0 (x)
10 STORE_FAST 2 (temp)
5 12 LOAD_FAST 1 (y)
14 STORE_FAST 0 (x)
6 16 LOAD_FAST 2 (temp)
18 STORE_FAST 1 (y)
20 LOAD_CONST 0 (None)
22 RETURN_VALUE
显然更少指令的更快。
ROT_TWO
用于交换两个栈顶层的元素,比执行一个 LOAD_FAST+STORE_FAST
快。
3. 用 enumerate() 获取序列迭代的索引和值
li = [1, 2, 4, 6]
for i, v in enumerate(li):
print(i, v)
0 1
1 2
2 4
3 6
def enumerate(sequence, start=0):
n = start
for elem in sequence:
yield n, elem
n += 1
字典的话用.iteritems()
4. is
和 ==
的使用场景
a is b
: 判断的是 object identity(对象标识符),两个对象是否拥有同一块内存空间a == b
: 判断的是两个对象值是否相等
a = 'ohoh'
b = 'ohoh'
print('a is b:', a is b)
print(id(a), id(b))
c = '判断的是 object identity(对象标识符),两个对象是否拥有同一块内存空间'
d = '判断的是 object identity(对象标识符),两个对象是否拥有同一块内存空间'
print('d is c:', d is c)
print('d == c:', d == c)
print(id(c), id(d))
a is b: True
2765551413376 2765551413376
d is c: False
d == c: True
2765556343152 2765556343312
需要注意的是,Python 有string interning
字符串保留机制,对于较小的字符串,为了提高性能,
5. 字符串驻留机制
以下来自Python的字符串驻留机制:
- 字符串长度为0或1时,默认采用驻留机制。
- 字符串长度大于1时,且字符串中只包含大小写字母、数字、下划线时,采用驻留机制。
- 字符串只在编译时进行驻留,而非运行时。Python是解释型语言,但是事实上,它的解释器也可以是理解为是一种编译器,它负责将Python代码翻译成字节码,也就是.pyc文件。c是几个字符串的拼装,字符串的 .join() 方法是在运行期间才知道结果。所以c不支持字符串驻留。
- 用乘法得到的字符串,如果结果长度 <=20且字符串只包含数字、字母大小写、下划线,支持驻留。长度>20,不支持驻留。这样的设计目的是为了保护.pcy文件不会被错误代码搞的过大。
- 对于[-5,256]之间的整数数字,Python默认驻留
- Pyhton提供intern方法强制2个字符串指向同一个对象。
a = 'nb'
b = 'n'+'b'
c = ''.join(['n', 'b'])
print(b is a)
print(c is a)
print(b is c)
True
False
False
import sys
a = '6%2=0'
b = '6%2=0'
print(a is b)
b = sys.intern(a)
print(a is b)
False
True
6. 没有自增
++i
会被解释为+(+i)
i++
则是SyntaxError
--
同理
7. finally 执行的坑
无论try
里是否有异常抛出,finally
总是会执行。
class 老子抛出来了(Exception):
pass
while(True):
try:
print('准备抛出')
raise 老子抛出来了('其实它不会出来')
except NameError as e:
print('不会有滴', e)
finally:
print('嘿嘿嘿')
break
准备抛出
嘿嘿嘿
当try
里发生异常,且except
里没有对应的异常处理,异常会被临时存储,等finally
执行完后再抛出,但在finally
里用了break
或return
,那么临时存储的异常就会丢失,导致异常屏蔽。
def 返回():
try:
return -1
except:
return -2
finally:
return -3
返回()
-3
执行try
里的return
前,会先执行finally
里的return
8. 大规模连接字符串优先用join
而非+
Python 里的字符串为不可变对象。
每次执行+
操作就要申请一块新的内存空间,然后进行复制操作,大概$$o(n^2)$$。
join
大概$$O(n)$$
import timeit
test_time = [1, 3, 5, 7, 10, 50, 100, 1000, 10000, 100000, 1000000]
strlist = []
str_source = 'oh 我的老伙计,该洗洗睡了啊'
def join_test():
return ''.join(strlist)
def plus_test():
ret = ''
for v in strlist:
ret += v
return ret
for i, v in enumerate(test_time, 1):
strlist = [str_source for x in range(v)]
join_timer = timeit.Timer("join_test()", "from __main__ import join_test")
print('join-{0}-{2}: {1}'.format(i, join_timer.timeit(10), v))
for i, v in enumerate(test_time, 1):
strlist = [str_source for x in range(v)]
plus_timer = timeit.Timer("plus_test()", "from __main__ import plus_test")
print('plus-{0}-{2}: {1}'.format(i, plus_timer.timeit(10), v))
join-1-1: 0.00011280000001079316
join-2-3: 8.600000001024455e-06
join-3-5: 4.699999976764957e-06
join-4-7: 5.399999963628943e-06
join-5-10: 7.500000037907739e-06
join-6-50: 1.989999998386338e-05
join-7-100: 1.7800000023271423e-05
join-8-1000: 0.0003618000000642496
join-9-10000: 0.002106799999978648
join-10-100000: 0.029422100000033424
join-11-1000000: 0.34234780000008413
plus-1-1: 6.100000064179767e-06
plus-2-3: 8.999999977277184e-06
plus-3-5: 1.0900000006586197e-05
plus-4-7: 1.6200000004573667e-05
plus-5-10: 1.5800000028320937e-05
plus-6-50: 0.00022269999999480206
plus-7-100: 0.00026260000004185713
plus-8-1000: 0.0032113999999410225
plus-9-10000: 0.02999529999999595
plus-10-100000: 6.14744189999999