基本语法
注释
# 注释
输入输出函数
# 输入
input("请输入:")
# 打印
print("xxx")
变量操作
# 赋值
a = 100
b = 200
c = 300
# 序列解包赋值,左侧变量数量与右侧序列元素数一致
t = (100, 200, 300)
l = [100, 200, 300]
s = "edf"
a, b, c = t
a, b, c = l
a, b, c = s
a, b, c = 100, 200, 300
# 左侧变量数量与右侧序列元素数不一致,剩余的给到最后一个变量
a, *b = t
# 匿名变量,约定使用下划线表示
_ = 1
# 删除变量
del a
命名约定
# 模块
module_name
# 包
package_name
# 类
ClassName
# 方法
function_name
# 异常
ExceptionName
# 全局常量
GLOBAL_CONSTANT_NAME
# 全局变量
global_var_name
# 实例变量
instance_var_name
# 方法参数
function_parameter_name
# 局部变量
local_var_name
# 类常量
CLASS_CONSTANT_NAME
# 特殊作用的方法或属性
__function_name__
# 私有变量
__var_name
# 内部变量
_var_name
# 避免关键字
class_
运行代码
eval("1 + 2")
数据类型
基本数据类型
# 整数
a = -100
# 浮点数
b = 99.99
# 精确十进制数
import decimal
a = decimal.Decimal("0.1")
b = decimal.Decimal("0.2")
print(a + b)
# 0.3
c = decimal.Decimal("0.3")
print(a + b == c)
# True
# 数学计数法
print(0.00005)
# 5e-05
# 复数
x = 1 + 2j
print(x.real)
# 1
print(x.imag)
# 2
# 布尔值
c = True
d = False
# 内置函数返回None
e = None
# 字符串
f = "f"
# 列表
g = [1, 2, 3, 4]
# 元组
h = (1, 2, 3, 4)
h = 1, 2, 3, 4
# 集合
i = {1, 2, 3, 4}
# 字典
j = {
"name": "Tom",
"age": 18
}
布尔类型
调用bool()
结果为False
的情况:
- 定义为
False
的对象:None
和False
- 值为0的数字类型:
0
,0.0
,0j
,Decimal(0)
,Fraction(0,1)
- 空的序列和集合:
''
,()
,[]
,{}
,set()
,range(0)
True
的值等于整数1
False
的值等于整数0
序列
序列是一种可遍历的集合类型,包括字符串、列表、元组、集合。列表和集合为可变序列,字符串和元组为不可变序列。一个序列对象是一个可迭代对象,可迭代对象可重复使用,而迭代器是一次性使用的
序列均可进行以下操作
+
和*
拼接与复制is
和is not
判断是否为同一对象in
和not in
判断元素中是否存在某值del
删除序列中的元素
序列构造器,参数可为另外一个类型的可迭代对象(包括其他类型的序列或迭代器)
list()
列表tuple()
元组str()
字符串,列表或元组转字符串,结果是字符串是列表或元组的代码表现形式set()
集合
# 求最小值
a = (1, 2, 3)
min(a)
# 求最大值
max(a)
# 求长度
len(a)
# 求和
sum(a)
# 排序,返回结果列表
sorted(a)
# 按某方法结果排序
sorted(a, key=len)
# 生成反向迭代器
reversed(a)
# 任意一个元素的值为True,则结果为True
any(a)
# 所有元素的值为True,则结果为True
all(a)
# 创建枚举对象
enumerate(a)
# 多列表联合转成元组列表, 以长度最短的列表长度为元组长度
x = [1, 2, 3]
y = [4, 5, 6]
z = [7, 8, 9]
zipped = zip(x, y, z)
list(zipped)
# [(1, 4, 7), (2, 5, 8), (3, 6, 9)]
# 以长度最长的列表长度为元组长度,没有对应元素的位置以None代替
import itertools
zipped = itertools.zip_longest(x, y, z)
# 遍历映射
# ord函数返回字符的编码
mapped = map(ord, "ABC")
# 支持多参数
# pow函数返回幂运算结果
mapped = map(pow, [2, 3, 10], [5, 2, 3])
# 遍历过滤
filterd = filter(str.islower, "aBc")
# 生成迭代器
iterator = iter(a)
# 遍历迭代器,当没有元素时抛异常
next(iterator)
# 当没有元素时返回默认值
next(iterator, -1)
字符串
字符串是不可变的
# 常规字符串,推荐双引号表示人类可读的文本,单引号表示数据
a = "a"
a = 'a'
# 多行字符串
a = """
a
a
"""
# 取消转义
a = r"\n"
print(a) #\n
# 单行字符串分开多行
a = "aaa\
bbb"
print(a) # aaabbb
# 字符串切片
string = "abcdefg"
string[0] # a
string[-1] # g
string[0:3] # abc
string[:3] # abc
string[-3:-1] # ef
string[-3:] # efg
string[0:6:2] # ace
string[::-1] # gfedcba
# 获取字符串长度
len(string)
# 字符串复制
string * 2 # abcdefgabcdefg
# 从左往右查找指定字符的位置,找不到返回-1
string.find("b")
string.find("c", 0, 5)
# 从右往左查找指定字符的位置,找不到返回-1
string.rfind("b")
string.rfind("c", 0, 5)
# 找不到抛异常
string.index("b")
string.rindex("b")
# 查询指定字符出现的次数
string.count("d")
string.count("d", 0, 5)
# 格式化字符串
string = "name:{}, age:{}"
string.format("Tom", "18") # name:Tom, age:18
# 指定参数位置
string = "name:{0}, age:{1}"
# 指定参数名
string = "name:{name}, age:{age}"
string.format(name="Tom", age="18")
# 指定格式,放在冒号右边,参数格式[[fill]align][sign][#][0][width][grouping_option][.precision][type]
# 冒号左边为上面的参数位置和参数名称
# ^居中 <左对齐 >右对齐 =数字右对齐(如有负号,在负号和数字之间填充) ,后面数字指定总宽度
string = "name:{:>10}, age:{:^10}"
# 指定填充字符
string = "name:{:%>10}, age:{:%^10}"
# 数字加正号
string = "age:{:%^+10}"
# 指定小数点后位数
string = "age:{:.2f}"
# 指定总数字位数
string = "age:{:.2g}"
# 输出二进制数
string = "age:{:b}"
# 输出八进制数
string = "age:{:o}"
# 输出十六进制数
string = "age:{:x}"
# 输出表示进制的前缀
string = "age:{:#b}"
# 科学计数法
string = "age:{:e}"
# 定点六位小数
string = "age:{:f}"
# 自动适配科学计数法和定点六位小数
string = "age:{:g}"
# 百分比
string = "age:{:%}"
# f-字符串,python3.6后支持,与format作用相同,效率更高
name = "Tom"
age = "18"
string = f"name:{name}, age:{age}" # name:Tom, age:18
string = f"name:{name:>10}, age:{age:^10}"
string = "name:%s, age:%d"
string % ("Tom", 18) # name:Tom, age:18
# 字符串拼接
a = "abc"
b = "def"
string = a + b # abcdef
# 去掉空格
string = " a "
string.strip() # a
string.lstrip()
string.rstrip()
# 指定去掉的字符,参数中的字符串中任意一个字符都会被去除
string.strip("abc")
# 去掉前缀
string.removeprefix("a")
string.removesuffix("c")
# 分割字符串,返回三元组(分割符前部分,分割符,分割符后部分)
a.partition(".")
a.rpartition(".")
# 分割字符串,返回分割后的各部分
a.split(".")
# 指定最大分割次数
a.split(".", 1)
a.rsplit(".", 1)
# 按换行符分割
a.splitlines()
# 字符串拼接,参数可以是任意序列,效率比+高
a = "a"
b = "b"
c = "c"
",".join((a, b ,c)) # a,b,c
# 首字母转大写
a.capitalize()
# 全转小写(能处理所有语言的字母)
a.casefold()
# 每个单词的首字母转大写,其他字母转小写
a.title()
# 大小写反转
a.swapcase()
# 全转大写
a.upper()
# 全转小写
a.lower()
# 对齐类,第一个参数为总用的总长度,第二个参数可选,为用于填充的字符
# 居中对齐
a.center(5)
a.center(5, "p")
# 左对齐
a.ljust(5)
# 右对齐
a.rjust(5)
# 左填充0
a.zfill(5)
# 制表符替换空格
a.expandtabs(4)
# 替换全部
a.replace("a", "b")
# 指定替换次数
a.replace("a", "b", 1)
# 转换表格
table = str.maketrans("abc", "123")
a.translate(table)
# 判断开头
a.startswith("a")
a.startswith("a", 1, 2)
# 判断结尾
a.endswith("a")
a.endswith("a", 0, 1)
# 支持从元组中判断,满足任一一个即可
a.startswith(("a", "b"))
# 是否都是单词第一个字母大写,其他小写
a.istitle()
# 是否全是大写
a.isupper()
# 是否全是字母
a.isalpha()
# 是否是空白字符串
a.isspace()
# 是否都是可打印字符(换行符不可打印)
a.isprintable()
# 是否为数字
a.isdecimal()
a.isdigit()
a.isnumeric()
# 是否是字母或数字
a.isalnum()
# 是否是合法的标识符
a.isidentifier()
# 是否为关键字
import keyword
keyword.iskeyword("if")
# 是否包含
"a" in a
"a" not in a
列表
# 创建列表
list1 = [1, 2, 3, 4]
# 访问列表某个位置的值
list1[0] # 第一个值
list1[-1] # 最后一个值
# 往某位置赋值
list1[0] = 10
list1[1:] = [3, 5, 7]
# 获取列表元素个数
len(list1)
list2 = [5, 6, 7, 8]
# 列表的拼接
list1 + list2 # [1, 2, 3, 4, 5, 6, 7, 8]
# 列表元素重复
list1 * 2 # [1, 2, 3, 4, 1, 2, 3, 4]
# 列表切片,包前不包后
list1[0:3] # [1, 2, 3]
# 第一个参数默认为0
list1[:3]
# 第二个参数默认为数组长度
list1[3:]
# 支持步进
list1[0:4:2]
list1[::2]
# 倒序
list1[::-1]
# 删除列表中的指定元素,可以使用切片语法
del list1[3] # [1, 2, 3]
# 往列表末尾增加一个元素
list1.append(4) # [1, 2, 3, 4]
# 往列表的某个位置插入一个元素
list1.insert(0, 0) # [0, 1, 2, 3, 4]
# 删除第一个指定值
list1.remove(4) # [0, 1, 2, 3]
# 往列表末尾增加另一个列表的元素
list1.extend([4, 5]) # [0, 1, 2, 3, 4, 5]
list1[len(list1):] = [4, 5]
# 返回某个元素并删除
list1.pop(1)
# 逆序
list1.reverse()
# 复制列表,浅拷贝
copyList = list1.copy()
copyList = list1[:]
# 排序
list1.sort()
list1.sort(reverse=True)
# 清除列表中的所有值
list1.clear()
# 列表内部可以是不同类型的值
list1 = [1, 2, 3, "s"]
# 某个值元素计数
list1.count(1)
# 查找第一个某值的位置
list1.index(3)
# 指定查找范围
list1.index(3, 1, 2)
# 嵌套列表
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
matrix = [None] * 3
for i in range(3):
matrix[i] = [None * 2]
matrix = [[None] * 2 for i in range(3)]
# 访问嵌套列表的元素
matrix[0][0]
# 判断是否包含
1 in [1, 2]
# 列表推导式,生成一个新列表再赋值
x = [i + 1 for i in range(10)]
# 符合if条件才迭代
a = [i + 1 for i in range(10) if i % 2 == 0]
# 嵌套循环
flatten = [col for row in matrix for col in row]
# 列表元素计数
from collections import Counter
value_list = ['1', '1', '2', '5', '5', '5']
value_list_counter = Counter(value_list)
# value_list_counter {'1': 2, '2': 1, '5': 3},类字典结构,key是列表元素,value是个数
# 获取’1‘的个数,获取不到默认值为0
value_list_counter.get('1', 0)
元组
元组元素不可修改,其它与列表类似
# 创建元组
a = (1, 2, 3, 4)
b = 1, 2, 3, 4
# 创建只有一个元素的元组
c = (1,)
# 访问元组
a[0]
a[-1]
# 元组切片
a[:3]
a[3:]
a[:]
a[::-1]
# 嵌套元组
d = a, b
集合
集合是无序的,且元素不可重复。集合中的元素必须是不可变、可哈希的
# 创建集合
i = {1, 2, 3, 4}
a = set("1234")
# 创建不可变集合
i = frozenset("1234")
# 集合推导式
i = {s for s in "abc"}
# 列表转集合
b = set([1, 2, 3, 4])
# 元组转集合
c = set((1, 2, 3, 4))
# 元素不同类型
e = {1, (1,2), "12"}
# 创建空集合
g = set()
# 遍历集合
for each in i:
print(each)
# 浅拷贝
t = i.copy()
a = {1, 2, 3}
b = {3, 4, 5}
# 是否无交集
a.isdisjoint(b)
# 是否是子集
a.issubset(b)
a <= b
# 是否是真子集
a < b
# 是否是超集
a.issuperset(b)
a >= b
# 是否是真超集
a > b
# 求并集
a.union(b)
a | b
# 求交集
a.intersection(b)
a & b
# 求差集
a.difference(b)
a - b
# 求对称差集
a.symmetric_difference(b)
a ^ b
# 增加一个元素
d.add(5)
f = {6, 7}
# 更新集合元素为并集结果
d.update(f)
# 更新集合元素为交集结果
d.intersection_update(f)
# 更新集合元素为差集结果
d.difference_update(f)
# 更新集合元素为对称差集结果
d.symmetric_difference_update(f)
# 删除一个元素,如果没有则抛异常
d.remove(7)
# 删除一个元素,如果没有不抛异常
d.discard(7)
# 随机返回并删除一个元素
d.pop()
# 清空所有元素
d.clear()
s1 = {1, 2, 3, 5}
s2 = {1, 2, 6, 7}
s3 = s1 & s2
s4 = s1 | s2
字典
Python3.7后字典中的键值对是有序的
字典中的键必须是不可变、可哈希的,字符串类型、数字类型均可作为字典的键
# 创建字典
a = {}
a = {"k1": "v1", "k2": "v2"}
a = dict(k1 = "v1", k2 = "v2")
# 访问字典
a["k1"]
a.get("k1")
# 不存在时返回默认值
a.get("k3", "v3")
# 增加字典值或修改字典值
a["k3"] = "v3"
a["k2"] = "v2"
# 批量修改字典值
a.update({"k1": "v11", "k2": "v22"})
a.update(k1 = "v11", k2 = "v22")
# 有则返回旧值,无则设置并返回新值
a.setdefault("k4", "v4")
# 初始化值一样的字典
keylist = ["k1", "k2"]
dict.fromkeys(keylist, "v1")
# 返回并删除,不存在对应的key则抛异常
a.pop("k1")
# 返回并删除,不存在对应的key则返回默认值
a.pop("k1", "v1")
# 返回键值对元组并删除,如字典有序则返回并删除的是最后一个键值对,否则随机一个
a.popitem()
# 删除
del a["k1"]
# 清空字典元素
a.clear()
# 视图对象,字典改变时,视图对象会跟随改变
# 返回键值对视图对象,视图对象可转为列表
a.items()
# 返回键视图对象
a.keys()
# 返回值视图对象
a.values()
# 浅拷贝
a.copy()
# 获取键值对数量
len(a)
# 判断键是否存在
"k1" in a
"k1" not in a
# 生成迭代器
iterator = iter(a)
# 迭代键
next(iterator)
# 嵌套字典
b = {"k1": {"k11": "v11"}, "k2": {"k22": "v22"}}
b["k1"]["k11"]
# 字典推导式
d = {x: ord(x) for x in "abc"}
检测数据类型
# 检测数据类型,基础数据类型也是一个对象
a = "123"
b = 123
type(a)
# <class 'str>'
type(a) is str
# True
type(b)
# <class 'int>'
# 判断对象是否是某类的实例
isinstance(b, int)
isinstance(b, (int, float, str))
class C:
pass
# 获取对象对应的类型
c.__class__
# 获取类型对应的父类类型
C.__bases__
数据类型转换
使用各类型的构造器来作转换
# 整数转字符串
a = 123
str(a)
# 整数转代码形式字符串
repr(123)
# 整数转布尔值
bool(a)
# True
bool(0)
# False
# 字符串转整数
b = "123"
int(b)
# 字符串转浮点数
float(b)
float("+1E6")
# 字符串转布尔值
bool(b)
# True
bool("")
# False
# 字符串转复数
complex("1+2j")
# 字符串转列表
list(b)
# 字符串转元组
tuple(b)
# 字符串转集合
set(b)
# 列表转字典,列表里的元素可以是列表或元组
dict([["name", "Tom"], ["age", "18"]])
# 元组转字典,元组里的元素可以是列表或元组
dict((["name", "Tom"], ["age", "18"]))
# 浮点数转整数,截掉小数部分
int(9.99)
# 9
类型注解
# 变量
a: int = 10
b: list[int] = [1, 2, 3]
c: tuple[str, int, bool] = ("a", 1, True)
d: dict[str, int] {"a": 1}
stu: Student = Student()
# 函数
def add(x: int, y: int) -> int:
return x + y
from typing import Union
a: list[Union[str, int]] = [1, "a"]
运算
算术运算
# 除法
2 / 4
# 0.5
# 除法,结果向下取值
2 // 4
# 0
# 幂运算
2 ** 3
pow(2. 3)
# 8
# 幂运算后求模
pow(2, 3, 5)
# 3
# 求模
3 % 2
# 1
# 除法,结果向下取值与求模
divmod(3, 2)
# (1, 1)
# 绝对值或求复数的模
abs(-10)
# 10
布尔运算
# 与
True and True
# True
3 and 4
# 4
# 或
False or False
# False
3 or 4
# 3
# 非
not True
同一性运算符
判断两个变量是否为同一对象,即对象的ID是否相等
x = "s"
y = "s"
# 获取对象的ID
id(x)
id(y)
x is y
# True
x is not y
# False
x = [1, 2, 3]
y = [1, 2, 3]
x is y
# False
# 判断是否为空对象
x is None
位运算
# 按位与
3 & 2
# 按位或
3 | 2
# 按位取反
~2
# 按位异或
3 ^ 2
# 左移
8 << 2
# 算术右移,补符号位
8 >> 2
语句结构
条件语句
if a > 0:
print("large")
elif a == 0:
print("small")
else:
print("zero")
# 条件表达式
print("小于10") if age < 10 else print("大于等于10”)
small = a if a < b else b
循环语句
a = 0
while a < 5:
print(a)
a += 1
else:
# 正常循环结束时调用,假如使用break跳出循环,这里将不会被执行
print("out")
# 跳出循环体
a = 0
while True:
print(a)
a += 1
if a > 5:
break
# 跳出本轮循环
a = 0
while a < 5:
if a % 2 == 1:
a += 1
continue
print(a)
a += 1
# 遍历一个列表
for i in [1, 2, 3]:
print(i)
# 遍历一个整数序列,包前不包后
for i in range(0, 10):
# pass为空语句,不干任何事情
pass
# 省略第一个参数,第一个参数默认为0
for i in range(10):
psss
# 支持步进
for i in range(10, 5, -2):
pass
# 遍历字符串里面的每一个字符,每一个字符以字符串的形式
for i in "fish":
print(i)
# 遍历列表,同时遍历内容和索引
for index, item in enumerate(item_list):
print(index)
print(item)
函数
函数基本使用
# 定义函数
def printSometing():
print("something")
# 调用函数
# 没有返回值的函数,默认返回值为`None`
printSomething()
# 带位置参数和返回值的函数
def sum(a, b):
print(a + b)
return a + b
# 传入位置参数
sum(1, 2)
# 传入关键字参数
sum(b = 2, a = 1)
# 位置参数和关键字参数混用时,位置参数要在关键字参数前面
sum(1, b = 2)
# 将元组或列表解包成位置参数传入
l = [1,2]
sum(*l)
# 将字典解包成关键字参数传入
d = {"a": 1, "b": 2}
sum(**d)
# 使用默认参数,默认参数后面必须都是默认参数,默认值应该为不可变对象
def sum(a = 3, b = 5):
print(a + b)
# 指定参数中必须使用位置参数的参数,斜杠前的参数必须使用位置参数
def sum(a, /, b):
return a + b
# 指定参数中必须使用关键字参数的参数,星号后的参数必须使用关键字参数
def sum(a, *, b):
return a + b
# 收集参数,实际参数是一个元组
def myfunc(*args):
print(args)
myfunc(1, 2)
# 收集参数后面只能使用关键字参数
def myfunc(*args, b, c):
print(args, b, c)
myfunc(1, 2, 3, b = 4, c = 5)
# 多返回值,实际使用元组打包
def myfunc():
return 1, 2, 3
x, y, z = myfunc()
# 字典收集参数
def myfunc(**kwargs):
print(kwargs)
myfunc(a = 1, b = 2, c = 3)
# 混用位置参数和收集参数
def printAll(a, *args):
print(a)
print(args)
abc(100, 200, 300)
# 混用位置参数和字典收集参数
def printAll(a, **kwargs):
print(a)
print(b)
abc(100, x = 200, y = 300)
# 混合使用
def printAll(a, b = "b", *args, **kwargs):
print(a)
print(b)
for i in args:
print i
for key, value in kwargs.items():
print(key)
print(value)
c = (1, 2, 3)
d = {
"name": "Tom",
"age": 18
}
printAll("a", "b", *c, **d)
# 函数作为参数
def calculator(compute):
return compute(1, 2)
def sum(x, y):
return x + y
calculator(sum)
函数嵌套
def funa():
x = 1
def funb():
x = 2
print(x)
funb()
print(x)
funa()
# 返回嵌套函数
def getFunction():
def f():
return 1
return f
f = getFunction()
f()
变量作用域
优先级 local > enclosing > global > built-in
# 全局变量
y = 1
def myfunc():
# 局部变量,作用域在函数内
x = 1
print(x)
# 当前作用域找不到的变量,往上层作用域找,这里访问全局变量
print(y)
# 定义一个与全局变量同名的局部变量,后续只会访问局部变量
y = 2
print(y)
def myfuncinner():
# 声明使用上层函数的局部变量
nonlocal x
x = 3
myfuncinner()
print(x)
def myfunc2():
# 声明使用全局变量
global y
y = 2
print(y)
# 闭包变量可修改
def outer():
x = 0
y = 0
def inner(x1, y1):
nonlocal x, y
x += x1
y += y1
print(x, y)
return inner
move = outer()
move(1, 2)
lamda表达式
# 定义lamda表达式
square = lambda x : x * x
# 作为一个函数参数
mapped = map(lambda x : ord(x) + 10, "abc")
生成器
def fib():
back1, back2 = 0, 1
while back1 < 1000:
yield back1
back1, back2 = back2, back1 + back2
generator = fib()
# 生成一个值
next(generator)
# 遍历生成的剩余所有值
for i in generator:
print(i)
# 生成器表达式
generator = (i ** 2 for i in range(10))
函数文档
# 定义函数文档
def fun():
"""
打印abc
"""
print("abc")
# 查看函数文档
help(fun)
类型注释
# 冒号后面加上参数的建议类型,->后面为返回值的预期类型
def times(s:str, n:int) -> str:
return s * n
# 序列或字典中的类型在中括号里面
def times(s:list[int], n:int) -> list[int]:
return s * n
自省
def times(s:str, n:int) -> str:
"""
字符串重复
"""
return s * n
# 获取函数名称
times.__name__
# 获取函数的类型注释
times.__annotations__
# 获取函数文档
times.__doc__
偏函数
固定某一个函数的某参数值,生成新的函数
import functools
square = functools.partial(pow, exp = 2)
square(3)
文件操作
文件读写
# 写模式打开文件,文件不存在则创建,文件存在则原内容会丢失
f = open("C:/Oliver/test.txt", "w", encoding="UTF-8")
f.write("hello")
# 不会自动添加换行符
f.writelines(["hello\n", "hello\n"])
f.flush()
f.close()
# 更新模式打开文件,可读取且可写入
f = open("C:/Oliver/test.txt", "r+", encoding="UTF-8")
f.readable()
# True
f.writeable()
# True
# 文件当前指针的位置
f.tell()
# 重置文件指针的位置
f.seek(0)
# 截取文件内容,范围默认是从起始位置到当前文件指针的位置
f.truncate()
# 指定截取的结束位置
f.truncate(5)
# 读模式打开文件
f = open("C:/Oliver/test.txt", "r", encoding="UTF-8")
# 读取剩余所有字符,直到EOF
f.read()
# 读取指定字符数
f.read(5)
# 读取一行字符串
f.readline()
# 逐行遍历读取文件
for line in f:
print(line)
# with文件上下文管理,文件使用完后自动关闭,且保证抛异常的时候会关闭
with open("C:/Oliver/test.txt", "r", encoding="UTF-8") as f:
pass
os
# 生成路径
import os.path
VIDEO_ORIGIN_UPLOAD_PATH = 'C:/traffic/origin/'
save_file_name = 'test.mp4'
update_path = os.path.join(common_config.VIDEO_ORIGIN_UPLOAD_PATH, save_file_name)
# 获取文件大小
size = os.path.getsize(update_path)
# 删除文件
os.remove(update_path)
pathlib
from pathlib import Path
# 获取当前的工作目录
Path.cwd()
# 创建一个路径
p = Path("C:/Oliver")
# 路径拼接
p = p / "test.text"
# 判断路径是否存在
p.exists()
# 判断是否为一个文件夹
p.is_dir()
# 判断是否为一个文件
p.is_file()
# 获取路径最后一部分,即文件名或文件夹名
p.name
# 获取文件名,不包括后缀名
p.stem
# 获取后缀名
p.suffix
# 获取父级路径
p.parent
# 获取所有祖先目录路径
ps = p.parents
# 遍历所有祖先目录路径
for each in ps:
print(each)
# 使用索引访问
ps[0]
# 拆分路径各部分,使用斜杠作为分割符
p.parts
# 获取路径信息
p.stat()
# 相对路径转绝对路径
p = Path("./doc")
p.resolve()
# 获取当前文件夹下所有文件或文件夹的迭代器
iterator = p.iterdir()
for each in iterator:
print(each)
# 创建文件夹
p.mkdir()
# 文件夹存在不抛异常,创建不存在的父级文件夹
p.mkdir(exist_ok = True, parents = True)
# 打开文件
p = Path("C:/Oliver/test.txt")
f = p.open("w")
# 重命名,类似剪切粘贴
p.rename("C:/Oliver/test1.txt")
# 替换,类似剪切粘贴
p = Path("C:/Oliver/test.txt")
q = Path("C:/Oliver/test1.txt")
p.replace(q)
# 删除文件
p.unlink()
# 删除文件夹,文件夹不为空则抛异常
p = Path("C:/Oliver")
p.rmdir()
# 查找
p.glob("*.py")
p.glob("*/*.py")
# 任意层级子文件夹下查询
p.glob("**/*.py")
pickle
对象序列化保存到一个文件,再从文件反序列化
x = 1
s = "abc"
l = [3, 4, 5]
with open("C:/Oliver/test.pkl", "wb", encoding="UTF-8") as f:
pickle.dump(x, f)
pickle.dump((s, l), f)
with open("C:/Oliver/test.pkl", "rb", encoding="UTF-8") as f:
# 按存的顺序读取出来
x = pickle.load(f)
s = pickle.load(f)
l = pickle.load(f)
异常
异常处理
# 捕获所有异常
try:
1 / 0
except:
print("error")
# 捕获指定异常
try:
1 / 0
except ZeroDivisionError:
print("error")
# 捕获指定的多种异常
try:
1 / 0
except (ZeroDivisionError, TypeError):
print("error")
except (ValueError):
print("another error)
# 定义没有捕获到异常时的处理,和离开try块时的处理
try:
f = open("C:/Oliver/no.txt", "r", encoding="UTF-8")
except Exception as e:
f = open("C:/Oliver/no.txt", "w", encoding="UTF-8")
else:
pass
finally:
f.close()
异常处理嵌套
try:
try:
1 / 0
except:
print("error1")
1 / 0
except:
print("error2)
主动抛出异常
raise
# 指定抛出的异常类型
raise ValueError("error")
# 异常链
try:
1 / 0
except ZeroDivisionError:
raise ValueError("error") from ZeroDivisionError
断言
调试时使用,断言不成立时,抛出AssertionError
s = "abc"
assert s == "abc"
面向对象
封装
# 定义一个类
class Student:
# 定义类属性,实例没有定义对应的同名属性会访问到这里
name = None
age = 0
# 定义类私有属性,实例没有对应的同名属性会访问到这里
__private_attribute = None
# 第一个参数必须是self,指的是当前对象
# 对象初始化函数
def __init__(self, name, age, private_attribute):
self.name = name
self.age = age
# __开头的属性在外部无法被直接调用,此属性外部名字改成_Student__private_attribute
# 对象构造完成后,无法再增加一个私有属性
self.__private_attribute = private_attribute
# 定义实例方法
def print_name(self):
print self.name
# __开头的函数在外部无法被直接调用,此函数外部名字改成_Student__private_method
def __private_method(self):
pass
# 创建一个对象
student = Student()
# 定义对象的属性
student.name = "Tom"
student.age = 18
# 增加对象的属性
student.height = 180
# 调用对象的方法
student.print_name()
# 查询对象的属性
student.__dict__
class Student:
# 限制该类的对象的属性,可降低内存占用量。子类对象的属性不会受父类的__slots__定义限制
__slots__ = ["name", "age"]
def __init__(self, name, age):
self.name = name
self.age = age
继承
# 继承的父类写在括号里
class SubStudent(Student):
sex = None
# super() 依赖MRO顺序,在钻石继承时调用自动去重
def __init__(self, name, age, sex):
super().__init__(name, age)
self.sex = sex
# 重写父类方法
def printName(self):
Student.printName(self)
super().printName()
print("Hello")
# 判断是否是某个类的子类
issubclass(SubStudent, Student)
# 多重继承,当多个父类有相同名称的属性和方法时,左边的父类优先
class A:
x = 1
def hello(self):
print("A")
class B:
x = 2
def hello(self):
print("B")
class C(A, B):
pass
# 查询MRO,继承关系中查找属性或方法的顺序
C.mro()
C.__mro__
多态
不需要继承的支持,不需要检查类型
class A:
x = 1
def hello(self):
print("A")
class B:
x = 2
def hello(self):
print("B")
def sayHello(obj):
obj.hello()
a = A()
b = B()
sayHello(a)
sayHello(b)
方法解析顺序
方法解析顺序(Method Resolution Order,MRO)通过继承关系确定,子类在顺序的前面,父类在顺序的后面。假如同一层级多继承,则先声明的在前面。
直接通过对象引用调用方法时,使用该对象对应类型的MRO,从头开始往后找,调用找到的第一个方法
通过super()
调用方法时,使用self
对象对应类型的MRO,从当前代码所在的类开始往后找,调用找到的第一个方法
class Displayer:
def display(self, message):
# 3.打印"abc"
print(message)
class LoggerMixin
def log(self, message, filename = "logfile.txt"):
# 6.self参数是subclass,message参数是"abc",filename参数是"subclasslog.txt"
# 打开subclasslog.txt文件,写入"abc"
with open(filename, "a") as f:
f.write(message)
def display(self, message):
# 2.self参数是subclass,message参数是"abc"
# super()根据self的类型MySubClass的MRO,再根据LoggerMixin往后找,找到Displayer的display方法
super().display(message)
# 4.self参数是subclass,根据MySubClass类的MRO,调用MySubClass重写的log方法
self.log(message)
class MySubClass(LoggerMixin, Displayer):
def log(self, message):
# 5.self参数是subclass,message参数是"abc"
# uper()根据self的类型MySubClass的MRO,再根据MySubClass往后找,找到LoggerMixin的log方法
super().log(message, filename = "subclasslog.txt")
subclass = MySubClass()
# 1.根据MySubClass类的MRO,找到LoggerMixin的display方法
subclass.display("abc")
组合
class Bird:
def sayHello(self):
print("bird")
class Cat:
def sayHello(self):
print("cat")
class Dog:
def sayHello(self):
print("dog")
class Garden:
bird = Bird()
cat = Cat()
dog = Dog()
def sayHello(self):
self.bird.sayHello()
self.cat.sayHello()
self.dog.sayHello()
魔法方法
class CapStr(str):
# 创建对象,在__init__之前被调用
def __new__(cls, string):
string = string.upper()
return super().__new__(cls, string)
class C:
# 初始化方法
def __init__(self, x):
print("init")
self.x = x
# 对象被垃圾回收前被调用的方法
def __del__(self):
print("del")
# +运算符方法重写
def __add__(self, other):
return self.x + other.x
# +=运算符方法重写
def __iadd__(self, other):
# 不实现
return NotImplemented
# 属性被访问时调用的方法重写
def __getattribute__(self, attrname):
print("exist")
return super().__getattribute__(attrname)
# 对象不存在的属性被访问时调用的方法重写
def __getattr__(self, attrname):
print("not exist")
# 属性被设置时调用的方法重写
def __setattr__(self, name, value):
self.__dict__[name] = value
# 属性被删除时调用的方法重写
def __delattr__(self, name):
del self.__dict__[name]
# 对象使用[]获取值时调用的方法重写
def __getitem__(self, index):
return NotImplemented
# 对象使用[]设置值时调用的方法重写
def __setitem__(self, index):
return NotImplemented
# 对象被使用for in迭代时被调用的方法重写,未定义时使用__getitem__代偿
def __iter__(self):
return NotImplemented
def __next__(self):
return NotImplemented
# 对象被调用in或not in时被调用的方法重写,未定义时使用__iter__和__next__代偿
def __contains__(self, item):
return NotImplemented
# 对象作为参数被调用bool()时被调用的方法重写,未定义时使用__len__代偿
def __bool__(self):
return True
# 对象比较时被调用的方法重写
def __lt__(self, other):
return self.x < other.x
def __le__(self, other):
return self.x <= other.x
def __gt__(self, other):
return self.x > other.x
def __ge__(self, other):
return self.x >= other.x
def __eq__(self, other):
return self.x == other.x
def __ne__(self, other):
return self.x != other.x
# 直接使用()调用对象时,被调用的方法重写
def __call__(self):
print("call")
# 带参数
def __call__(self, *args, **kwargs):
print("call")
# 对象作为参数被调用str()时被调用的方法重写,未定义时使用__repr__代偿
def __str__(self):
return str(self.x)
# 对象作为参数被调用repr()时被调用的方法重写
def __repr__(self):
return repr(self.x)
属性代理
# x代理_x
class C:
def __init__(self):
self._x = 1
def getx(self):
return self._x
def setx(self, value):
self._x = value
def delx(self):
del self._x
x = property(getx, setx, delx)
c = C()
print(c.x)
c.x = 2
del c.x
# 装饰器写法
class E:
def __init__(self):
self._x = 1
@property
def x(self):
return self._x
@x.setter
def x(self, value):
self._x = value
@x.deleter
def x(self):
del self._x
类方法
class C:
count = 0
@classmethod
def get_count(cls):
print(cls.count)
c = C()
c.get_count()
静态方法
class C:
count = 0
@staticmethod
def get_count():
print(C.count)
c = C()
c.get_count()
动态创建类
C = type("C", (), {})
c = C()
# 增加继承
D = type("D", (C,) {})
d = D()
# 增加属性和方法
def fun(self):
pass
E = type("E", (), {x = 1, y = 2, fun = fun})
# 增加给__init_subclass__方法的参数
F = type("F", (), {x = 1, y = 2, fun = fun}, value1 = 1, value2 = 2)
子类初始化方法
class C:
# 子类初始化时调用,cls后面的参数可选
def __init_subclass__(cls, value1, value2):
print("abc")
class D(C, value1 = 1, value2 = 2):
pass
d = D()
# abc
元类
元类与类的关系,类似类与对象的关系
# 元类继承type
class MetaC(type):
# 在类创建时执行
def __new__(mcls, name, bases, attrs):
# 增加一个对象
attrs["x"] = 1
return type.__new__(mcls, name, bases, attrs)
# 在类初始化时执行
def __init__(cls, name, bases, attrs):
if not name.istitle():
raise TypeError("error")
type.__init__(cls, name, bases, attrs)
# 在类的构造方法被调用时执行
def __call__(cls, *args, **kwargs):
new_args = [each.upper() for each in args if isinstance(each, str)]
return type.__call__(cls, *new_args, **kwargs)
class C(metaclass = MetaC):
pass
# 单例
class SingleInstance(type):
def __init__(cls, *args, **kwargs):
cls.__instance = None
type.__init__(cls, *args, **kwargs)
def __call__(cls, *args, **kwargs):
if cls.__instance is None:
cls.__instance = type.__call__(cls, *args, **kwargs)
return cls.__instance
class Cat(metaclass=SingleInstance):
pass
查看对象定义列表
# 查看当前模块的定义,变量、函数、类
dir()
# 增加对象参数
dir(c)
抽象基类
from abc import ABCMeta, abstractmethod
class Animal(metaclass = ABCMeta):
def __init__(self, name, age):
self.name = name
self.age = age
@abstractmethod
def say(self):
pass
class Cat(Animal):
def say(self):
print("cat")
class Dog(Animal):
def say(self):
print("dog")
c = Cat()
d = Dog()
def animal_say(animal):
animal.say()
animal_say(c)
animal_say(d)
描述符
实现了__set__
或delete__
方法的称为数据描述符,只实现__get__
方法的称为非数据描述符
访问数据时,优先级为数据描述符 > 实例对象属性 > 非数据描述符 > 类属性
# 定义描述符,需实现__get__,__set__,__delete__三个方法
class D:
def __get__(self, instance, owner):
return instance._x
def __set__(self, instance, value):
instance._x = value
def __delete__(self, instance):
del instance._x
class C:
def __init__(self, x):
self._x = x
# 使用D描述符去管理属性x,描述符只能用在类属性
x = D()
c = C(1)
print(c.x)
c.x = 2
del c.x
# Python3.6以后增加__set_name__方法
class D:
def __set_name__(self, owner, name):
self.name = name
def __get__(self, instance, owner):
return instance.__dict__.get(self.name)
def __set__(self, instance, value):
instance._dict__[self.name] = value
class C:
# 使用D描述符去管理属性x,属性x的名称传递到__set_name__方法
x = D()
装饰器
函数作为函数的装饰器
def add(func):
def inner():
x = func()
return x + 1
return inner
def cube(func):
def inner():
x = func()
return x * x * x
return inner
def square(func):
def inner():
x = func()
return x * x
return inner
# 靠近方法定义的装饰器先生效
@add
@cube
@square
def test():
return 2
test()
# 相当于
add(cube(square(test)))()
# 原方法接收参数
def subtract(func):
def inner(*args, **kwargs):
x = func(*args, **kwargs)
return x - 1
return inner
@subtract
def test(number):
return number
# 带参数的装饰器
import time
def logger(msg):
def time_master(func):
def call_func():
start = time.time()
func()
stop = time.time()
print(f"[{msg}]-{(stop-start):.2f}")
return call_func
return time_master
@logger(msg = "A")
def funA():
time.sleep(1)
print("AAA")
# 防止装饰器改变函数的名称
import time
import functools
def time_master(func):
@functools.wraps(func)
def call_func():
start = time.time()
func()
stop = time.time()
print(f"{(stop - start):.2f}")
return call_func
@time_master
def myfunc():
print("a")
myfunc.__name__
# myfunc
函数作为类的装饰器
def report(cls):
def oncall(*args, **kwargs):
# 实例化前后做操作
print("1")
_ = cls(*args, **kwargs)
print("2")
return _
return oncall
@report
class C:
pass
c = C(1, 2, 3)
# 相当于
report(C)(1,2,3)
类作为函数的装饰器
class Counter:
def __init__(self, func):
self.count = 0
self.func = func
def __call__(self, *args, **kwargs):
self.count += 1
print(self.count)
return self.func(*args, **kwargs)
@Counter
def say_hi():
print("hi")
say_hi()
# 相当于
Counter(say_hi)()
模块和包
模块
一个py文件可看作为一个模块,一个模块被引入时,相当于整个模块执行一遍
hello.py
# 控制 from hello import * 导入的内容
__all__ = ["say_hello", "say_hi"]
def say_hello():
print("hello")
def say_hi():
print("hi")
def say_what():
print("what")
class Cat:
pass
if __name__ == "__main__":
# 被引入时,此处不执行
# 只有在本模块作为入口被独立运行时,__name__的值是__main__,否则__name__的值是模块名,如hello。引入时带包,则前面加上包名,如util.hello
print("abc")
引入整个模块
import hello
hello.say_hello()
hello.say_hi()
hello.say_what()
cat = hello.Cat()
引入整个模块并加上别名
import hello as h
h.say_hello()
h.say_hi()
h.say_what()
cat = h.Cat()
引入模块中的对象或类
from hello import say_hello, say_hi, Cat
say_hello()
say_hi()
cat = Cat()
引入模块中的全部对象,受__all__
属性限制。引入的对象名有冲突时,后引入的优先级高
from hello import *
say_hello()
say_hi()
包
一个包含__init__.py
文件和其它模块py文件的文件夹,可看作为一个包,Python3.3以及之前的版本,__init__.py
文件是必须的
包文件夹中可以包含子文件夹作为子包,子包不需要__init__.py
文件
util/hello.py
def say_hello():
print("hello")
def say_hi():
print("hi")
def say_what():
print("what")
class Cat:
pass
# 被引入时,此处不执行
# 只有在本模块被独立运行时,__name__的值是__main__,否则__name__的值是模块名
if __name__ == "__main__":
print("abc")
util/__init__.py
# 包被引入时执行
print("util")
引入包中的某个模块
test.py
import util.hello
util.hello.say_hello()
util.hello.say_hi()
util.hello.say_what()
cat = util.hello.Cat()
引入包中某些模块,如使用*
,则受__init__.py
中的__all__
属性限制
util/__init__.py
# 控制 from util import * 引入的模块
__all__ = ["hello"]
test.py
from util import hello
hello.say_hello()
hello.say_hi()
hello.say_what()
cat = hello.Cat()
test.py
from util import *
hello.say_hello()
hello.say_hi()
hello.say_what()
cat = hello.Cat()
引入包中某模块的某些类和对象
test.py
from util.hello import Cat, say_hello
say_hello()
cat = Cat()
省略模块
util/__init__.py
from .hello import Cat
from .hello import say_hello
test.py
from util import Cat, say_hello
say_hello()
cat = Cat()
类库
随机数
import random
# 1到10之间随机生成一个整数,前后包含
random.randint(1, 10)
拷贝
import copy
# 浅拷贝
x = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
y = copy.copy(x)
# 深拷贝
z = copy.deepcopy(x)
reduce
import functools
functools.reduce(lambda x, y : x + y, [1, 2, 3 , 4, 5])
JSON
import json
string = json.dumps(data, ensure_ascii = False)
dictionary = json.loads(data)