廖雪峰的Python笔记

1
2
3
4
5
6
类名:驼峰式 和首字母缩略词:HTTPWriter 优于 HttpWriter。
变量名:lower_with_underscores
方法名和函数名:lower_with_underscores
模块名:lower_with_underscores.py(不带下划线的名字更好)
常量名:UPPER_WITH_UNDERSCORES
预编译的正则表达式:name_re
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
不要去刻意对齐注释,后期维护代码会增加麻烦
采用#来进行多行注释
标准方法注释
def f(a, b):
"""
To sum two ints
:arg:
a: int
b: int
:return:
c: int
"""
c = a + b
return c
if __name__ == '__main__':
print(f.__doc__)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
print("I'm ok") # I'm ok 字符串内外引号要不同,否则转义
print('I"m ok') # I"m ok
print('I\'m ok') # I'm ok 抑制转义
print(r'I\'m ok') # I\'m ok 抑制转义
print('''aaa # 换行打印
bbb
ccc''')
print(9/3) # 3.0 浮点型除法
print(9//3) # 3 取整
print(9 % 3) # 0 取余
print('%10s:%10s' %('a','b') # 插入变量,10s控制长度可对齐
print(), # 逗号抑制换行
print('start : {:0.3f}'.format(0.123456))
print('start : {:3s}'.format('a'))
print('start : {:5s}{:5s} '.format('a', 'b'))
1
2
3
4
5
6
7
s = 'My name is captain'
s_list = s.split()
for i in range(len(s_list)):
s_list[i] = s_list[i].upper() # 可以全变大写,lower小写
for i in s_list: # 不可全变大写,for循环中的i是临时变量
i = i.upper()
s_caps_equal = ' '.join(s_list) # join的用法:‘分隔符’.join(字符串序列)
1
2
3
4
5
6
7
8
9
10
11
L = [x for x in range(6)] # [0, 1, 2, 3, 4, 5] 列表生成式
L = list(range(0, 6)) # [0, 1, 2, 3, 4, 5]
L1 = L[0:4] # [0, 1, 2, 3]
L2 = L[-4:] # [2, 3, 4, 5]
L3 = L[:4:2] # [0, 2]
L4 = L[::2] # [0, 2, 4]
# tuple也可以用切片操作,只是操作的结果仍是tuple
# 字符串也可以用切片操作,只是操作结果仍是字符串
1
2
3
4
5
6
7
8
9
10
11
# dict的items()可以同时迭代key和value
for k, v in d.items():
print(k, '=', v)
for k in d:
print(k, d[k])
# Python内置的enumerate函数可以把一个list变成索引-元素对,可访问下标
l = ['a', 'b', 'c']
for i, v in enumerate(l):
if i == 2:
print(v)
1
2
3
l = (x for x in range(6)) # 列表生成式[] vs 生成器(), 循环访问不变/next(l), 防止内存爆
for i in l:
print(i)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
def fib(n):
a, b, i, res = 1, 1, 1, 0
while i < n:
yield a
temp = a
a = b
b = temp + b
i = i + 1
res = res + temp
return res
f = fib(6) # 返回生成器对象
# for v in f:
# print(v) # 打印生成器yield的内容1,1,2,3,5
while True:
try:
print(next(f))
except StopIteration as e:
print(e.value) # 打印return的res=12
break
1
2
3
4
5
6
7
8
9
10
11
12
def f(x):
return x*x
r = map(f, list(range(1, 6))) # map将传入的函数依次作用到序列的每个元素,好处是能一眼看明白
print(r) # <map object at 0x031721F0>, r是一个迭代器,是惰性序列
res = list(r)
print(res) # [1, 4, 9, 16, 25]
******
from functools import reduce
def f(x, y):
return x*10 + y
r = reduce(f, list(range(1, 6))) # reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)
print(r) # 12345, 返回类型为参数类型
1
2
3
4
5
6
7
8
from functools import reduce # map/reduce的应用,思想:对序列做同一函数运算
def str2int(s):
def char2num(i):
return {'0':0, '1':1, '2':2, '3':3, '4':4, '5':5, '6':6, '7':7, '8':8, '9':9}[i]
def fn(x, y):
return x*10 + y
return reduce(fn, list(map(char2num, s)))
print(str2int('12345')) # int:12345
1
2
3
4
5
6
# filter()把传入的函数依次作用于每个元素,然后根据返回值是True还是False决定保留还是丢弃该元素
def is_odd(x):
return x % 2 == 1
l = filter(is_odd, list(range(1, 6)))
print(l) # <filter object at 0x036D21B0>
print(list(l)) # [1, 3, 5]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
def generate_num():
n = 1
while True:
n = n + 2
yield n
def not_divisible(n):
return lambda x: x % n > 0 # 匿名函数lambda 参数:返回值
def prime():
yield 2
it = generate_num()
while True:
n = next(it)
yield n
it = filter(not_divisible(n), it)
for i in prime(): # 求素数,结合了generator和filter, 理解了即理解了generator和filter
if i < 100:
print(i)
else:
break
1
2
3
4
5
# sorted()函数也是一个高阶函数,可以接收一个key函数来实现自定义的排序
sorted([36, 5, -12, 9, -21])
sorted([36, 5, -12, 9, -21], key=abs)
sorted(['bob', 'about', 'Zoo', 'Credit'])
sorted(['bob', 'about', 'Zoo', 'Credit'], key=str.lower)
1
2
3
4
5
6
7
8
9
10
11
12
13
def log(func): # 装饰器
def wrapper(*args, **kw):
print('call %s' % func.__name__)
return func(*args, **kw)
return wrapper
@log
def now():
print('hello world')
now() # call now hello world, @log放到now()函数的定义处,相当于执行了语句:now = log(now)
# 现在同名的now变量指向了新的函数
now = log(now)
1
2
3
4
5
6
7
8
9
10
11
12
13
# 返回闭包时牢记的一点就是:返回函数不要引用任何循环变量,或者后续会发生变化的变量
def my_sum(l):
def do_sum(): # 不需要立刻计算,而是在后面的代码中,根据需要再计算
res = 0
for i in l:
res = res + i
return res
return do_sum
if __name__ == '__main__':
f = my_sum(list(range(1, 6)))
print(f) # <function my_sum.<locals>.do_sum at 0x02B7C618>
print(f()) # 15
1
2
3
4
def my_abs(x):
if not isinstance(x, (int, float)): # 判断参数类型
raise TypeError('bad operand type')
pass
1
2
3
4
5
6
def power(x, n=2): # 设置默认参数 power(2)=4, power(2,3)=8
s = 1
while n > 0:
n = n - 1
s = s * x
return s
1
2
if __name__=='__main__': # 运行测试,其他py文件引用此句将失效
test() # 特殊变量:__xx__,自己定义不能用特殊变量
1
2
3
4
5
6
7
8
9
10
11
def _f1(name): # private,继承时将内部逻辑隐藏,加1/2个下划线
return 'Hello, %s' % name
def _f2(name):
return 'Hi, %s' % name
def f(name): # public
if len(name) > 3:
return _f1(name)
else:
return _f2(name)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Student(object): # 括号中为父类,没有就用object
def __init__(self, name, score): # 第一个参数永远是self,向创建的实例本身
self.__name = name
self.__score = score # private:属性的名称前加上两个下划线
def print_score(self): # 不用传参,类内可直接调用
print('%s: %s' % (self.__name, self.__score))
if __name__ == '__main__':
s1 = Student('zp', 23)
s1.print_info()
print(s1.__name) # 会报错没有此属性,因为是private属性
print(s1.__age)
1
2
3
4
5
6
7
8
9
10
11
12
class Animal(object):
def run(self):
print('Animal is running...')
class Dog(Animal): # Dog继承Animal
def run(self):
print('Dog is running...')
dog = Dog()
dog.run() # Dog is running...
res1 = isinstance(dog, Dog) # 子类的run()覆盖了父类的run(),体现多态
res2 = isinstance(dog, Animal) # 都为True,多态本质
1
2
3
type()判断对象类型
isinstance()判断有继承的class类型
dir()获得一个对象的所有属性和方法,无论private或public
1
2
class Student(object):
name = 'Student' # 类属性 优先级低于self,没有实例属性则访问类属性
1
2
3
4
5
6
7
class Student(object):
__slots__ = ('name', 'age') # 用tuple定义允许绑定的属性名称
s = Student()
s.name = 'Michael' # 绑定属性'name'
s.age = 25 # 绑定属性'age'
s.score = 99 # AttributeError
1
2
3
主线都是单一继承下来的,需要“混入”额外的功能可通过多重继承实现,这种设计通常称之为MixIn
class MyTCPServer(TCPServer, ForkingMixIn): # 多进程模式的TCP服务
pass
1
2
3
4
5
6
7
class Student(object):
def __init__(self, name):
self.name = name
def __str__(self): # 定制类,打印的好看
return 'Student object (name: %s)' % self.name
print(Student('Michael')) # Student object (name: Michael)
1
2
3
4
5
6
7
class Student(object):
def __init__(self, name):
self.name = name
def __str__(self): # __str__()返回用户看到的字符串
return 'Student object (name=%s)' % self.name
__repr__ = __str__ # __repr__()返回程序开发者看到的字符串,是为调试服务的
# 通常__str__()和__repr__()都是一样
1
2
3
4
5
6
7
8
def say_hello(self, name):
print('hello %s' % name)
zp = type('Hello', (object,), dict(hello=say_hello)) # type动态创建类
print(type(zp)) # zp是type类型,可理解为zp是Hello类的动态创建器
cwy = zp()
print(type(cwy)) # cwy是Hello类型
cwy.hello('cwy')
1
2
3
4
5
6
7
8
9
10
11
12
13
class ListMetaClass(type): # 元类
def __new__(cls, name, bases, attrs):
attrs['add'] = lambda self, value: self.append(value) # add=append
return type.__new__(cls, name, bases, attrs)
class MyList(list, metaclass=ListMetaClass):
pass # 指示Python解释器在创建MyList时,要通过ListMetaclass.__new__()来创建
L = MyList()
L.add(1) # [1]
print(L)
L.append(2)
print(L) # [1,2]
1
2
3
4
5
from enum import Enum
Month = Enum('Month', ('Jan', 'Feb', 'Mar')) # 非精确的枚举类
print(Month.Jan.value) # value属性是自动赋给成员的int常量,默认从1开始
for name in Month:
print(name, name.value)
1
2
3
4
5
6
7
8
9
from enum import Enum, unique
@unique # @unique装饰器可以帮助检查没有重复值
class Weekday(Enum): # 精确的枚举类
Sun = 0
Mon = 1
Tue = 2
print(Weekday.Sun.value)
for name in Weekday:
print(name, name.value)
1
2
3
4
5
6
7
8
9
10
11
12
def foo(s):
n = int(s)
if n==0:
raise ValueError('invalid value: %s' % s)
return 10 / n # 中断自己抛出错误,让调用函数去处理错误
def bar():
try:
foo('0')
except ValueError as e:
print('ValueError!')
raise # 当前函数不知道应该怎么处理该错误,继续往上抛让顶层调用者处理
1
2
3
4
5
6
7
8
9
import logging
logging.basicConfig(level=logging.INFO)
s = '0'
n = int(s)
logging.info('n = %d' % n)
print(10 / n)
# logging代替print,logging级别有debug、info、warning、error等几个级别,当我们指定如level=INFO时,logging.debug就不起作用了;logging通过简单的配置,一条语句可以同时输出到不同的地方,比如console和文件
1
2
3
read()会一次性读取文件的全部内容,内存易爆
readlines()一次性读取所有内容并按行返回list
readline()每次读取一行内容
1
2
3
4
5
6
r:读
w: 写 # 写/追加不存在则创建,二进制同
r+:读写
w+:读写
a:追加写
a+: 追加读写
1
2
3
4
5
with open('dsjtzs_txfz_training_sample.txt') as f:
line = f.readline()
while line:
print(line)
line = f.readline() # 非一次性读进内存
1
2
3
4
5
6
7
8
import os
dirs = [x for x in os.listdir('C:\\Users\\captianzp\\Documents')
if os.path.isdir(os.path.join('C:\\Users\\captianzp\\Documents', x))]
print(dirs)
# 遍历当前目录,isdir采用绝对路径,os.path.join方便连接路径
print(os.path.split('C:\\Users\\captianzp\\Documents'))
# 分割路径 ('C:\\Users\\captianzp', 'Documents'),后一部分总是最后级别的目录或文件名
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import pickle # 序列化: 把变量从内存中存储到文件中
d = {'name': 'Bob', 'age': 23, 'score': 90}
res = pickle.dumps(d) # pickle.dumps()方法把任意对象序列化成一个bytes
d = pickle.loads(res) # pickle.loads()方法反序列化出对象
f = open('dump.txt', 'wb')
pickle.dump(d, f) # pickle.dump()直接把对象序列化后写入一个文件
f.close()
f1 = open('dump.txt', 'rb')
d = pickle.load(f1) # pickle.load()从一个文件中直接反序列化出对象
f1.close()
1
2
3
4
5
6
7
8
9
10
11
import json
d = {'name': 'Bob', 'age': 23, 'score': 90}
print(type(d)) # dict
res = json.dumps(d)
print(type(res)) # str,json.dumps()方法把任意对象序列化成一个bytes
d = json.loads(res)
print(type(d)) # dict,json.loads()方法反序列化出对象
# json.dump()、json.load()用法与pickle相同,写入文件