PEP8编码规范
前闭后开
列表转换为字符串join
a = ["a", "p", "p", "l", "e"]
# 将列表中的每一个元素拼接起来
print("".join(a))
# apple
字符串转换为列表split
# 根据split内的内容将字符串进行切分
str1 = "apple banner"
str1.split(" ")
# ['apple', 'banner']
in 如果在指定的序列中找到值返回 True,否则返回 False。 not in
is 是判断两个标识符是不是引用自一个对象 is not
list_a = ["a", "b", "c"]
list_b = ["a", "b", "c"]
print(id(list_a)) # 使用id查看变量的内存地址
print(id(list_b))
print(list_a is list_b)
print(list_a == list_b)
可变的数据结构,即使看着一样,但内存地址是不同的
不可变的数据结构,看着一样,内存地址是相同的
h = "变量1" if a>b else "变量2"
break-跳出整个循环体
continue:跳出当前轮次循环
列表推导式
li = [i for i in range(11)]
# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
li1 = [i for i in range(11) if i % 2 == 0]
# [0, 2, 4, 6, 8, 10]
列表方法 | 作用 | 入参 | 返回 | |
---|---|---|---|---|
append() | append(item):将一个对象 item 添加到列表的末尾。 | 入参:对象 item | 返回:None | |
extend() | extend(iterable):将一个可迭代对象的所有元素,添加到列表末尾。 | 入参:可迭代对象 iterable | 返回:None | |
insert() | insert(index, item):将一个对象插入到指定的索引位置 | 入参:索引值 index ,一个对象 item | 返回:None | 原索引位置及后面的元素后移一位 |
pop() | pop(index) 或 pop() | 入参:索引值 index,可不传 | 弹出并返回所指定索引的元素。返回:指定索引的元素、返回:未指定索引则返回末尾元素 | 如果索引值不正确,或者列表已经为空,则引发 IndexError 错误 |
remove() | remove(item)移除列表中第一个等于 item 的元素 | 入参:指定元素 item | 返回:None | 目标元素必须已存在,否则会报 ValueError |
sort() | sort(key=None, reverse=False)对列表进行原地排序,只使用 < 来进行各项间比较。 | key:指定带有一个参数的函数,用于从每个列表元素中提取比较键。reverse:默认值为 False 表示升序,为 True 表示降序 | 返回:None | |
reverse() | reverse():将列表中的元素顺序反转 | 参数:无 | 返回:None | 反转只是针对索引值,元素之间不相互比较 |
元组方法 | 作用 | 入参 | 返回 | |
---|---|---|---|---|
index() | index(item)查找元组中的元素 | 入参:对象 item | 返回与目标元素相匹配的首个元素的索引。 | 目标必须在元组中存在的,否则会报错 |
count() | count(item):返回某个元素出现的次数。 | 入参:对象 item | 返回:次数 |
a, b, c = (1, 2, 3)
print(type(a),a)
# 1
a= (1,)
print(type(a),a)
print(type(*a),*a)
# (1,)
# 1
集合方法 | 作用 | 入参 | 返回 | |
---|---|---|---|---|
add() | add(item):将单个对象添加到集合中 | 入参:对象 item | 返回:None | |
update() | update(iterable)批量添加来自可迭代对象中的所有元素 | 入参:可迭代对象 iterable | 返回:None | |
remove() | remove(item):从集合中移除指定元素 item。 | 入参:指定元素值 | 返回:None | 如果 item 不存在于集合中则会引发 KeyError |
discard() | discard(item):从集合中移除指定对象 item。 | 入参:指定对象值 | 返回:None | 元素 item 不存在没影响,不会抛出 KeyError 错误。 |
pop() | pop():随机从集合中移除并返回一个元素。 | 入参:无。 | 返回:被移除的元组。 | 如果集合为空则会引发 KeyError。 |
clear() | clear():清空集合,移除所有元素 | 入参:无 | 返回:None |
集合运算 | 函数 | 操作符 | 图 |
---|---|---|---|
交集运算 | intersection() | 操作符:& | |
并集运算 | union() | 操作符:| | |
差集运算 | difference() | 操作符: - |
字典方法 | 作用 | 入参 | 返回 | |
---|---|---|---|---|
keys() | 入参:无 | 返回由字典键组成的一个新视图对象。 | ||
values() | 入参:无 | 返回由字典值组成的一个新视图对象。 | ||
items() | 入参:无 | 返回由字典项 ((键, 值) 对) 组成的一个新视图对象。 | ||
get() | get(key)获取指定 key 关联的 value 值。 | key:字典的键,必传。 | 如果 key 存在于字典中,返回 key 关联的 value 值。如果 key 不存在,则返回 None。 | 此方法的好处是无需担心 key 是否存在,永远都不会引发 KeyError 错误。 |
update() | update(dict)使用来自 dict 的键/值对更新字典,覆盖原有的键和值。 | 入参:字典对象,必传 | 返回:None | |
pop() | pop(key)删除指定 key 的键值对,并返回对应 value 值。 | key:必传 | 如果 key 存在于字典中,则将其移除并返回 value 值、如果 key 不存在于字典中,则会引发 KeyError。 |
列表变字典
list1 = [("name", "Harry Potter"), ("age", 18)]
dict1 = {i: j for i, j in list1}
# {'name': 'Harry Potter', 'age': 18}
字典变列表
params = {'Tom':18, 'Jim':20, 'Lily':12}
dictlist=[]
for keys, value in params.items():
temp = (keys,value)
dictlist.append(temp)
print(dictlist)
dc = {'a': 1, 'b': 2, 'c': 3}
d_new = {k : v ** 2 for k,v in dc.items() if v > 1 }
print(d_new)
# {'b': 4, 'c': 9}
内置函数
*args 接收任意多个实际参数,并将其放到一个元组中。
使用已经存在的列表或元组作为函数的可变参数,可以在列表的名称前加*号
def print_language(*args):
print(args)
for i in args:
print(i)
print_language("python", "java", "php", "go")
params = ["python", "java", "php", "go"]
print_language(*params)# 解包
**kwargs接收任意多个类似关键字参数一样显式赋值的实际参数,并将其放到一个字典中
使用已经存在字典作为函数的可变参数,可以在字典的名称前加**
def print_info(**kwargs):
print(kwargs)
print_info(Tom=18, Jim=20, Lily=12)
params = {'Tom':18, 'Jim':20, 'Lily':12}
print_info(**params)
匿名函数-没有名字的函数-lambda
result = lambda [arg1 [, arg2, .... , argn]]: expression
result:调用 lambda 表达式
[arg1 [, arg2, …. , argn]]:可选,指定要传递的参数列表
expression:必选,指定一个实现具体功能的表达式
dictlist=[('Tom', 18), ('Jim', 20), ('Lily', 12)]
# lambda x:x[1] 返回了列表中每个元组的第二个元素
dictlist.sort(key=lambda x:x[1])
# [('Lily', 12), ('Tom', 18), ('Jim', 20)]
类的方法:实例方法(构造方法)、类方法、静态方法
构造方法:实例化对象__init__(self,参数) 实例变量(实例属性)self.name
实例方法:在类中定义的函数 def 方法名(self,参数)
类方法:使用 @classmethod 装饰器 def 方法名(cls,参数) 操作获取类的详细状态或属性——不修改原有代码,进行拓展的方式
静态方法:使用 @staticmethod 装饰器 def 方法名(参数) 不能访问类的数据 ——此方法没有任何和实例、类相关的部分,可以作为一个独立函数使用,通用的工具函数,将常用的函数放在一个类中进行管理
内置类装饰器:不用实例化、直接调用、提升代码的可读性
普通方法
定义:第一个参数为self,代表 实例本身
调用:要有实例化的过程,通过 实例对象.方法名 调用
类方法classmethod
定义:使用 @classmethod 装饰器,第一个参数为类本身,所以通常使用cls命名做区分(非强制),在类内可以直接使用类方法或类变量,无法直接使用实例变量或方法
调用:无需实例化,直接通过 类.方法名 调用,也可以通过 实例.方法名 调用
静态方法staticmethod
定义:使用 @staticmethod 装饰器,没有和类本身有关的参数,无法直接使用任何类变量、类方法或者实例方法、实例变量
调用:无需实例化,直接通过 类.方法名 调用,也可以通过 实例.方法名 调用
名称 | 定义 | 调用 | 关键字 | 使用场景 |
---|---|---|---|---|
普通方法 | 至少需要一个参数self | 实例名.方法名() | 无 | 方法内部涉及到实例对象属性的操作 |
类方法 | 至少需要一个cls参数 | 类名.方法名() 或者实例名.方法名() | @classmethod | 如果需要对类属性,即静态变量进行限制性操作 |
静态方法 | 无默认参数 | 类名.方法名() 或者实例名.方法名() | @staticmethod | 无需类或实例参与 |
class DateFormat:
def __init__(self, year=0, month=0, day=0):
self.year = year
self.month = month
self.day = day
def out_date(self):
return f"输入的时间为{self.year}年,{self.month}月,{self.day}日"
@classmethod
def json_format(cls,json_data):
year, month, day = json_data["year"],json_data["month"],json_data["day"]
return cls(year, month, day)
year, month, day = 2017, 7, 1
demo = DateFormat(year, month, day)
print(demo.out_date())
#需求变更,输入 年、月、日 的格式为json,不修改构造函数的前提下,更改代码:添加类方法json_format
data={"year":2022,"month":6,"day":27}
demo_json = DateFormat.json_format(data)
print(demo_json.out_date())
参数类型
name:str
参数:类型
返回类型
def get_name(name:str) -> str:
类型提示 的好处:增强代码可读性;ide中代码提示;静态代码检查(第三方库)
类型别名:Vector = List[float]
from typing import List
Vector = List[float]
def scale(scalar:float,vector:Vector) ->Vector:
return [scalar *num for num in vector]
print(scale(2, [1.1, 2.2, 3.3, 4.4]))
# [2.2, 4.4, 6.6, 8.8]
自定义类型
class Student:
name :str
age :int
def get_student(name:str) ->Student:
return Student()
安装pip install mypy
命令行执行mypy xx.py
import 模块名
from 模块名 import 方法、变量、类
from 模块名 import *
系统内置模块
第三方开源模块
自定义模块
dir() 找出当前模块定义的对象
dir(sys) 找出参数sys模块定义的对象
隐藏:属性和实现细节,不允许外部直接访问
暴露:公开方法,实现对内部信息的操作和访问
作用:限制安全的访问和操作,提高数据安全性;可进行数据检查,从而有利于保证对象信息的完整性。
内部属性
_属性名
私有属性
__属性名 == _类名__属性名
class TestDome:
name = "Tom"
_username = "username"
__password = "password"
@property
# 计算属性,把一个方法变成属性
def password(self):
return self.__password
# 使用@计算属性名。setter装饰器
@password.setter
def password(self,value):
if len(value) >= 6:
self.__password = value
else:
print("密码长度不足")
obj = TestDome()
# 访问私有属性
print(obj.password)
# 修改私有属性
obj.password = "admin123"
print(obj.password)
# 修改私有属性
obj.password = "123"
print(obj.password)
#print(TestDome.__dict__)
复用父类的公开属性和方法,拓展出新的属性和方法。
class 类名(父类列表)
默认父类object
isinstance(实例,类名) 检查对象是否是某个类及其派生类的实例
issubclass(类名1,类名2)检查类名1是否是类名2的子类
同名方法呈现多种行为
举例 +号: 加法(数字+数字)拼接(字符串+字符串)合并(列表+列表)
举例 len()函数:获取可迭代对象的长度或个数, 可以接收字符串、可以接收列表,入参不同
举例 同名变量调用 同名方法呈现多种行为
class China:
def speak(self):
print("说汉语")
class Usa:
def speak(self):
print("say english")
cn = China()
us = Usa()
for x in (cn,us):
x.speak()
多态 与继承
方法重写:子类的方法名称与父类的相同(优先访问自己的方法,父类同名方法被覆盖)
重写构造方法,两种super().init() 父类名.init(self)
class Human:
message = "人类"
def __init__(self,name,age):
self.name = name
self.age = age
def live(self):
print("住在地球上")
class Student(Human):
def __init__(self,name ,age,school):
# super().__init__(name,age)
Human.__init__(self,name,age)
self.school = school
def live(self):
print(f"住在{self.school}里")
stu = Student("Tom",10,"希望小学")
print(stu.name)
stu.live()
#Tom 住在希望小学里
错误:语法错误SyntaxError、逻辑错误、系统错误
异常:程序执行过程中出现的未知错误;语法和逻辑正常;程序业务逻辑不完善引起的程序漏洞bug
ZeroDivisionError除数为零异常
NameError名称异常
IndexError索引异常
KeyError键异常
ValueError值异常
…
try:
li = [2]
print(li[9])
except Exception as e:
print(e)
print("发生异常时执行的代码")
else:
print("没有异常时执行的代码")
finally:
print("最终都会被执行,无论有无异常")
抛出异常
def set_age(age:int):
if age <= 0 or age > 150:
raise ValueError(f"年龄的值错误:{age}")
else:
print(f"年龄是{age}")
set_age(-1)
自定义异常
class MyException(Exception):
def __init__(self,msg):
print(f"这是一个异常:{msg}")
def set_age(age: int):
if age <= 0 or age > 150:
raise MyException(f"年龄的值错误:{age}")
else:
print(f"年龄是{age}")
set_age(-2)
程序调试:修正语法错误、逻辑错误的过程
打印、日志 、debug
import logging
logging.basicConfig(level=logging.INFO)
logging.info("sdsds")
operating system
系统相关操作,处理文件、目录…
import os
# 查看说明文档
help(os)
# 查看所有属性和方法名称
print(dir(os))
os.name:获取系统名称,nt代表Windows,posix代表linux
os.environ:获取系统环境变量信息
os.getenv(‘PATH’):获取指定名称的环境变量信息
os.system():执行系统指令,模拟cmd指令
os.getcwd():获取当前目录
os.chdir():切换目录,cd命令
os.listdir():列出当前目录内容
os.mkdir():创建空目录
os.makedirs():递归创建多级目录
os.rmdir():删除空目录
os.rename():重命名目录
os.remove():删除文件
os.path.abspath(path) 返回绝对路径os.path.abspath(file)
os.path.basename(path) 返回文件名
os.path.dirname(path) 返回文件路径
os.path.split(path) 分割路径
os.path.join(path) 拼接路径
os.path.exists(path) 判断路径是否存在
os.path.isdir(path) 判断是否是目录
os.path.isfile(path) 判断是否是文件
os.path.getsize(path) 获取文件大小,单位是字节
与python解释器交互
sys.version:返回 Python 解释器版本
sys.platform:返回操作系统平台名称
sys.argv:返回外部向程序传递的参数
sys.modules:返回已导入的模块信息
sys.path:返回导包的搜索路径列表
sys.getdefaultencoding():获取编码方式
sys.exit():运行时退出
import sys,time
for i in range(10):
if i == 6:
print("exit...")
sys.exit("正常退出")
print(f"running {i} ...")
time.sleep(1)
打开文件、操作文件(读写追加)、关闭文件
def open(file, mode=‘r’, buffering缓冲区大小=None, encoding=None, errors=None, newline换行符=None, closefd=True):
r 只读 ,r+ 读 写,替换原来的内容,覆盖原有内容,如果内容很少,就只会覆盖一部分
w 写入 , w+ 读 写,没有文件时新建文件,清空内容再写入
a 追加 , a+ 读 写,追加内容
b 二进制(音乐、视频…)
f = open('demo.txt','r',encoding='utf-8')
print(f.read())
f.close()
忘记关闭文件的危害:打开文件达到一定数量将会导致打开失败;占用内存空间,非常浪费资源;会导致系统自动回收资源,而丢失数据。
with 自动关闭文件
with open('demo.py','r',encoding='utf-8') as f:
print(f.read())
日志信息里需要时间;计算某个功能的执行时间;用日期命名文件;生成随机数…
time
datatime
calendar
时间戳:浮点数
格式化的时间字符串
import datetime
nowtime = datetime.datetime.now()
print(nowtime)# 2022-06-28 10:24:45.959896
print(nowtime.day)# 28
print(nowtime.timestamp())# 1656383085.959896
old_time = datetime.datetime(2011,6,2,10,15)
print(old_time)# 2011-06-02 10:15:00
str0 = old_time.strftime('%a, %b %d %H:%M')
print(str0)# Thu,Jun 02 10:15
str1 = "2011-06-02 10:15:00"
time1 = datetime.datetime.strptime(str1,"%Y-%m-%d %H:%M:%S")
print(time1)# 2011-06-02 10:15:00
time2 = datetime.datetime.fromtimestamp(nowtime.timestamp())
print(time2)# 2022-06-28 10:27:27.995164
JSON 是用于存储和交换数据的语法,是一种轻量级的数据交换格式。
使用场景:接口数据传输、序列化、配置文件
可以从字符串或文件中解析 JSON,该库解析 JSON 后将其转为 Python 字典或者列表
dumps():将 Python 对象编码成 JSON 字符串
loads():解码 JSON 字符串数据,该函数返回 Python 对象
dump(): Python 对象编码,并将数据写入 json 文件中
load():从 json 文件中读取数据并解码为 Python 对象
import json
with open("./demo.json") as f:
data:dict = json.loads(f.read())
dumps 常用参数
indent:根据数据格式缩进显示,默认为 None,没有缩进
ensure_ascii:对中文使用 ASCII 编码,默认为 True
正则表达式:记录文本规则的代码,可以查找操作符合某些复杂规则的字符串
作用:处理字符串\处理日志
把正则表达式作为模式字符串,正则表达式可以使用原生字符串来表示,原生字符串需要在字符串前方加上 r’string’
正则表达式对象转换
compile():将字符串转换为正则表达式对象,需要多次使用这个正则表达式的场景
import re
'''
prog:正则对象,可以直接调用匹配、替换、分割的方法,不需要再传入正则表达式
pattern:正则表达式
'''
pattern = r"apple"
prog = re.compile(pattern)
匹配字符串
re.match():从字符串的开始处进行匹配
re.search():在整个字符串中搜索第一个匹配的值
re.findall():在整个字符串中搜索所有符合正则表达式的字符串,返回列表
'''
pattern: 正则表达式
string: 要匹配的字符串
flags: 可选,控制匹配方式
- A:只进行 ASCII 匹配
- I:不区分大小写
- M:将 ^ 和 $ 用于包括整个字符串的开始和结尾的每一行
- S:使用 (.) 字符匹配所有字符(包括换行符)
- X:忽略模式字符串中未转义的空格和注释
'''
re.match(pattern, string, [flags])
re.search(pattern, string, [flags])
re.findall(pattern, string, [flags])
import re
pattern = r"apple"
s1 = "Apple is a fruit"
match1 = re.match(pattern,s1,re.I)
print(match1)#
print(f"匹配起始位置:{match1.start()},结束位置:{match1.end()}")
print(f"匹配位置:{match1.span()}")
print(f"要匹配的字符串:{match1.string},匹配到的数据:{match1.group()}")
import re
pattern = r"apple"
s1 = "Apple is a fruit"
match1 = re.match(pattern,s1,re.I)
print(match1)#
print(f"匹配起始位置:{match1.start()},结束位置:{match1.end()}")
print(f"匹配位置:{match1.span()}")
print(f"要匹配的字符串:{match1.string},匹配到的数据:{match1.group()}")
re.sub():实现字符串替换
'''
pattern:正则表达式
repl:要替换的字符串
string:要被查找替换的原始字符串
count:可选,表示替换的最大次数,默认值为 0,表示替换所有匹配
flags:可选,控制匹配方式
'''
re.sub(pattern, repl, string, [count], [flags])
re.split():根据正则表达式分割字符串,返回列表
'''
pattern:正则表达式
string:要匹配的字符串
maxsplit:可选,表示最大拆分次数
flags:可选,控制匹配方式
'''
re.split(pattern, string, [maxsplit], [flags])
线程:小丑扔一个苹果
多线程:小丑扔三个苹果,3个线程轮巡执行,谁也不会在空中多停留一会儿
GIL 在同一时刻,只能有一个线程在运行
并发
排队,线程一执行完,再执行线程二,本质跟一个线程一样(如果有sleep)
信息交互方便,高效,资源切换比较快
flask
import threading
def task():
print("扔第二个苹果")
def task2():
print("扔第三个苹果")
def main():
print("扔第一个苹果")
# 创建线程
thread1 = threading.Thread(target=task)
# 执行线程
thread1.start()
thread2 = threading.Thread(target=task2)
thread2.start()
if __name__ == '__main__':
main()
多进程:3个小丑扔苹果,3个苹果同时在空中,但每个小丑的苹果不方便通讯,慢
并行
应用场景:cpu大量计算,cpu逻辑处理器
import datetime
import threading
from time import sleep
def task():
sleep(3)
print("扔第二个苹果")
def task2():
sleep(5)
print("扔第三个苹果")
def main():
start_time = datetime.datetime.now()
print(start_time)
print("扔第一个苹果")
thread1 = threading.Thread(target=task)
thread2 = threading.Thread(target=task2)
thread1.start()
thread2.start()
# 让其他线程等待自己执行完成
thread1.join()
thread2.join()
end_time = datetime.datetime.now()
print(end_time)
if __name__ == '__main__':
main()
https://docs.python.org/zh-cn/3/howto/logging.html
日志作用:调试;辅助定位;数据分析
import logging
# create logger
logger = logging.getLogger('simple_example')
logger.setLevel(logging.DEBUG)
# create console handler and set level to debug
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
# create formatter
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
# add formatter to ch
ch.setFormatter(formatter)
# add ch to logger
logger.addHandler(ch)
# 'application' code
logger.debug('debug message')
logger.info('info message')
logger.warning('warn message')
logger.error('error message')
logger.critical('critical message')
[loggers]
keys=root,main
[handlers]
keys=consoleHandlers,fileHandlers
[formatters]
keys=fmt
[logger_root]
level=DEBUG
handlers=consoleHandlers,fileHandlers
[logger_main]
level = DEBUG
handlers = fileHandlers
qualname=main
propagate=0
[handler_consoleHandlers]
class = StreamHandler
level = DEBUG
formatter = fmt
args = (sys.stdout,)
[handler_fileHandlers]
class = logging.handlers.RotatingFileHandler
level = DEBUG
formatter = fmt
args = ('./logs/test.log', 'a', 10000, 3, 'UTF-8')
[formatter_fmt]
format=%(asctime)s (%(filename)s:%(lineno)s) [%(levelname)s] %(message)s
import logging.config
logging.config.fileConfig('logging.conf')
# create logger
logger = logging.getLogger('main')
# 'application' code
logger.debug('debug message')
logger.info('info message')
logger.warning('warn message')
logger.error('error message')
logger.critical('critical message')
https://pypi.org/ 托管了大量流行的 Python 包
查看 pip 版本 pip -V
查看帮助文档 pip help
查看包列表 pip list
导出包列表 pip freeze
安装 pip install 包名
升级 pip install -U 包名
卸载 pip uninstall 包名
pip install -U pytest
升级已安装的 Python 包
pip install -i 镜像源
阿里源:https://mirrors.aliyun.com/pypi/simple/
清华源:https://pypi.tuna.tsinghua.edu.cn/simple/
豆瓣源:http://pypi.douban.com/simple/
使用镜像
pip install pytest -i https://pypi.douban.com/simple
venv 虚拟环境的优点:独立的 Python 环境,不会产生冲突;有助于包的管理;删除和卸载方便。
venv 使用方法:创建虚拟环境;激活虚拟环境;安装 Python 包。
venv 创建虚拟环境
python3 -m venv test
venv 激活虚拟环境
切换指定文件夹
Windows:/Scripts/
macOS:/bin/
执行指令:activate
# Windows 系统激活虚拟环境
cd test
cd Scripts
activate
# macOS系统激活虚拟环境
cd test
cd bin
source actiavte
# 或者一步到位
source ./test/bin/acitvate
一种数据序列化格式,用于人类的可读性和与脚本语言的交互,一种被认为可以超越 XML、JSON 的配置文件。
YAML 基本语法规则:大小写敏感;使用缩进表示层级关系;缩进时不允许使用 Tab 键,只允许使用空格;缩进的空格数目不重要,只要相同层级的元素左侧对齐即可;#表示注释,从这个字符一直到行尾都被注释掉了
对象:键值对的集合,用冒号 “:” 表示
数组:一组按次序排列的值,前加 “-”
纯量:单个的、不可再分的值,字符串、布尔值、整数、浮点数、Null、时间、日期
Python 的 YAML 解析器和生成器
官网:https://pypi.org/project/PyYAML/
安装:pip install pyyaml
创建 yaml 文件
import yaml
data = {
"client": {"default-character-set": "utf8"},
"mysql": {"user": 'root', "password": 123},
"custom": {
"user1": {"user": "张三", "pwd": 666},
"user2": {"user": "李四", "pwd": 999},
}
}
# 直接 dump 可以把对象转为 YAML 文档
with open('./my.yaml', 'w', encoding='utf-8') as f:
yaml.dump(data, f, allow_unicode=True)
读取 yaml 文件
import yaml
file_path = './my.yaml'
with open(file_path, 'r', encoding='utf-8') as f:
data = yaml.safe_load(f)
print(data)
Python 的数据库接口标准是 Python DB-API
PyMySQL 是从 Python 连接到 MySQL 数据库服务器的接口
PyMySQL 的目标是成为 MySQLdb 的替代品
官方文档:http://pymysql.readthedocs.io/
host:MySQL 服务器地址
user:用户名
password:密码
database:数据库名称
charset:编码方式,推荐使用 utf8mb4
import pymysql
# 1.封装建立连接的对象
def get_conn():
conn = pymysql.connect(
host="服务器地址",
user="root",
password="123456",
database="数据库名",
charset="utf8mb4"
)
return conn
from . import get_conn
def test_demo():
# 1.获取连接对象
conn = get_conn()
# 2.获取游标对象
cursor = conn.cursor()
# 3.执行SQL
cursor.execute("SELECT VERSION();")
# 4.查询结果
version = cursor.fetchone()
print(f"数据库的版本是:{version}")
# 5.关闭连接
conn.close()
CRUD 操作:
创建表
插入记录
查询记录
更新记录
删除记录
执行事务:
提交:commit
回滚:rollback
pymysql 创建表
from . import get_conn
def test_create():
conn = get_conn() # 获取连接
cursor = conn.cursor() # 获取游标
sql = """
CREATE TABLE `testcase` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`title` varchar(255) COLLATE utf8_bin NOT NULL,
`expect` varchar(255) COLLATE utf8_bin NOT NULL,
`owner` varchar(255) COLLATE utf8_bin NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
"""
cursor.execute(sql) # 执行SQL
conn.close() # 关闭连接
pymysql 插入操作
from . import get_conn
def test_insert():
conn = get_conn() # 获取连接
cursor = conn.cursor() # 获取游标
sql = """INSERT INTO testcase
(id, title, expect, owner)
values (1, 'S11总决赛', '冠军', 'EDG');
"""
cursor.execute(sql) # 执行SQL
conn.commit() # 提交
执行事务
from . import get_conn
def test_insert():
conn = get_conn() # 获取连接
cursor = conn.cursor() # 获取游标
sql = """INSERT INTO testcase
(id, title, expect, owner)
values (2, 'S11全球总决赛', '冠军', 'EDG');
"""
try:
cursor.execute(sql) # 执行SQL
conn.commit() # 提交事务
except:
conn.rollback() # 回滚事务
finally:
conn.close() # 关闭连接
pymysql 查询操作
fetchone():获取单条记录
fetchmany(n):获取 n 条记录
fetchall():获取所有结果记录
import sys
from . import get_conn
def test_retrieve():
conn = get_conn() # 获取连接
cursor = conn.cursor() # 获取游标
sql = "SELECT * FROM testcase;"
# 捕获异常
try:
cursor.execute(sql) # 执行SQL
record = cursor.fetchone() # 查询记录
print(record)
except Exception as e:
print(sys.exc_info()) # 打印错误信息
finally:
conn.close() # 关闭连接
pymysql 更新操作
from . import get_conn
def test_update():
conn = get_conn()
cursor = conn.cursor()
sql = "UPDATE testcase SET owner='hogwarts' WHERE id=2;"
try:
cursor.execute(sql) # 执行SQL
conn.commit() # 提交事务
except:
conn.rollback() # 回滚事务
finally:
conn.close() # 关闭连接
pymysql 删除操作
from . import get_conn
def test_delete():
conn = get_conn() # 获取连接
cursor = conn.cursor() # 获取游标
sql = "DELETE FROM testcase WHERE id=3;"
try:
cursor.execute(sql) # 执行SQL
conn.commit() # 提交事务
except:
conn.rollback() # 回滚事务
finally:
conn.close() # 关闭连接
发起网络请求:内置模块urllib第三方库requests、urllib3
线程安全;连接池管理;客户端 SSL/TLS 验证;支持 HTTP 和 SOCKS 代理
官方文档:https://urllib3.readthedocs.io/en/stable/
import urllib3
def test_response():
# 创建连接池对象
pm = urllib3.PoolManager()
# 发送请求
resp = pm.request(method='GET', url="http://httpbin.org/ip")
print(type(res))
print(resp.status) # 查看响应状态状态码
print(resp.headers) # 查看响应头信息
print(resp.data) # 查看响应原始二进制信息
二进制响应内容解码,成JSON 字符串
import urllib3
import json
def test_response():
pm = urllib3.PoolManager()
resp = pm.request(method='GET', url="http://httpbin.org/ip")
# 获取二进制形式的响应内容
raw = resp.data
print(type(raw), raw)
# 使用utf-8解码成JSON字符串
content = raw.decode('utf-8')
print(type(content), content)
# 将JSON字符串解析成字典对象
dict_obj = json.loads(content)
print(type(dict_obj), dict_obj)
print(dict_obj['origin'])
语法:request(method, url, fields, headers, **)
必填
method:请求方式
url:请求地址
选填
headers:请求头信息
fields:请求体数据
body:指定请求体类型
tiemout:设置超时时间
import urllib3
import json
def test_headers():
pm = urllib3.PoolManager()
url = "http://httpbin.org/get"
# 定制请求头
headers = {'School': 'hogwarts'}
resp = pm.request('GET', url, headers=headers)
定制查询字符串参数
fields 参数:适用于GET, HEAD, DELETE 请求
拼接url:适用于POST, PUT请求
import urllib3
import json
# GET/HEAD/DELETE 请求
def test_fields():
pm = urllib3.PoolManager()
url = "http://httpbin.org/get"
fields = {'school': 'hogwarts'}
resp = pm.request(method='GET', url=url, fields=fields)
# POST/PUT 请求
def test_urlencode():
# 从内置库urllib的parse模块导入编码方法
from urllib.parse import urlencode
pm = urllib3.PoolManager()
url = "http://httpbin.org/post"
# POST和PUT请求需要编码后拼接到URL中
encoded_str = urlencode({'school': 'hogwarts'})
resp = pm.request('POST', url=url+"?"+encoded_str)
提交 form 表单数据
类型 ‘Content-Type’: 'multipart/form-data
请求方式:POST、PUT
import urllib3
import json
# POST/PUT 请求
def test_form():
pm = urllib3.PoolManager()
url = "http://httpbin.org/post"
fields = {'school': 'hogwarts'}
# fields数据会自动转成form格式提交
resp = pm.request('POST', url, fields=fields)
提交 JSON 格式数据
类型:‘Content-Type’: ‘application/json’
请求方式:POST、PUT
import urllib3
import json
def test_json():
pm = urllib3.PoolManager()
url = "http://httpbin.org/post"
# 设定请求体数据类型
headers={'Content-Type': 'application/json'}
# JSON文本数据
json_str = json.dumps({'school': 'hogwarts'})
resp = pm.request('POST', url, headers=headers, body=json_str)
timeout :设置超时时间
时间单位:秒
值的格式:float 类型
import urllib3
def test_timeout():
pm = urllib3.PoolManager()
# 访问这个地址,服务器会在3秒后响应
url = "http://httpbin.org/delay/3"
# 设置超时时长
resp = pm.request(method='GET', url=url, timeout=4.0)
assert resp.status == 200
HTTPS 请求默认需要校验证书
PoolManager 的 cert_reqs 参数"CERT_REQUIRED":需要校验;“CERT_NONE”:取消校验
import urllib3
import json
def test_HTTPS():
# 创建不校验证书的连接池对象
pm_https = urllib3.PoolManager(cert_reqs="CERT_NONE")
url = "https://httpbin.ceshiren.com/get"
# 发送HTTPS请求
resp = pm_https.request(method='GET', url=url)
print(json.dumps(resp.data.decode('utf-8')))
函数引用:函数可以被引用;函数可以被赋值给一个变量。
def school():
print("school")
harry = school# 把函数对象赋值给一个变量
harry()
闭包函数:闭包的内部函数中,对外部作用域的变量进行引用;闭包无法修改外部函数的局部变量;闭包可以保存当前的运行环境。
def output_student(grade):
def inner(name, gender):
print(f"学生的名称是{name},性别是{gender},
\年级是{grade}")
return inner
student = output_student(1)
student("罗恩", "男")
student("哈利", "男")
student("赫敏", "女")
为什么要学习装饰器?
行业需求: 涉及 Python 技术栈,面试常见题
使用需求: 优化代码的可读性,可维护性
需求:函数体开始执行与结束执行的时候分别添加打印信息
# 不使用装饰器的代码
def timer(func):
print("计时开始")
func()
print("计时结束")
def school():
print("school")
timer(hogwarts)
# 使用装饰器的代码
def timer(func):
def inner():
print("计时开始")
func()
print("计时结束")
return inner
@timer
def school():
print("school")
hogwarts()
基本装饰器
def timer(func):
def inner(*args, **kwargs):
func(*args, **kwargs)
return inner
@timer
def aaa(name):
print(f"aaa:{name}")
aaa("Tom")
练习:实现一个计时器的装饰器,计算函数执行时间
import datetime
def timer(func):
def inner(*args, **kwargs):
# 获取当前时间
start_time = datetime.datetime.now()
func(*args, **kwargs)
end_time = datetime.datetime.now()
print(f"函数的执行时间{end_time-start_time}")
return inner
@timer
def school(name):
print("school", name)