Tip:
(1).py文件首行添加 #!/usr/bin/python3 后,py文件变成可执行文件;
(2)'/'即使可以整除也会返回浮点型结果;
(3)计算机内存中,统一使用Unicode编码,当需要保存到硬盘或者需要传输的时候会转换为UTF-8编码。
(4)python中的编码问题:
- ord('char')、chr(n)
- bytes类型:基本格式为:b'字符串',bytes类型中的每个字符占用一个字节
- 以Unicode表示的str通过encode()方法可以编码为指定的bytes,如:'中国'.encode('utf-8')
- 从网络或磁盘上读取了字节流,那么读到的数据就是bytes。要把bytes变为str,就需要用decode()方法,如:
x = b'\xe4\xb8\xad\xe5\x9b\xbd'
x.decode('utf-8')
- len()函数作用于bytes类型用于获取字节数
(5)在.py文件开头添加:# -*- coding: utf-8 -*-,用于指定解释器按照utf-8编码读取文件;
(6)input()接收的输入值默认是字符串类型,如果要进行数值运算需强转为数值类型;
(7)type(var) //获取变量var的类型
(8)isinstance(obj,cls) //判断obj是否为cls类型实例;cls可传多个,用括号括起来
(9)逻辑运算符:and、or、not;
(10)python中以'__'开头且以'__'结尾的变量是特殊变量,并非私有变量
(11)获取CPU核数:multiprocessing.cpu_count()
1、基本数据类型:type(var):获取变量类型
(1)int、float:
除法运算默认结果为浮点型,'//'表示整除;
** 表示乘方;
% 表示取模;
+=、-=、/=、*=;
int(str)用于将字符串转为int类型,且str必须是纯数字字符串;
(2)字符串:"..."
、'...'
str[n|-n]:获取变量str指定[倒数]指定位置上的字符;
str[m:n]:获取变量str`m至n`位置的字符串(`不能以负数开头`、`n为负数时m表示截取长度`);
字符串复制:str * n;
str.split('*')、str.upper()、str.lower()、len(str)...
int(str):将str转为int类型
'char' in[not in] str:判断str中是否包含char
格式化:
format函数:`str = "姓名:{0},年龄:{1}".format("张三",20)`;
f\fr+str:`f'姓名:{var1},年龄:{var2}'`;// fr用于格式化有特殊字符的字符串
%s用于占位,使用%符号进行格式化,如:'Hi %s,你 %s 岁了' % ('张三', 20) => 'Hi 张三,你 20 岁了'.
(3)布尔型:True、False;
(4)空值:None
2、内置数据类型:
(1)list(有序可变列表):[value1、value2...]
arr[n|-n]:获取第n个或倒数第n个元素,最后一个元素的位置是-1;
arr[m:n]:获取第m到第n个元素,不包括第n个元素,m为0时可以省略;
arr[x:y:z]:获取集合中位置从x到y且不包括y,步长为z的元素;
+ :列表拼接
arr.append(item):添加元素
insert(index,item):在指定位置index添加item
arr.pop([n]):删除并返回arr中第n个元素,n为空则删除并返回最后一个元素;
arr.remove(n):删除arr中值为n的元素(如果arr中n元素有多个,则只删除第一个);
del(arr[n]):删除arr中下标为n的值;
len(arr):获取列表长度;
arr.count("value"):获取列表中值为value的元素个数
set(list):去重,生成一个新的列表
sorted(list):排序,生成一个新的列表
list(Obj):将obj转换为list
简单遍历——格式:[item处理逻辑 for item in list];
(1)将list中的每一项乘以2:
prices = [1,2,3,4,5]
double_prices = [price * 2 for price in prices]
(2)将列表中偶数的乘方生成一个新的集合:
prices = [1,2,3,4,5]
squart_even_price = [price ** 2 for price in prices if price%2 == 0]
(2)tuple(元组,有序且不可变的列表):格式:(value1、value2...)
只有1个元素的tuple定义时必须加一个逗号,,来消除歧义:(1,);
元组不可变指的是元组中元素的引用不可变;
(3)dict(字典):
(1)基本格式:
dict = {"key1":"value1","key2":"value2"...}或dict(key="value",key1="value1"...) //key值相同会发生覆盖
(2)根据key查找value:
dict["key"]; //不存在则报错
dict.get('key'[, default]); //不存在则返回None,也可以指定不存在时的默认返回值
(3)判断字典中是否有对应的key:"key" in dict;
(4)获取所有key值:dict.keys();
(5)获取所有value值:dict.values();
(6)添加/修改值:dict["key"] = "value" //如果dict中key已存在则为更新操作
(7)删除:del dict["key"]
(8)遍历:for key,value in dict.items();
(4)set(无序且不可重复的列表):
创建:set1 = set([...]) 或 set1 = {value1、value2...};
添加元素:add(val)
删除元素:remove(val)
3、条件分支:
if condition1:
#...
elif condition2:
#...
else:
#...
4、循环:
(1)for循环:
for item in collection:
#...
注:所有可遍历的对象都可以通过for循环进行遍历,如:list、tuple、dict、str等,使用如下可以判断一个对象是否可以遍历:
from collections import Iterable
number = 123
print(isinstance(number, Iterable))
(2)while循环:
while condition:
#...
(3)break与continue;
(4)list遍历同时获取对应的下标:
numbers = [1, 2, 3, 4, 5]
for index,item in enumerate(numbers):
print(index, '-' ,item)
(5)for循环遍历过程中使用两个变量:
numbers = [(1, 2), (3, 4), (5, 6)]
for x, y in numbers:
print(x, '-', y)
注:两个变量的本质是对for循环循环变量再次进行遍历获取到的,因此循环使用两个变量需要集合中的元素是可遍历的。
5、range()方法:
range(n):从0开始,递增打印n位;
range(start,end):从start开始,递增打印至end-1;
range(start,end,step):从start开始,递增打印至end-1,递增步长为step;
6、内置函数:
abs(n)、max(n1,n2...)、int(str)/float(str)/str(n)/bool(n)、hex(n)...
7、自定义函数:
(1)函数定义时可以指定默认参数值,但默认值参数必须置于必选参数后面;
(2)函数调用时默认值参数需要使用:参数名=参数值 的形式,如果不指定默认参数名,则按默认值参数顺序传入;
(3)默认参数必须指向不变对象! 如:可变参数不能为list
(4)函数实现可以使用 pass 占位。
(5)函数可以同时返回多个值,但其实就是一个tuple。
(6)函数定义时使用'*arg'表示可变参数,arg在调用时实际接收的是一个tuple,也可以是一个list。如:
def f1(*args):
sum = 0
for n in var:
sum += n
return sum
#传入多个参数
print(f1(1,2,3))
#传入list,注意list类型参数前需加'*'
list1 = [1, 2, 3]
print(f1(*list1))
(7)关键字参数:'**kwargs',如:
def f1(name, age, **kargs):
return {'name': name, 'age': age, 'other': extra}
print(f1('张三', 20, address='beijing', sex='男'))
// 输出:{'name': '张三', 'age': 20, 'other': {'address': 'beijing', 'sex': '男'}}
关键字参数在函数内接收实际是一个字典。
(8)命名关键字参数:用于对关键字参数名称进行限制;'*'用于分割关键字参数与位置参数,但如果函数定义中已经有了一个可变参数,
后面跟着的命名关键字参数就不再需要一个特殊分隔符*了:
def f1(name, age, *, address):
print(f'姓名:{name},年龄:{age},地址:{address}')
f1('张三', 20, address='北京')
---
def f1(name, age, *nums, address):
print(f'姓名:{name},年龄:{age},可变参数:{nums},地址:{address}')
list1 = [1, 2, 3]
f1('张三', 20, *list1, address='北京')
(9)参数组合顺序:必选参数、默认参数、可变参数、命名关键字参数和关键字参数。
8、生成器(generator函数
):在一个函数中有yield
关键字,则当前函数执行后生为一个生成器,可以通过调用next(g)
或通过循环获取生成器生成的值。它是在for循环的过程中不断计算出下一个元素,并在适当的条件结束for循环。对于函数改成的generator来说,遇到return语句或者执行到函数体最后一行语句,就是结束generator的指令,for循环随之结束。
(1)通过list简单遍历获取生成器:g = (n**2 for n in numbers) // 将简单遍历的'[]'替换为'()'
(2)通过函数定义获取生成器:
def fib(max):
index, m, n = 0, 0, 1
while index < max:
yield n
m, n = n, m + n
index += 1
// 函数执行得到生成器
g = fib(5)
// for循环遍历
for i in g:
print(i)
// 通过next(g)函数遍历
while True:
try:
item = next(g)
print(item)
except StopIteration as e:
print('generator return value: ', e)
break
9、迭代器(iterator
):Iterator对象表示的是一个数据流,Iterator对象可以被next()
函数调用并不断返回下一个数据,直到没有数据时抛出StopIteration错误。可以把这个数据流看做是一个有序序列,但我们却不能提前知道序列的长度,只能不断通过next()函数实现按需计算下一个数据,所以Iterator的计算是惰性的,只有在需要返回下一个数据时它才会计算。
(1)凡是可作用于for循环的对象都是Iterable类型;
(2)凡是可作用于next()函数的对象都是Iterator类型,它们表示一个惰性计算的序列;
(3)集合数据类型如list、dict、str等是Iterable但不是Iterator,不过可以通过iter()函数获得一个Iterator对象。
(4)Python的for循环本质上就是通过不断调用next()函数实现的,即:
numbers = [1, 2, 3, 4, 5]
for number in numbers:
print(number)
#上述for循环等价于下面的部分
g = iter(numbers)
while True:
try:
print(next(g))
except StopIteration:
# 遇到StopIteration异常退出循环
break
10、高阶函数:函数化参数
(1)函数名称就是一个指向函数体的变量,可以赋值给其他变量,所以函数也可以作为参数传给其他函数;
(2)map():接收两个参数,一个是函数,一个是Iterable,map将传入的函数依次作用到每个元素,并把结果作为新的Iterator返回;
由于结果r是一个Iterator,Iterator是惰性序列,因此通过list()函数让它把整个序列都计算出来并返回一个list。
names = ["hello","python"]
short_line_names = []
def short_line_join(word):
words = list(word)
return '-'.join(words)
short_line_names = list(map(short_line_join,names))
(3)reduce():把一个函数作用在一个序列上,这个函数必须接收两个参数,reduce把结果继续和序列的下一个元素做累积计算
# 累加求和
def add(x, y):
return x + y
list1 = [1,2,3,4,5]
sum_num = reduce(add, list1)
print(sum_num)
---
#map结合reduce实现字符串转int
from functools import reduce
st1 = '123456'
DIGITS = {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}
def str2int(s):
def add(x, y):
return x * 10 + y
def char2int(c):
return DIGITS[c]
return reduce(add, map(char2int, list(s)))
print(str2int(st1))
(4)filter:filter()也接收一个函数和一个序列。和map()不同的是,filter()把传入的函数依次作用于每个元素,然后根据返回值
是True还是False决定保留还是丢弃该元素。
注意:filter()函数返回的是一个Iterator,也就是一个惰性序列,所以要强迫filter()完成计算结果,需要用list()函数获得所有
结果并返回list。
(5)排序算法:sorted(list[,key=fn(),reserve=True|False]) //iterable表示一个可遍历的对象;fn()表示将list中的每一个对象
经过函数fn()处理,并根据返回结果对原list进行排序;reserve表示是否逆序排序。
L = [('Bob', 75), ('Adam', 92), ('Bart', 66), ('Lisa', 88)]
print(sorted(L, key=lambda x: x[0], reverse=True))
(6)函数返回函数:一个函数可以返回一个计算结果,也可以返回一个函数。返回的函数不会立刻执行,需要调用才能执行。
def outer_fn(*args):
def sum():
result = 0
for i in args:
result += i
return result
return sum
list_arg = [1,2,3]
s1 = outer_fn(*list_arg)
print(s1())
(7)匿名函数:lambda x: x处理
squarts_list = list(map(lambda x:x**2,origin_list))
等价于:
def f(n):
return n**2
squarts_list = list(map(f,origin_list))
11、变量作用域:
(1)global(全局变量):定义在函数外部的变量;
(2)local(局部变量):定义在函数内部的变量;
(3)在函数内部使用global修饰的变量会变为全局变量;
(4)globals().keys():获取所有全局变量
(5)locals().keys():所有所有局部变量
12、module与package:
(1)一个.py文件称为一个模块;一个module中可以包含多个类、多个函数等
(2)如果想要一个package可以被其他类所引用,需要在该package下建立一个空的新文件,文件名为: __init__.py
(3)模块代码标准模板:
# !/usr/local/bin/python3
# -*- coding:utf-8 -*-
'module描述'
__author__ = '作者'
#代码正文开始
(4)位于不同级目录下的module导入:
import sys
sys.path.append("指定路径")
import car // 模块名称
(5)变量名或函数名以'_'开头的,不建议在其他模块中直接引用,可以理解为模块私有的。
(6)第三方模块引入:通过 pip3 install 模块名称 下载,通过import引入。
(7)reload(**):重新导入
13、装饰器(Decorator
):在代码运行期间动态增加功能的方式
# 修饰器函数接收一个函数参数,返回一个函数,并在返回的函数中调用参数函数
def log(fun):
def print_log(user_name):
print('call %s()' % fun.__name__)
fun(user_name)
return print_log
@log
def print_date(user_name):
print('hello %s' % user_name)
print_date('张三')
---
#含有参数的修饰器形式:
import functools
def log(text):
def decorator(fun):
@functools.wraps(fun)
def wrapper(user_name):
print('修饰器参数:%s' % text)
print('%s() 开始执行' % fun.__name__)
fun(user_name)
print('%s() 执行完毕' % fun.__name__)
return wrapper
return decorator
@log('hello')
def print_date(date):
print(date)
print_date('2019-11-20')
注:被修饰器修饰的函数执行时由于实际执行的是修饰器返回的函数,因此其'__name__'属性也变成了修饰器返回函数的名称,可通过在修饰器
内返回函数添加'@functools.wraps(参数函数)'防止该情况(需先导入functools)。
14、偏函数:当函数的参数个数太多,需要简化时,使用functools.partial可以创建一个新的函数,这个新函数可以固定住原函数的部分参数,从而在调用时更简单。
int(str[,base=2])函数可以将str转为整形,base参数表示进制转换类型,默认为10;
# 将int函数的base参数固定位8,生成一个新函数
int2 = functools.partial(int, base=8)
print(int('0110', base=2))
15、面向对象:
isinstance(obj, class):判断obj是否是class类型
(1)构造方法(__init__(self,arg1,arg2...)):
该方法的第一个参数永远是self,表示创建的实例本身,因此,在__init__方法内部,就可以
把各种属性绑定到self,因为self就指向创建的实例本身;
有了__init__方法,在创建实例的时候,就不能传入空的参数了,必须传入与__init__方法
匹配的参数,但self不需要传,Python解释器自己会把实例变量传进去
(2)类属性:
所有类实例公用的属性,定义在类中init方法之外,可以通过类或者对象调用;
通过类名修改的类属性,所有实例都会受受影响;
通过对象修改的类属性,只有该实例的类属性受影响而不会影响其他对象的该类属性值;
(3)类方法:
所有类实例公用的方法,使用 @classmethod 修饰,至少一个形参表示当前类(通常为cls);
类方法中可以对类属性进行修改,且无论使用类还是实例调用类方法对类属性进行修改,都会影响到所有的实例;
(4) 静态方法:
使用@staticmethod 修饰,与类方法的区别是无需传递类参数;
通常用于工具类中封装的工具方法;
可以通过类或者实例调用;
(5)普通方法:至少一个参数表示当前对象,通常为self;通过实例对象调用;
(6)私有属性/私有方法:以'__'开头,不能在类外部直接访问,子类不能继承。
(7)继承与多态:
python中类可以同时继承多个父类,但通常只有主父类,其他只是为了拥有某个功能而继承,这样的功能型父类命名格式通常为
"classNameMixIn",如:'FlyableMixIn'。
(8)dir(obj):获取对象内的所有属性和方法
hasattr(obj, feildName);
getattr(obj, feildName);
setattr(obj, feildName, value)
(9)私有化属性/方法:以'_'开头,禁止import导入。
(10)魔法对象/属性:__class__、__dict__、__init__()、__str__...
(11)代码案例:
#类名后括号内表示继承自哪个类型,如果没有则为object,可以多继承
class Dog(object):
#类属性
brand = "二哈"
#类方法
@classmethod
def getBrand(cls):
return cls.brand
@classmethod
def setBrand(cls,newBrand):
cls.brand = newBrand
@staticmethod
def staticMethod(str):
return f"参数为:{str}"
# init方法,color为私有属性
def __init__(self,name,color):
self.name = name
self.__color = color
#普通方法
def say(self):
return f"{self.name} is 一只 {self.brand},{self.color}的"
#init方法的调用
dog = Dog("tom","黑色")
dog1 = Dog("jack","白色")
print(Dog.getBrand())
print(dog.say())
print(dog1.say())
dog.setBrand("拉布拉多")
print(dog.say())
print(dog1.say())
print(Dog.staticMethod("哈哈"))
print(dog.staticMethod("嘿嘿"))
16、面向对象高级特性:
(1)实例创建后可以动态绑定参数和方法:
from types import MethodType
class Animal(object):
def __init__(self, name, color):
self.name = name
self.color = color
def run(self):
print('Animal is running!')
def set_name(self, name):
self.name = name
animal = Animal('Tom', 'red')
animal.age = 30
animal.set_name = MethodType(set_name, animal)
animal.set_name('ZS')
print(animal.name)
注:通过实例设置的属性和方法对其他实例无效,通过类名绑定的属性或方法对所有实例有效。
(2)__slots__ = (feild1,feild2...) 用于限制可以为实例动态添加的属性。
(3)@property修饰器用于将一个getter方法变为属性,结合@属性名.setter注解可以实现属性的可读可写设置
class Animal(object):
def __init__(self, color):
self.__color = color
@property
def color(self):
return self.__color
@color.setter
def set_color(self, value):
self.__color = value
a = Animal('black')
print(a.color)
a.set_color = 'red'
print(a.color)
(4)定制类:
__str__():定制对象print时内容
__iter__()、__next__():前者返回一个迭代对象使类实例可迭代,后者返回迭代时调用next()方法返回的内容
__getitem__():定制通过下表访问对象时返回的内容
__getattr__():定制获取对象属性不存在时的返回内容
__call__():定制直接调用实例时的执行语句
callable(var):判断一个对象是否可以调用
(5)枚举类:
通过Enum()函数创建:Sex = Enum('sex', ('man', 'woman'))
定制枚举值:
@unique
class WeekEnum(Enum):
Mon = 1
Tue = 2
Wen = 3
Thr = 4
遍历:
for member in Sex.__members__.items():
pass
(6)type类型:等价于Java中的Class类型
通过type()函数动态创建类:
def fn(self, name):
print('hello %s' % name)
# 参数一:类名
# 参数二:父类,通过一个tuple类型提供
# 参数三:方法绑定
People = type('People', (object,), dict(sayHi=fn))
p = People()
p.sayHi('Tom')
(7)metaclass(元类):用于定义一个类的创建模板
https://www.liaoxuefeng.com/wiki/1016959663602400/1017592449371072
17、异常处理:
(1)异常的捕获:
try:
pass
# 捕获异常
except *Exception as e:
# 未捕获或向上抛出异常,代码块之后的语句不再继续执行;如果只是输出或日志记录会继续执行代码块后的代码
raise *Exception(...)
# 未发生异常时执行
else:
pass
# 无论是否异常都会执行的方法
finally:
pass
(2)调试:
logging、assert...
(3) 单元测试:#TODO
(4) 文档测试:#
18、IO:
(1)文件读取:
f = open(filePath, ['r'|'rb'], [encoding='***']) //参数2表示文件打开方式,r表示读取普通文本,rb表示读取二进制文件;
encoding表示读取时使用的字符编码
f.read([n]) //读取文件,可以指定读取的字符数
f.close() //关闭文件
f.readline()、f.readlines()
(2)文件写入:
f = open(filePath, ['w'|'wb'|'a']) //参数二表示写模式,w表示覆盖写,wb表示二进制文件写入,a表示追加写
f.write(***)
(3)以自动关闭的方式打开文件:with open(filePath, 'r|w...') as file: ...
(4)StringIO、BytesIO:在内存中读写字符串/二进制数据
from io import StringIO, BytesIO
str = StringIO()
str.write("hello world")
print(str.getvalue())
bytes = BytesIO()
bytes.write('中国'.encode('utf-8'))
print(bytes.getvalue())
19、文件与目录操作:
import os
print(os.uname()) # 获取系统信息
print(os.environ) # 获取系统变量
print(os.path.abspath('.')) # 获取当前绝对路径
os.path.join('/home/lyq', 'python') # 在指定目录中插入目标路径
os.mkdir('/home/lyq/python') # 创建目录
os.rmdir('/home/lyq/python') # 删除目录
print(os.path.split('/Users/michael/testdir/file.txt')) # 拆分路径,获取最后以及目录或文件
print(os.path.splitext('/Users/michael/testdir/file.txt')) # 拆分获取文件后缀
os.rename('enumTest.py', 'enumTest11.py') # 文件重命名
os.remove('test1.py') # 移除文件
os.listdir('.') # 列出当前目录下所有文件和目录
20、序列化(pickling
):
(1)pickle:
import pickle
tom = dict(name='Tom', age=30, address='北京市')
with open('./dump.txt', 'wb') as f:
# 序列化为bytes类型
b = pickle._dumps(tom)
# 反序列化
print(pickle.loads(b))
# 序列化并存储至文件
pickle.dump(tom, f)
with open('./dump.txt', 'rb') as f:
# 从文件中反序列化
tom = pickle.load(f)
print(tom)
(2)json:
import json
tom = dict(name='张三', age=30)
# 序列化
b = json.dumps(tom, ensure_ascii=False)
print(b)
# 反序列化
print(json.loads(b, encoding='utf-8'))
注:自定义类实例默认是不可序列化的,需要在使用json序列化时指定对应的序列化与反序列化方法。
import json
# 自定义animal序列化方法
def tranToJson(animal):
return {
'name': animal.name,
'age': animal.age
}
class Animal:
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self):
return '{name=%s, age=%s}' % (self.name, self.age)
tom = Animal('tom', 30)
# 使用定制的序列化方法对Animal实例进行序列化
bytes = json.dumps(tom, ensure_ascii=False, default=tranToJson)
print(bytes)
# 使用__dict__方法作为序列化方法
print(json.dumps(tom, default=lambda obj: obj.__dict__))
#定制Animal类的反序列化方法
def transToAnimal(a):
return Animal(a['name'], a['age'])
# 使用定制的反序列化方法对Animal实例进行反序列化
print(json.loads(bytes, encoding='utf-8', object_hook=transToAnimal))
21、进程:
(1)fork():fork()调用一次,返回两次,因为操作系统自动把当前进程(称为父进程)复制了一份(称为子进程);然后,分别在父进程和
子进程内返回。子进程永远返回0,而父进程返回子进程的Id。
import os
print('current process id is %s' % os.getpid())
pid = os.fork()
if pid == 0:
print('i am child, my pid is %s, my parent pid is %s' % (os.getpid(), os.getppid()))
else:
print('i am parent,my pid is %s' % os.getpid())
(2)Process():为实现跨平台统一的多进程编码:
from multiprocessing import Process
def child_func(name):
print('hello: %s' % name)
# 创建子进程: 参数1:子进程要执行的方法;参数2:方法参数
p = Process(target=child_func, args=('tom',))
print('child will start---')
# 启动子进程
p.start()
# 优先执行子进程
p.join()
print('child run end---')
(3)Pool():进程池,批量创建子进程
import os, time, random
from multiprocessing import Process, Pool
def child_func(name):
print('Run task %s (%s)...' % (name, os.getpid()))
startTime = time.time()
time.sleep(random.random() * 3)
endTime = time.time()
print('process %s run end, cost %s sec' % (os.getpid(), endTime - startTime))
# 默认大小为CPU核数
pool = Pool(8)
for i in range(9):
pool.apply_async(child_func, (i, ))
print('waiting...')
# join()之前必须调用close()
pool.close()
# 等待所有子进程执行完毕
pool.join()
print('end...')
(4)子进程:
启动子进程:subprocess.call(['nslookup', 'www.baidu.com'])
或subprocess.Popen(['nslookup'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
向子进程输入:sub.communicate(b'***')
(5)进程通信:Queue、PIPE;
(6)分布式进程:#Todo
22、线程:
(1)线程创建与启动:
t = threading.Thread(target=thread_run)
t.start()
(2)加锁保证线程安全:
lock = threading.Lock()
try:
lock.acquire()
change_index(n)
finally:
lock.release()
(3)ThreadLocal:threading.local()
23、正则表达式:TODO
24、常用内建模块:
(1)datetime:
from datetime import datetime, timedelta, timezone
# 获取当前时间
t1 = datetime.now()
# 获取指定时间,参数依次为:年月日时分秒
t2 = datetime(2019, 11, 25, 3, 20, 59)
# 时间转时间戳
t3 = t2.timestamp()
# 时间戳转时间
t4 = datetime.fromtimestamp(t3)
# 字符串转时间
t5 = datetime.strptime('2019-11-25 09:21:55', '%Y-%m-%d %H:%M:%S')
# 时间转字符串
t6 = t5.strftime('%Y/%m/%d %H:%M:%S')
# 时间加减
t7 = datetime.now() + timedelta(days=2, hours=12)
t8 = datetime.now() - timedelta(days=1, hours=6)
# 本地时间转UTC时间
# (1)创建时区
tz_utc_8 = timezone(timedelta(hours=8))
# (2)获取当前时间
t9 = datetime.now()
# (3)指定时区
t10 = t9.replace(tzinfo=tz_utc_8)
# 时区转换
# (1)获取当前UTC时间并强制设置时区
utc_now = datetime.utcnow().replace(tzinfo=timezone.utc)
# (2)转换为指定时区,如:北京时间
utc_now_ch = utc_now.astimezone(timezone(timedelta(hours=8))
(2)collections:
from collections import namedtuple, deque, OrderedDict, ChainMap
# 命名元组:定义tuple对象及参数列表
Point = namedtuple('Point', ['x', 'y'])
p = Point(4, 5)
# deque
dq = deque(['a', 'b', 'c'])
dq.appendleft('x')
dq.popleft()
# OrderedDict:按插入顺序排序key
d = dict([('a', 1), ('b', 3), ('c', 2)])
od = OrderedDict([('a', 1), ('c', 3), ('b', 2)])
# chainMap:将多个dict组成一个逻辑上的dict,查找时会在每个子dict中依次查找
d1 = {'name': 'tom', 'age': 20}
d2 = {'sex': '男', 'address': 'china'}
cd = ChainMap(d1, d2)
(3)hashlib:生成hash摘要
import hashlib
str = "hello world"
md5 = hashlib.md5()
md5.update(str.encode('utf-8'))
print(md5.hexdigest())
(4)hmac:哈希摘要+加盐
message = b'hello world'
salt = b'test'
passwd = hmac.new(salt, message, digestmod='MD5')
print(passwd.hexdigest())
(5)itertools:构造迭代器:
import itertools
# 无限递增
iter1 = itertools.count(1)
for n in iter1:
print(n)
# 循环
iter2 = itertools.cycle('ABC')
for i in iter2:
print(i)
# 重复但限制次数
iter3 = itertools.repeat('A', 5)
for i in iter3:
print(i)
# 连接
iter4 = itertools.chain('ABC', 'DEF')
for i in iter4:
print(i)
# 对相邻元素分组
iter5 = itertools.groupby('AAABBCCCCD')
for key, group in iter5:
print('key is %s, group is %s' % (key, list(group)))
(6)contextlib:构建上下文,使之可以使用 with 关键字
from contextlib import contextmanager
class Car(object):
def __init__(self, brand):
self.brand = brand
def run(self):
print('car is running, it is %s牌的' % (self.brand))
@contextmanager
def test(name):
print('<%s> starting...' % name)
yield Car('大众')
print('<%s> ending...' % name)
with test('tom') as car:
car.run()
#执行顺序:yield前的代码块 --> with代码块 --> yield后的代码块
#如果一个对象没有实现上下文,就不能使用在with代码中;这时可以用closing()来把该对象变为上下文对象。
with closing(open('../files/test2.txt')) as f:
for line in f.readlines():
print(line)
(7)urllib:通过request对象对URL进行操作
- 抓取url内容:
from urllib import request
with request.urlopen('http://11.11.141.59:30102/dashboard') as f:
print('Status: ', f.status, f.reason)
print('Data: ', f.read().decode('utf-8'))
for k, v in f.getheaders():
print('%s : %s' % (k, v))
- 发送Get请求:
req = request.Request('url...')
# 添加请求头
req.add_header('key', 'value')
with request.urlopen(req) as page:
pass
- 发送Post请求:post请求时参数以bytes形式传入
from urllib import request, parse
import json
class ResponseMessage(object):
def __init__(self, code, data):
self.code = code
self.data = data
def transToResponse(message):
return ResponseMessage(message['code'], message['data'])
req = request.Request('url')
login_data = parse.urlencode([
('key1', 'value1'),
...
])
with request.urlopen(req, data=login_data.encode('utf-8')) as page:
result_data = page.read()
result_data = json.loads(result_data, encoding='utf-8', object_hook=transToResponse)
print(result_data.data)
(8)html解析:
from html.parser import HTMLParser
from html.entities import name2codepoint
class MyHTMLParser(HTMLParser):
def handle_starttag(self, tag, attrs):
print('<%s>' % tag)
def handle_endtag(self, tag):
print('</%s>' % tag)
def handle_startendtag(self, tag, attrs):
print('<%s/>' % tag)
def handle_data(self, data):
print(data)
def handle_comment(self, data):
print('<!--', data, '-->')
def handle_entityref(self, name):
print('&%s;' % name)
def handle_charref(self, name):
print('&#%s;' % name)
parser = MyHTMLParser()
parser.feed('''<html>
<head></head>
<body>
<!-- test html parser -->
<p>Some <a href=\"#\">html</a> HTML tutorial...<br>END</p>
</body></html>''')