global
在局部修改 全局变量 时需要使用 global
关键字才能进行修改,读的话不需使用
nonlocal
在局部修改 函数内部的 局部变量 时需要使用 nonlocal
关键字才能进行修改,读的话不需使用
函数对象
def fun1():
print("fun1")
def fun2():
print("fun2")
def fun3():
print("fun3")
func_dict = {
'1': fun1,
'2': fun2,
'3': fun3
}
ch = '1'
if ch in func_dict:
func_dict[ch]() # 调用 fun1函数
闭包函数
def outer():
name = "albert"
def inner():
print("inner is %s" % name)
return inner
f = outer()
f()
装饰器
项目上线后要求: 开发封闭原则。对修改函数内部的源代码和调用方式是封闭的,对功能的扩展是开放的。
装饰器:能够在不修改被装饰对象源代码与调用方式的前提下,为被装饰器对象添加新功能
无参装饰器
无参装饰器简单实现
# 为 index 函数添加一个统计时间的功能
import time
def index():
time.sleep(1)
print("index")
return 1
def home(name):
time.sleep(2)
print("home %s" % name)
def timer(func):
def wrapper(*args, **kwargs):
start_time = time.time()
res = func(*args, **kwargs)
stop_time = time.time()
print(stop_time - start_time)
return res
return wrapper
index = timer(index) # 新的 index = wrapper
home = timer(home)
home(name='Albert1')
home('Albert2')
index()
修饰器模板:
def outer(func):
def inner(*args, **kwargs):
"""
写装饰器的逻辑
:param args: 任意位置参数
:param kwargs: 任意关键参数
:return: 一个函数对象
"""
res = func(*args, **kwargs)
return res
return inner
装饰器语法糖
import time
def timer(func):
def wrapper(*args, **kwargs):
start_time = time.time()
res = func(*args, **kwargs)
stop_time = time.time()
print(stop_time - start_time)
return res
return wrapper
@timer
def index():
time.sleep(1)
print("index")
return 1
# @timer
def home(name):
time.sleep(2)
print("home %s" % name)
index()
home("albert")
用户认证装饰器
import time
current_user = {
'username': None
}
def auth(func):
def wrapper(*args, **kwargs):
if current_user['username']:
print('已登录')
res = func(*args, **kwargs)
return res
name = input('用户名>>:').strip()
pwd = input('密码>>:').strip()
if name == 'Albert' and pwd == '1':
print('登录成功')
current_user['username'] = name
res = func(*args, **kwargs)
return res
else:
print('用户名或密码错误')
return wrapper
@auth
def index():
time.sleep(1)
print("welcome to index")
return 1
@auth
def home(name):
time.sleep(2)
print("welcome to home %s" % name)
index()
home('Albert')
多个装饰器叠加
import time
current_user = {
'username': None
}
def auth(func):
def wrapper(*args, **kwargs):
if current_user['username']:
print('已登录')
res = func(*args, **kwargs)
return res
name = input('用户名>>:').strip()
pwd = input('密码>>:').strip()
if name == 'Albert' and pwd == '1':
print('登录成功')
current_user['username'] = name
res = func(*args, **kwargs)
return res
else:
print('用户名或密码错误')
return wrapper
def timer(func):
def wrapper(*args, **kwargs):
start_time = time.time()
res = func(*args, **kwargs)
stop_time = time.time()
print(stop_time - start_time)
return res
return wrapper
# timer 统计 auth + index 的执行时间
@timer
@auth
def index():
time.sleep(1)
print("welcome to index")
return 1
# timer 统计 index 的执行时间
@auth
@timer
def home(name):
time.sleep(2)
print("welcome to home %s" % name)
index()
home('Albert')
有参装饰器
用于文件操作、数据库访问等等
import time
current_user = {
'username': None
}
def auth(engine):
def user_auth(func):
def wrapper(*args, **kwargs):
if engine == 'file':
print('基于文件的认证')
if current_user['username']:
print('已登录')
res = func(*args, **kwargs)
return res
name = input('用户名>>:').strip()
pwd = input('密码>>:').strip()
if name == 'Albert' and pwd == '1':
print('登录成功')
current_user['username'] = name
res = func(*args, **kwargs)
return res
else:
print('用户名或密码错误')
elif engine == 'mysql':
print('mysql的认证')
elif engine == 'ldap':
print('ldap的认证')
return wrapper
return user_auth
@auth('file')
def index():
time.sleep(1)
print("welcome to index")
return 1
@auth('mysql')
def home(name):
time.sleep(2)
print("welcome to home %s" % name)
index()
home('Albert')
装饰器补充
from functools import wraps
def deco(func):
@wraps(func)
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
return wrapper
@deco
def index():
"""哈哈哈"""
print(index.__doc__)
index()
迭代器
可迭代对象
Python
内置 str, list, tuple, dict, set, file都是可迭代对象,内置 iter 方法,返回迭代器对象
迭代器对象
迭代器对象: 内置next
方法,执行 next
方法拿到迭代器对象中的一个值,执行 iter
方法拿到迭代器本身
优缺点
优点
- 提供了一种不依赖索引取值的方式
- 迭代器更加节省内存
for i in range(0, 10):
print(i)
item = range(0, 10000000)
iter_item = item.__iter__()
while True:
try:
print(iter_item.__next__())
except StopIteration:
break
缺点
- 只能一个一个取值,一次性(当一个迭代器取完之后,需要重新获取一个迭代器对象才可以取值
iter_x = x.__iter__()
) - 无法用
len
获取长度
生成器
yield
yield
自定义迭代器yield
可以返回多次值,yeild
可以保存函数执行状态
def test_yield():
print("=====>first")
yield 1
print("=====>second")
yield 2
print("=====>third")
yield 3
res = test_yield()
print(res)
print(res.__iter__() is res)
print(res.__next__())
print(res.__next__())
print(res.__next__())
## 结果
<generator object test_yield at 0x7ffba287aa20>
True
=====>first
1
=====>second
2
=====>third
3
range
range(1,20,1)
左闭右开[1,20) 步长为1
yield表达式
yield 可以暂停函数,保存函数的运行状态
def eat(name):
print('[1] %s is ready for eating' % name)
while True:
food = yield # yield 可以赋值给一个变量
print('[2] %s starts to eat %s' % (name, food))
"""
person1 = eat('Albert')
# 函数停在 food = yield 这行代码
person1.__next__()
# 继续执行代码, 由于 yield没有值,即 yield = None, 这 food = None
person1.__next__()
"""
person1 = eat('Albert')
"""
表达式 yield 使用必须初始化
第一次必须传 None, 或者用__next__方法
"""
# person1.send(None) 初始化和 __next__()作用一样
person1.__next__()
person1.send('羊肉') # send 传值 初始化
person1.send('牛肉')
person1.send('面包')
person1.send('牛奶')
person1.close() # 关闭之后就不能send了
# person1.send('error')
# answer
[1] Albert is ready for eating
[2] Albert starts to eat 羊肉
[2] Albert starts to eat 牛肉
[2] Albert starts to eat 面包
[2] Albert starts to eat 牛奶
获得 吃掉的食物列表:
def eat(name):
print('[1] %s is ready for eating' % name)
food_list = []
while True:
food = yield # yield 可以赋值给一个变量
print('[2] %s starts to eat %s' % (name, food))
food_list.append(food)
print('[3] %s has eaten %s' % (name, food_list))
"""
person1 = eat('Albert')
# 函数停在 food = yield 这行代码
person1.__next__()
# 继续执行代码, 由于 yield没有值,即 yield = None, 这 food = None
person1.__next__()
"""
person1 = eat('Albert')
"""
表达式 yield 使用必须初始化
第一次必须传 None, 或者用__next__方法
"""
# person1.send(None) 初始化和 __next__()作用一样
person1.__next__()
person1.send('羊肉') # send 传值 初始化
person1.send('牛肉')
person1.send('面包')
person1.send('牛奶')
person1.close() # 关闭之后就不能send了
# person1.send('error')
# answer
[1] Albert is ready for eating
[2] Albert starts to eat 羊肉
[3] Albert has eaten ['羊肉']
[2] Albert starts to eat 牛肉
[3] Albert has eaten ['羊肉', '牛肉']
[2] Albert starts to eat 面包
[3] Albert has eaten ['羊肉', '牛肉', '面包']
[2] Albert starts to eat 牛奶
[3] Albert has eaten ['羊肉', '牛肉', '面包', '牛奶']
三元表达式
x = 12
y = 11
res = x if x > y else y
print(res)
匿名函数
使用规则:
- 冒号左边为参数
- 冒号右边为返回值
- 不需要写 return
f1 = lambda x, y, z: x + y + z
print(f1(1, 2, 3))
匿名函数与 max, min, sorted 联用
salaries = {
'jam': 30000,
'tom': 100000,
'jack': 4000,
'lucy': 1000000
}
print(max(salaries))
print(min(salaries))
print(sorted(salaries))
print('-------------------------------')
print(max(salaries, key=lambda x: salaries[x]))
print(min(salaries, key=lambda x: salaries[x]))
print(sorted(salaries, key=lambda x: salaries[x]))
#answer
tom
jack
['jack', 'jam', 'lucy', 'tom']
-------------------------------
lucy
jack
['jack', 'jam', 'tom', 'lucy']
匿名函数与map, reduce, filter联用
map 映射
nums = [i for i in range(1, 6)]
# 数字映射
res = map(lambda x: x ** 2, nums)
print(res)
print(list(res))
# 字符串映射
names1 = ['jack', 'tom', 'lucy', 'ming']
res1 = map(lambda x: x + ' is super star', names1)
print(list(res1))
names2 = ['jack', 'tom', 'lucy', 'ming']
res2 = map(lambda x: x + ' is super star' if x == 'ming' else x + ' is referee', names2)
print(list(res2))
#answer
<map object at 0x7ff89a8b1f98>
[1, 4, 9, 16, 25]
['jack is super star', 'tom is super star', 'lucy is super star', 'ming is super star']
['jack is referee', 'tom is referee', 'lucy is referee', 'ming is super star']
reduce 合并
"""
reduce 可以传三个参数:
第一个是必传项,合并规则,即函数
第二个是必传项,可迭代对象
第三个是可选项,初始的值
"""
# 计算 1+2+3+ ... +100
from functools import reduce
res1 = reduce(lambda x, y: x + y, range(1, 101), 0)
print(res1)
# 不指定初始值
res = reduce(lambda x, y: x + y, range(1, 101))
print(res)
# 字符串合并
list1 = ['Today', 'is', 'the', 'first', 'day', 'of', 'the', 'rest', 'of', 'your', 'life']
res2 = reduce(lambda x, y: x + ' ' + y, list1)
print(res2)
# answer
5050
5050
Today is the first day of the rest of your life
filter 过滤
# 过滤出年龄不小于30的
ages = [18, 19, 20, 40, 24, 99]
res = filter(lambda n: n >= 30, ages)
print(list(res))
# 过滤出裁判
name = ['Jame is super star', 'harden is super star', 'Jack is referee']
res1 = filter(lambda x: x.endswith('referee'), name)
print(list(res1))
# answer
[40, 99]
['Jack is referee']
内置函数
format
res = '{} {} {}'.format('Albert', 18, 'male') # 相当于 %
print(res)
res = '{1} {0} {1}'.format('Albert', 18, 'male') # 根据索引对应值
print(res)
res = '{name} {age} {sex}'.format(sex='male', name='Albert', age=20)
print(res)
# answer
Albert 18 male
18 Albert 18
Albert 20 male
format
可以穿对象等,但是 % 只能对字符串进行站位
class Person(object):
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self):
return "This guy is {self.name}, {self.age} years old.".format(self=self)
p1 = Person("Albert", 18)
print(p1)
# answer
This guy is Albert, 18 years old.
c = (250, 250)
# s1 = "敌人坐标:%s" % c # error
s1 = "敌人坐标:{}".format(c)
print(s1)
# answer
敌人坐标:(250, 250)
f-strings
3.6 以后新特性
name = 'Albert'
print(f'he said his name is {name}')
# answer
he said his name is Albert
填充与对齐
^、<、> 分别是 居中、左对齐、右对齐,后面带宽度,冒号后面带填充的字符串,只能是一个字符,不指定默认空格填充
print('{:>10}'.format('18'))
print('{:3<10}'.format('18'))
print('{:*^10}'.format('18'))
print('a'.zfill(10)) # 右对齐 填充0 指定长度为10
# answer
18
1833333333
****18****
000000000a
float精度调整
print('{:.5f}'.format(3.1415926535)) # 精度为5
# answer
3.14159
进制转换
print('{:b}'.format(18)) # 二进制
print('{:d}'.format(18)) # 十进制
print('{:o}'.format(18)) # 八进制
print('{:x}'.format(18)) # 十六进制
print(bin(18))
print(oct(18))
print(hex(18))
# answer
10010
18
22
12
0b10010 # 0b b bin
0o22
0x12
绝对值
print(abs(-1))
逻辑判断
print(all([1, 'a', True])) # True
print(all([1, 'a', True, 0])) # False
print(any([1, 'a', True, None, False])) # True
print(any([1, 'a', True])) # True
print(any([])) # False
bool值判断
print(bool(0)) # False
print(bool(1)) # True
print(bool('a')) # True
print(bool('')) # True
bytes类型构造
# bytes 类型构造
res = '你好Albert'.encode('utf-8') # unicode 按照 utf-8 进行编码,得到的结果为 bytes 类型
print(res)
res = bytes('你好Albert', encoding='utf-8')
print(res)
# answer
b'\xe4\xbd\xa0\xe5\xa5\xbdAlbert'
b'\xe4\xbd\xa0\xe5\xa5\xbdAlbert'
判断对象是否可调用
def func():
pass
print(callable(func))
print(callable('abc'.strip))
print(callable(max))
# answer
True
True
True
字符与十进制转换
print(chr(65)) # 按照 ascii 码表 将十进制数转为字符
print(ord('a')) # 按照 ascii 码表 将字符转为十进制数
# answer
A
97
查看对象下可调用的方法
print(dir('abc'))
去商和余数返回元组
print(divmod(1331, 25))
# answer
(53, 6)
将字符内的表达式拿出运行,得到表达式的执行结果
res1 = eval('2*3')
print(res1, type(res1))
res2 = eval('[1,3,5]')
print(res2, type(res2))
res3 = eval('{"name":"Albert", "age":18}')
print(res3, type(res3))
# answer
6 <class 'int'>
[1, 3, 5] <class 'list'>
{'name': 'Albert', 'age': 18} <class 'dict'>
不可变集合
s = {1, 3, 4}
s.add(5)
print(s)
f_set = frozenset(s)
print(f_set, type(f_set))
# answer
{1, 3, 4, 5}
frozenset({1, 3, 4, 5}) <class 'frozenset'>
名字与值得绑定关系
x = 2
print(globals())
print(dir(globals()['__name__']))
哈希
Hash 只能为不可变的类型 int ,str, float, truple
可变类型 list dict set 不能 hash
print(hash('a'))
print(hash((1, 3, 5, 7, 9)))
查看文档注释
def func1():
"""
注释
:return:
"""
pass
print(help(max))
print(help(func1))
幂
# 2 ** 3 % 3
print(2 ** 3 % 3)
print(pow(2, 3, 3))
# answer
2
2
反转顺序
i = [1, 4, 7, 2]
res = reversed(i)
print(list(res))
print(i)
# answer
[2, 7, 4, 1]
[1, 4, 7, 2]
切片对象
# [start_index : end_index : step]
sc = slice(1, 5, 2)
l = ['a', 'b', 'c', 'd', 'e', 'f']
print(sc)
print(l[1:5:2])
print(l[sc])
# answer
slice(1, 5, 2)
['b', 'd']
['b', 'd']
拉链函数
返回列表长度与最短的对象相同
left = 'hello'
right1 = {'x': 1, 'y': 2, 'z': 3}
right2 = [1, 3, 5, 7, 9]
res1 = zip(left, right1)
res2 = zip(left, right2)
print(list(res1))
print(list(res2))
# answer
[('h', 'x'), ('e', 'y'), ('l', 'z')]
[('h', 1), ('e', 3), ('l', 5), ('l', 7), ('o', 9)]
nums = ['123','456','789']
print(nums)
for j in zip(*nums):
print(j)
# answer
['123', '456', '789']
('1', '4', '7')
('2', '5', '8')
('3', '6', '9')
列表生成式
提高效率
迭代取值
l1 = ['egg%s' % i for i in range(10)]
l2 = ['egg%s' % i for i in range(10) if 2 < i < 7]
print(l1)
print(l2)
l3 = ('egg%s' % i for i in range(10))
print(next(l3))
print(next(l3))
# answer
['egg0', 'egg1', 'egg2', 'egg3', 'egg4', 'egg5', 'egg6', 'egg7', 'egg8', 'egg9']
['egg3', 'egg4', 'egg5', 'egg6']
egg0
egg1
常用模块
time
# 1、时间戳
print(time.time())
start_time = time.time()
time.sleep(3)
end_time = time.time()
print(end_time - start_time)
# 2、格式化的字符串
print(time.strftime('%Y-%m-%d %H:%M:%S %p'))
print(time.strftime('%Y-%m-%d %X %p'))
# 3、struct_time 对象
print(time.localtime()) # 上海: 东八区
print(time.localtime().tm_year)
print(time.localtime().tm_mday)
print(time.gmtime()) # UTC时区
print(time.localtime(111).tm_hour)
print(time.gmtime(11111).tm_hour)
print(time.mktime(time.localtime()))
print(time.strftime('%Y/%m/%d', time.localtime()))
print(time.strptime('2017/04/08', '%Y/%m/%d'))
print(time.asctime(time.localtime()))
print(time.ctime(123))
print("~~~~~~~~~~~~~~~~~~~~")
def progress(percent, width=50):
if percent > 1:
percent = 1
show_str = ('[%%-%ds]' % width) % (int(width * percent) * '#')
print('\r%s %d%%' % (show_str, int(100 * percent)), end='')
recv_size = 0
total_size = 102400
while recv_size < total_size:
time.sleep(0.1)
recv_size += 4096
percent = recv_size / total_size
progress(percent)
# answer
1602397909.678658
3.0040740966796875
2020-10-11 14:31:52 PM
2020-10-11 14:31:52 PM
time.struct_time(tm_year=2020, tm_mon=10, tm_mday=11, tm_hour=14, tm_min=31, tm_sec=52, tm_wday=6, tm_yday=285, tm_isdst=0)
2020
11
time.struct_time(tm_year=2020, tm_mon=10, tm_mday=11, tm_hour=6, tm_min=31, tm_sec=52, tm_wday=6, tm_yday=285, tm_isdst=0)
8
3
1602397912.0
2020/10/11
time.struct_time(tm_year=2017, tm_mon=4, tm_mday=8, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=5, tm_yday=98, tm_isdst=-1)
Sun Oct 11 14:31:52 2020
Thu Jan 1 08:02:03 1970
~~~~~~~~~~~~~~~~~~~~
[##################################################] 100%
datatime
print(datetime.datetime.now())
print(datetime.datetime.now() + datetime.timedelta(days=3))
print(datetime.datetime.now() + datetime.timedelta(days=-3))
print(datetime.datetime.now() + datetime.timedelta(hours=3))
print(datetime.datetime.now() + datetime.timedelta(seconds=111))
current_time = datetime.datetime.now()
print(current_time.replace(year=1999))
print(datetime.date.fromtimestamp(1111111))
# answer
2020-10-11 14:31:55.282782
2020-10-14 14:31:55.282812
2020-10-08 14:31:55.282828
2020-10-11 17:31:55.282834
2020-10-11 14:33:46.282840
1999-10-11 14:31:55.282844
1970-01-14
shutil tarfile 压缩解压
# 压缩文件
ret = shutil.make_archive(
base_name="模块对象_%s" % time.strftime("%Y-%m-%d"),
format='gztar',
base_dir='file'
)
# 解压文件
t = tarfile.open('/code/python基础/简单基础/模块对象_2020-10-12.tar.gz',
'r')
t.extractall(r'/Users/yang/deepLearning/python基础/code/python基础/extract')
t.close()
Logging模块
logging.basicConfig(
filename='access.log',
format='%(asctime)s - %(name)s - %(levelname)s - %(module)s: %(message)s',
datefmt='%Y-%m-%d %H:%M:%S %p',
level=20
)
logging.debug('debug...')
logging.info('info...')
logging.warning('快着火了...')
logging.error('着火了...')
logging.critical('火月着越大')
# logging 模块的四种对象
# 1 logger:负责产生日志
logger1 = logging.getLogger('xxx')
# 2 flitter 过滤日志(不常用)
# 3 handler: 控制日志打印到文件 or 终端
fh1 = logging.FileHandler(filename='a1.log', encoding='utf8')
fh2 = logging.FileHandler(filename='a2.log', encoding='utf8')
sh = logging.StreamHandler()
# 4 formatter: 控制日志的格式
formatter1 = logging.Formatter(
fmt='%(asctime)s - %(name)s - %(levelname)s - %(module)s: %(message)s',
datefmt='%Y-%m-%d %H:%M:%S %p',
)
formatter2 = logging.Formatter(fmt='%(asctime)s - %(message)s')
# 为 logging 对象绑定 handler
logger1.addHandler(fh1)
logger1.addHandler(fh2)
logger1.addHandler(sh)
# 为 handler 绑定日志格式
fh1.setFormatter(formatter1)
fh2.setFormatter(formatter1)
sh.setFormatter(formatter2)
# 日志级别: 两层关卡,必须都通过,才能正常记录
logger1.setLevel(30)
fh1.setLevel(10)
fh2.setLevel(10)
sh.setLevel(10)
# 调用 logging1 对象下的方法,产生日志,然后交给不同的handler,控制日志记录到不同的地方
logger1.debug('调试信息')
logger1.info('使用中')
logger1.warning('警告')
logger1.critical('问题很严重')
json与pickle
# json序列化
import json
dic = {'name': '杨', 'age': 18}
with open('db1.son', 'wt', encoding='utf-8') as f:
json.dump(dic, f)
# 反序列化
with open('db1.son', 'r', encoding='utf-8') as f:
dic = json.load(f)
print(dic)
# pickle序列化
import pickle
s = {1, 2, 3, 4}
res = pickle.dumps(s)
print(res, type(res))
with open('db2.pkl', 'wb') as f:
f.write(res)
# 反序列化
with open('db2.pkl', 'rb') as f:
data = f.read()
s = pickle.loads(data)
print(s, type(s))
# dump 与 load
import pickle
s = {7, 8, 9}
with open('db3.pkl', 'wb') as f:
pickle.dump(s, f)
# 反序列化
with open('db3.pkl', 'rb') as f:
s = pickle.load(f)
print(s, type(s))
os模块
import os
res = os.getcwd()
print(res)
res = os.listdir()
print(res)
print(os.sep)
print([os.linesep, ])
print(os.pathsep)
print(os.system('ls'))
# os.path 系列
file_path = r'file/a/b/c/1'
print(os.path.abspath(file_path))
res = os.path.split(r'file/a/b/c/1')
print(res)
print(res[-1])
print(res[0])
print(os.path.isabs(file_path))
print(os.path.isabs(r'/code/python基础/简单基础/file/a/b/c/1'))
BAS_DIR = os.path.dirname(os.path.dirname(__file__))
DB_PATH = r'%s/db/db.txt' % BAS_DIR
print(BAS_DIR)
print(DB_PATH)
# 判断文件存在
print(os.path.exists(r'/code/python基础/简单基础/file/12312'))
print(os.path.exists(r'/Users/yang/deepLearning/python基础/code/python基础/12312'))
print(os.path.isfile(r'/code/python基础/简单基础/file/12312'))
# 判断文件夹是否存在
print(os.path.isdir(r'/code/python基础/简单基础/file'))
print(os.path.join('/Users/yang/deepLearning/python基础/code', 'python基础', 'file', '12312'))
print(os.path.join('/Users/yang/deepLearning/python基础/code', 'python基础', '/Users/yang', 'code'))
print(os.path.join('file', 'a', 'b', 'c', '1'))
# 得到文件大小
res = os.path.getsize(file_path)
print(res)
shelve模块
info1 = {'weight': 1, 'age': 1, 'height': 'a'}
info2 = {'weight': 2, 'age': 1, 'height': 'b'}
d = shelve.open('db.shv')
d['yang'] = info1
d['xin'] = info2
d.close()
s = shelve.open('db.shv')
print(s['yang'])
print(s['xin'])
s.close()
re模块(正则表达式)
hashlib模块
哈希是一种算法,该算法接收传入的内容,经过运算得到一串hash值。
特点:
- 只要传入的内容一样,得到的hash必然一样 ==> 文件校验完整性
- 不能由hash值反解该内容,把密码做成hash值,不应该在网络中传输明文密码
- 只要使用的hash算法不变,无论校验的内容有多大,得到的hash值长度是固定的
import hashlib
m = hashlib.md5()
m.update('hello'.encode('utf8'))
m.update('world'.encode('utf8'))
m.update('yang'.encode('utf8'))
print('字符串md5值:', m.hexdigest())
# md5 值校验
md = hashlib.md5()
with open('/code/python基础/简单基础/14模块-hash.py', 'rb') as f:
for line in f:
md.update(line)
file_md5 = m.hexdigest()
print('md5_file', file_md5)
# 密码加密
pwd = 'yang123'
mp = hashlib.md5()
mp.update('天王盖地虎'.encode('utf8'))
mp.update(pwd.encode('utf8'))
mp.update('宝塔镇河妖'.encode('utf8'))
print('密码md5值:', mp.hexdigest())
subprocess模块
import subprocess
cmd = input('>>:') # ls
obj = subprocess.Popen(
cmd,
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE
)
print(obj)
res1 = obj.stdout.read() # 输出正确结果
print('正确结果:', res1.decode('utf-8'))
res2 = obj.stderr.read() # 输出错误结果
print('错误结果:', res2.decode('utf-8'))