集合(set)
集合:是一个不重复无序的元素序列,里面的元素不可重复。无序的。
set1 = {1, 3, 3}
set2 = set()
# 定义字典
set3 = {}
# 打印数据类型
type()
# 打印元素类型
print(f'set:{set1}')
# list 转换set
set4 = set([1, 2, 1,2])
# set 转换 list
list1 = list(set4)
集合公共操作符
函数名 | 描述 |
---|---|
len() | 计算容器中元素个数 |
del 或del() | 删除 自动补位 |
max() | 返回容器中元素最大值 |
min() | 返回容器中元素最小值 |
range(start,end,step) | 生成从start到end的数字,步长为step,供for循环使用,如果使用需要进行类型转换。list(range(1,3)) |
enumerate() | 函数用于将一个可遍历的数据对象(如列表,元素或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在for循环中 。格式:(集合,下标起始值) |
l1 = range(1, 5)
en1 = enumerate(l1) # 输出为(0, 1) (1, 2) (2, 3) (3, 4)
en2 = enumerate(l1, 2) # 输出为(2, 1) (3, 2) (4, 3) (5, 4) 指定起始角标
列表集合字典推导式
什么是推导式?推导式又称解析式,是python的一种独有特性,推导式是可以从一个数据序列构建另一个新的数据序列(一个有规律的列表或控制一个有规律列表)的结构体。共有三种推导:列表推导式,集合推导式,字典推导式
列表推导式
变量名 = [表达式 for 变量 in 列表 for 变量 in 列表 ]
变量名 = [表达式 for 变量 in 列表 if 条件]
l1 = [i for i in range(10)]
print(l1) [0,1,2,3,4,5,6,7,8,9]
l2 = [i for i in range(10) if i % 2 ==0]
print(l1) [0,2,4,6,8]
l3 = [(i,j) for i in range(1,5) for j in range(2)]
print(l1) [(1, 0), (2,1), (3, 0), (4,1)]
# 创建一个字段,字典key为1-5数字,value是这个数字的2次方
dic1 = {i: i**2 for i in range(5)}
print(dic1) #{1,1, 2:4, 3:9, 4:16}
# 将两人个列表合并为一个字典
list1 = ['name', 'age', 'gender']
list2 = ['Tom', 20, 'man']
dic2 = {list[i]:list2[i] for i in range(len(list1))}
print(dic2) {'name': 'Tom', 'age': 20, 'gender': 'man'}
集合推导式
变量名 = {表达式 for 变量 in 列表 for 变量 in 列表}
变量名 = {表达式 for 变量 in 列表 if 条件}
# 创建0-4的次方集合
set1 = {i ** 2 for i in ragne(5)}
函数
# 函数中的说明文档
def get_sum(a, b):
"""
计算两个数的和
:param a: 参数1
:param b: 参数2
:return: 参数1和参数2的和
"""
return a + b
变量作用域
局部变量:函数内使用的变量;存储到堆;生命周期与函数或类的生命周期一样,
全局变量:在函数内外都能使用,可以使用global关键字;存储到方法区;生命周期随着.py文件加载而存在,.py文件在内存中移除而消失。
使用变量遵循就近原则,
函数返回多个返回值
- 当返回多个数据的时候,默认是元组类型
- return后面可以连接列表,元组或字典,以返回多个值。
# 返回两个值,默认为元组类型
def reutn_num():
return 1, 2
函数参数
位置参数
位置参数:调用函数时根据函数定义的参数位置来传递参数。传递的参数和定义的参数的顺序及个数必须一致。是对于实参来讲的。
def user_info(name, age, gender):
print(f'您的名字是{name}, 年龄是{age}, 性别是{gender}')
user_info('lisi', 20, '男');
关键字参数
关键字参数:函数调用时通过”键=值”形式传递参数,对于实参来讲的。
作用:可以让函数更加清晰,容易使用,同时也清除了参数的顺序需求。
注意:函数调用时,如果有位置参数时,位置参数必须在关键字参数的前面,但关键字参数之间不存在先后顺序
def user_info(name, age, gender):
print(f'您的名字是{name}, 年龄是{age}, 性别是{gender}')
# 调用时可以不按顺序来
user_info('lisi', gender='男', 23)
缺省参数
缺省参数:缺省参数也叫默认参数,用于定义函数,为参数提供默认值,调用函数时可不传该默认参数的值(注意:所有位置参数必须出现在默认参数前,包括函数定义和调用)
作用:调用函数时没有传递参数,就会使用缺省参数的对应值。
注意:函数调用时,如果为缺省参数传值则修改默认参数值,否则使用这个默认值
def user_info(name, age, gender='男'):
print(f'您的名字是{name}, 年龄是{age}, 性别是{gender}')
# 调
user_info('liSi', age=23)
不定长参数
不定长参数:不定长参数也叫可变参数,用于不确定调用的时候会传递多少个参数(不传参也可以)的场景,
作用:当调用函数时不确定参数个数时,可以使用不定长参数。
不定长参数的类型:位置传递,关键字传递
- *args:传进的所有参数都会被args变更收集,它会根据传进参数的位置合并为一个元组(tuple),args是元组类型,这就是位置传递。应用于实体的个数不确定的情况,就可以把形参定义成可变参数。
- **kwargs:参数是“键=值”形式的情况下,所有的键值都会被 kwargs接受,同时会根据键值组成字典。只能接收所有关键字参数,封装到字典中。
def user_info(*args):
print(args)
def user_info(**kwargs):
print(args)
拆包
拆包:对于函数中的多个返回数据,去掉无组,列表,或者字典,直接获取里面数据的过程。
一个元组中有多个元素,当我们想要获取元组中的每一个元素的时候就可以使用拆包获取。
字典拆包只能拿到key,不能拿到value,因为value是重复的,key是不重复的。
my_tup = (1, 3.14, 'hello') # 组包
num, pi, name = my_tup # 拆包
# 交换两个变量的值
a = 10
b = 20
a,b = b, a
匿名函数
匿名函数:没有名字的函数叫做匿名函数
格式:变量名 = lambda 形参列表: return 返回值
应用场景:当对方法仅调用一次,匿名函数可以做为函数对象进行传递。
函数作为参数,是对功能逻辑的一种封装。
fn_sum = lambda a, b: a +b
n = fn_sum(1, 2) # 3
# 函数作为参数
def custom_fun(a, b, fun):
return fun(a, b)
res1 = custom_fun(1, 2, lambda a, b: a + b)
print(f'result: {res1}')
res2 = custom_fun(1, 2, lambda a, b: a * b)
print(f'result: {res2}')
文件操作
open(name, model):打开一个文件
name:要打开的文件名的字符串具体路径,
model:设置打开文件的模式 (只读,写入,追加)
- 国内主要使用GBK码表,1个中文占2个字节
- 国际通用码表UTF-8,1个中文占3个字节
- 无论是什么码表,英文字母,数字,特殊字符都占1个字节
- 只要出现乱码,说明变是编解码码表不一样
- 如果开头是负数,应该是中文编码,要么以GBK读两个字节来解析,要以3个字节UTF-8来解析。
格式:with open(‘路径’, ’模式’, ‘码表’) as 别名: 语句体
特点:语句体执行结束后,with后边定义的变量,会自动释放
f = open('python.txt', 'rw') # r只能读文本文件, 默认为系统码表
f.read() # 读所有内容
f.read(3) # 读3个字节
f.readline() # 读一行
f.write("你好")
f.writelines("大家好")
with open('demo.txt', 'rb') as src_f, open('write.txt', 'wb') as dest_f:
while True:
data = src_f.read(8192)
if len(data) <= 0:
break
dest_f.write(data)
异常
捕获常规异常
基本语法:
try:
可能发生错误的代码
except:
如果出现异常执行的代码
# 捕获指定异常
try:
可能发生错误的代码
except (NameError, ZeroDivisionErr) as e:
如果出现异常执行的代码
try:
可能发生错误的代码
except Exception as e:
print(e)
异常的else:
try:
可能发生错误的代码
except Exception as e:
print(e)
else:
try中的代码无问题时执行,有问题才跳过。
异常的finally:
try:
可能发生错误的代码
except Exception as e:
print(e)
else:
try中的代码无问题时执行,有问题才跳过。
finally:
无论是否异常都要执行的代码。
异常的传递
- 分享错误处理逻辑与核心逻辑
- 实现集中化错误处理
- 支持灵活的异常处理策略
- 保留完整的错误上下文信息
模块
什么是模块?
python模块(module)是一个python文件,以.py结尾,模块能定义函数,类和变量,模块里也能包含可执行的代码。
模块的作用?
每个模块都可以帮助我们快速实现一些功能,对功能的封装,模块就是一个工具包。
学习模块就是记忆一些.py文件及其中的一些函数。如random模块,time模块,os模块
导入模块的方式
- import 模块名 后续通过模块名.函数名() 方式调用,模块下所有函数均可使用
- import 模块名 as 别名 后续通过别名.函数名() 方式调用,模块下所有函数均可使用
- from 模块名 import 函数名 后续通过函数名()的方式调用,只能使用该模块导入的函数
- from 模块名 import 函数名 as 别名 后续通过别名()的方式调用,只能使用该模块导入的函数
- from 模块名 import * 后续通过函数()的方式调用,模块下所有函数都可以使用
自定义模块
每个python文件都可以作为一个模块,模块的名字就是文件的名字,也就是说自定义模块名必须要符合标识符命名规则。
# __name__ 属性,可以解决模块自测的问题,当前模块中打印结果是__main__,在调用者模块中打印的是当前的模块名。
if __name__ == '__main__':
如果为true,说明在当前模块中执行的
# __all
当导入多个模块时,且模块内有同名功能,当调用这个同名功能的时候,调用到的是最后面导入的模块的功能。
# __all__ 属性,只对针对于from 模块名 import *这种写法有效,它只会导入__all__记录的内容。
# 模块文件 只爆露指定的函数
__all__ = ['fun1', 'fun2']
包
什么是python的包?
从物理上看,就是一个文件夹,包含了一个__init__.py
文件,该文件夹用于包含多个模块文件,从逻辑上看,包的本质依然是模块。
包的作用:管理模块,包含多个模块,但也是模块。
导包的方式:
1. improt 包.模块名
2 . from 包名 import * 但必须在__init__.py
文件中添加__all__=[]
控制允许导入的模块列表。如果__init__.py
中的all属性不写的话,无法导入;模块中的all不写是导所有。
3 . from 模块名 import 目标
os模块
全称叫: operation system, 系统模块,主要是操作文件夹,文件,路经,
常用函数:
- getcmd():获取当前工作空间目录,current work directory
- chdir():改变工作空间 change directory
- rmdir():删除文件夹,必须是空文件夹
- mkdir():创建文件夹,make directory
- rename():改名,文件名或文件夹名
面向对象
面向对象的三大特征:封装,继承,多态
封装:把属性和方法封装在一起,仅提供对外的方法让别人访问,好处:简化编程
继承:子类复用父类的功能,好处:代码复用
多态:同样一个函数在不同场景下表现出不同形态,好处:解耦合,可扩展
格式:
class 类名(父类名):
pass
对象名 = 类名()
类外属性操作:
设置属性:对象名.属性 = 属性值
获取属性:对象名.属性
类内属性操作:
self.属性名=属性值
# 格式1
class Car:
def run(self): # self代表当前本类对象的引用
print("汽车会跑")
# 格式2
class Car():
def run(self): # self代表当前本类对象的引用
print("汽车会跑")
# 格式3
class Car(object): # 所有类的父类,所有有类直接或间接继承自objecst
def run(self): # self代表当前本类对象的引用
print("汽车会跑")
def work(self):
self.run()
if __name__ == "__main__":
c1 = Car()
c1.run()
魔法方法
概念:在python中,有一些可以给python类增加魔力的特殊方法,它们总是被双下划线所包围,我们称之为魔法方法,在特殊情况下会被自动调用,不需要开发者手动调用。格式为:__魔法方法名__()
__init__()方法
在python中,当新创建一个对象时,则会自动触发__init__()
魔法方法,无参不需要外面传参数,有参则需要外面传参。可用于初始对象的属性值。
__str__()方法
用于快速打印对象的各个属性值的,在输出语句打印对象的时候会被自动调用 print(c1)
__del__()方法
当删除对象的时候调用,或者main函数执行完毕后,会自动调用,常用于释放资源。
class Car:
def __init__(self, color, number):
self.color = color
self.number = number
def __str__(self):
return f"The Car Color is {self.color}, that number is {self.number}"
def __del__(self):
print("The car object is del.")
继承
面向对象中的继承:指子类继承父类的属性和方法,是的类的继承,在Python中所有类默认继承object类,object类是顶级类或基类,其他子类叫做派生类。
继承可以提升代码的复用性。
单继承:一个子类只能继承一个父类,不能继承多个类。
class Father(object):
def __init__(self):
self.gender = "男"
class Son(Father):
def sayGender(self):
print(f"My Son gender is {self.gender}")
多继承:一个类同时继承了多个父类,并且同时具有所有父类的属性和方法。如果有相同属性和方法时,优先继承第一个父类的同名属性和方法。
当一个类有多个父类时,默认使用第一个父类的同名属性和方法,可以使用类名.__mro__属性或类名.mro()方法查看调用的先后顺序。
class Father(object):
def __init__(self):
self.gender = "男"
class Mather(object):
def __init__(self):
self.gender = "女"
def make_cook(self):
print("做饭")
class Son(Father, Mather):
def sayGender(self):
print(f"My Son gender is {self.gender}")
重写
重写也叫作覆盖,就是当子类属性或方法与父类的属性或方法名字相同时,从父类继承下来的成员可以重新定义,优先调用子类的属性和方法
子类调用父类的方法:父类名.父类方法(self),super().父类方法名(),多继承不建议使用super
class Son(object):
def do_soming(self):
Father.__init__(self)
Father.do_soming(self)
封装
私有属性与方法
在python中,可以为属性和方法设置为私有权限,即设置某个属性或方法不继承给子类,设置私有属性与方法的方法:在属性或方法名前加上__,格式:__属性名,def __方法名(),私有属性与方法,只能在类的内部使用,不能在类的外部使用。
class PrivateClass(object):
def __init__(self, title):
self.__title = title
def say_upper_title(self):
print(f"Say Upper Title {self.__trans_to_upper()}")
def __trans_to_upper(self):
return self.__title.upper()
多态
多态,指的是:多种状态,比如同一个函数在不同场景下有不同的状态。python中的多态是伪多态。通过多态语法轻松的实现模块和模块之间的解耦合,实现了软件系统的可拓展。
实现多态有三个条件:
- 有继承(定义父类,宝义子类,子类继承父类)
- 函数重写(子类重写父类的函数)
- 父类引用指向子类对象(子类对象传递给父类对象调用者)
class Animal(object):
def speak(self):
pass
class Dog(Animal):
def speak(self):
print("Dog speak")
class Cat(Animal):
def speak(self):
print("Cat speak")
def animal_speak(animal:Animal):
animal.speak()
if __name__ == '__main__':
dog = Dog()
cat = Cat()
animal_speak(dog)
animal_speak(cat)
抽象类(接口)
方法中没有具体的实现,只有一个pass关键的方法称为抽象方法,有抽象方法的类叫做抽象类或接口,设计的含义:父类用来确定有那些方法(父类制定接口标准),具体的方法实现有子类来实现(子类实现接口标准)
class Person(object):
def say_gender():
pass
class Man(Person):
def say_gender():
print("Gender is Man")
class Woman(Person):
def say_gender():
print("Gender is Woman")
其它属性
类属性:指的就是类所拥有的属性,它被共享于整个类中(都可以直接调用),调用格式:类名.类属性名,对象名.类属性名
对象属性:属于每个对象的属性,调用格式:self.属性名,对象名.属性名
如果一个变更是被该类下所有的对象所共享的,就要考虑定义为类变量。
class Person(object):
count = 1
if __name__ == '__main__':
Person.count = 2
类方法:就是类所有拥有的方法,并需要使用装饰火龙@classmethod来标识其为类方法,对于类方法的第一个参数必须是类对象,通过以cls作为第一个参数名。调用格式为:类名.类方法
class Book(object):
@classmethod
def say_title(cls):
print("Book Title")
if __name__ == '__main__':
Book.say_title()
静态方法:需要通过装饰器@staticmethod来标识其为静态方法,且静态方法不需要多定义参数。调用方法为:类名.静态方法名()
class Book(object):
@staticmethod
def say_author():
print("Book author")
if __name__ == '__main__':
Book.say_author()
类方法与静态方法的区别:是否需要使用该类的对象,如果使用则定义类方法,不需要定义成静态方法,如果非要定义成静态方法,则可以使用类名.类属性调用类属性与类方法
闭包
闭包的作用:闭包可以保存函数内的变量,而不会随着调用函数而被销毁。
闭包的定义:在函数嵌套的前提下,内部函数使用外部函数的变量,并且外部函数返回了内部函数,这种使用外部函数变量的内部函数称为闭包。
# 外部函数
def 外部函数名(外部参数):
# 内部函数
def 内部函数名(内部参数):
# 使用外部函数的变量
return 内部函数名 # 闭包
闭包构成的条件:
- 有嵌套:在函数嵌套(函数里再定义函数)的前提下
- 有引用:内部函数使用了外部函数的变量(包括外部函数的参数)
- 有返回:外部函数返回了内部函数名。
def op_fn(n1: int, op: str):
def add(n2: int):
return n1 + n2
def sub(n2: int):
return n1 - n2
if "+" == op:
return add
elif "-" == op:
return sub
return None
if __name__ == '__main__':
res = op_fn(10, "+")(20)
print(f"close fn result: {res}")
闭包关键字:
global:全局变量
nonlocal:声明能够让内部函数去修改外部函数的变量
def fn_outer(op:str):
num = 10
def add_fn(n1):
nonlocal num
num += n1
return num
def sub_fn(n1):
nonlocal num
num -= n1
return num
if "+" == op:
return add_fn
elif "-" == op:
return sub_fn
else:
return None
if __name__ == '__main__':
res = fn_outer("+")(10)
print(f"fn outer res: {res}") # 20
res = fn_outer("-")(20)
print(f"fn outer res: {res}") # -10
op_fn = fn_outer("+")
res = op_fn(10)
print(f"fn outer res: {res}") # 20
res = op_fn(10)
print(f"fn outer res: {res}") # 30
装饰器
语法糖:就是语法简化的写法
装饰器:在不改函数的基础上,给原有函数增加额外的功能 ,装饰器本质上就是一个闭包函数。内部函数的形式,必须和原函数(要被装饰的函数)形式一致,即要有参数都有参,要有返回值就都有返回值。
装饰器构成的条件:
- 有嵌套:在函数嵌套(函数里再定义函数)的前提下
- 有引用:内部函数使用了外部函数的变量(包括外部函数的参数)
- 有返回:外部函数返回了内部函数名。
- 有客外的功能:给需求装饰的原有函数增加额外功能
装饰器语法:
# 传统方法
变量名 = 装饰器名(原有函数)
# 语法糖
变量名 = @装饰器 (加上函数上面)
# 调用
变量名()
# 无参无返回
def check_login(fn_name):
def inner():
print("登录中...")
print("登录成功...")
fn_name()
return inner
@check_login
def comment():
print("发表评论")
if __name__ == '__main__':
# 传统方式调用
# check_login(comment)
# 语法糖方式调用
comment()
# 有参有返回
def fn_before(fn):
def inner(n1, n2):
if isinstance(n1, int) and isinstance(n2, int):
return fn(n1, n2)
else:
return None
return inner
@fn_before
def fn(n1, n2):
return n1 + n2
if __name__ == '__main__':
res = fn(1, 2)
print(f"res: {res}") # res: 3
res = fn(1, 'a')
print(f"res: {res}") # res: None
# 多个装饰器装饰一个函数,按顺序执行装饰器,最后执行离函数最近的装饰器
有参数的装饰器
def op_decorate(flag):
def decorate(fn_name):
def inner_add(n1, n2):
fn_name(n1, n2)
return n1 + n2
def inner_sub(n1, n2):
fn_name(n1, n2)
return n1 - n2
if "+" == flag:
return inner_add
elif "-" == flag:
return inner_sub
else:
return fn_name
return decorate
@op_decorate("+")
def op_num(n1, n2):
return 0
if __name__ == '__main__':
res = op_num(10, 20)
print(f"res: {res}") # res: 30
多进程
子进程对象 = multiprocessing.Process(group=None, targe=None, name=None, args=(), kwargs = {})
- group:参数未使用,值始终为None
- target+表示调用对象,子进程要执行的任务
- args:表示以元组的形式向子任务函数传参,元组传参一定要和参数列表顺序保持一致
- kwargs:表示以字典的方式给子任务函数传参,字典方式传参字典中的key要和参数名保持一致.
- name:子进程的名称
多线程
import threading
import time
def coding(name):
var = threading.current_thread().name
while True:
print(f"{var} --> {name} coding....\n")
time.sleep(1)
def music(name):
var = threading.current_thread().name
while True:
print(f"{var} --> {name} music.....\n")
time.sleep(1)
if __name__ == '__main__':
t1 = threading.Thread(target=coding, name='Coding', args=("xx",))
t2 = threading.Thread(target=music, name='Music', kwargs={"name": "LiSi"})
t1.start()
t2.start()
锁
num = 0
mutex = threading.Lock()
def set_num_one():
mutex.acquire()
global num
for i in range(100):
num += 1
mutex.release()
print(f'set_num_one函数,累加后的结果为:{num}')
def set_num_tow():
mutex.acquire()
global num
for i in range(100):
num += 1
mutex.release()
print(f'set_num_two函数,累加后的结果为:{num}')
if __name__ == '__main__':
t1 = threading.Thread(target=set_num_one, name='set_num_one')
t2 = threading.Thread(target=set_num_tow, name='set_num_two')
t1.start()
t2.start()
print("main is over...")
上下文管理器
一个类只要实现了__enter__()和__exit__()这两个方法,通过该类创建的对象我们称之为上下文管理器。with 语法功能底层用到的就是上下文管理器。其中__enter__()会在with语句之前执行,常用于初始化对象,__exit__() 会在with语句后执行,一般用于释放资源。
class My_File(object):
def __init__(self, file_name, file_model):
self.file_name = file_name
self.file_model = file_model
self.file_obj = None
def __enter__(self):
self.file_obj = open(self.file_name, self.file_model, encoding="utf-8")
return self.file_obj
def __exit__(self, exc_type, exc_val, exc_tb):
if self.file_obj:
self.file_obj.close()
print("文件释放")
if __name__ == '__main__':
with My_File("./main.py", "r") as f:
line = f.readline()
print(f"文件内容:{line}")
生成器
什么是生成器?
根据程序员制定的规则循环生成数据,当条件不成立时则生成数据结束。数据不是一次生全部生成出来,而是使用一个,再生成一个,可以节约大量的内存。如果生成器中没有数据的话,会报错。
创建生成器的方式: 生成器推导式,yield关键字(可以临时存有所有数据,并放到生成器中,调用函数时会返回 一个生成器对象)
yield关键字的作用:创建生成器,把值放到生成器中,返回生成器。
使用生成器的方式:next函数,遍历生成器即可
# 生成器推导式
gen = (i for i in range(5))
print(next(gen))
print("-" * 21)
for i in gen:
print(i)
# yield生成器
def gen():
for i in range(5):
yield i
fn_gen = gen()
print(next(fn_gen)) # 0
print(next(fn_gen)) # 1
@Property
它是用来修饰函数的,目的是:简化代码开发
格式:
- property充当装饰器的用法
- @property 修饰是的获取值的方法
- @property.setter 修饰的是设置值的方法 ,@propert修饰的方法 名
- property充当类变量
- 类变量名 =property(获取值的方法,设置值的方法 )
# 充当装饰器
class Student(object):
def __init__(self):
self.__name = ''
@property
def name(self):
return self.__name
@name.setter
def name(self, new_name):
self.__name = new_name
if __name__ == '__main__':
s = Student()
s.name = "四经"
print(f"Student name: {s.name}")
# 充当类变量
class Teacher(object):
def __init__(self):
self.__name = ''
def get_name(self):
return self.__name
def set_name(self, name):
self.__name = name
name = property(get_name, set_name)
if __name__ == '__main__':
s = Teacher()
s.name = "教师"
print(f"Teacher name: {s.name}")