第九节/第十节
三元运算【三目运算】
- 语法:
- "v = a if a >b else b" #自我总结:当条件满足时返回a,条件不满足时返回b
函数
1.函数基础
1.1函数基础结构
def 函数名(参数):
#函数内容
pass
函数名(参数) # 执行函数
1.2返回值
- return值,函数默认return None
def func():
reuturn 1,3,"abc" #这种情况会自动转换为元组返回
1.3函数参数
- 函数的参数传递是什么?【内存地址=引用】
- 任意个数
- 任意类型
- 位置传参
def func(name,age,gender):
pass
func("伊万科夫",25,"人妖")
- 关键字传参
& 关键字与位置混合传参的情况,位置参数一定在前,关键字参数在后 - 参数默认值【定义】
& 如果给默认值为可变类型---》坑
#该部分代码解释了为什么默认值慎用可变类型
def func(data,value=[]):
value.append(data)
return value
v1=func(1) #[1,]
v2=func(1,[11,22,33]) # [11,22,33,1]
v3=func(2) # [1,2]
print(v1) #[1,2]
def func(name,age,gender='男'):
pass
func("伊万科夫",25,gender="人妖")
func("伊万科夫",gender="人妖",25) # 错误方式
func("伊万科夫",25) # gender不传的情况下使用默认值 “男”
- 万能参数
-
*args 接收任意个数的位置参数
& 可以接收任意个数的参数,并且将所有参数转换成一个元组def func(*args): # 将所有参数打包成元组传递 print(args) v1 = func((11,22,33,44,55)) #将参数元祖作为整个元组的第一个参数 print(v1) # ((11,22,33,44,55),) v2 = func(*(11,22,33,44,55))# 将元组元素打散再打包成元组传递 print(v1) # (11,22,33,44,55) #********************************************************** def func(*args,**kwargs): print(args) print(kwargs) func(*(11,"aaa"),444,"abc",name="沙鳄鱼",age='30') """ (11, 'aaa', 444, 'abc') {'name': '沙鳄鱼', 'age': '30'} """
-
**kwargs 接收任意个数的关键字参数
& 接收关键字参数,按键值转换成字典def func(**kwargs): print(kwargs) func(k1="v1",k2="v2") #转换字典{"k1":"v1","k2":"v2"} func(**{"k1":"v1","k2":"v2"}) #直接传递字典{"k1":"v1","k2":"v2"} #********************************************************** def func(*args,**kwargs): print(args) print(kwargs) func((11,"aaa"),444,"abc",name="沙鳄鱼",age='30') """ ((11, 'aaa'), 444, 'abc') {'name': '沙鳄鱼', 'age': '30'} """
-
1.4 函数作用域
- 全局作用域
- 局部作用域
- 总结:
- 一个函数一个作用域
- 作用域中查找数据规则:现在自己的作用域内部查找,找不到在沿父级查找
- 子作用域只能使用父级变量的值,不能重新给其父级的变量赋值 【给变量重新赋值相当于在子作用域给自己定义了新的变量】
- 对于可变类型变量,子作用域可对其进行修改
- 如果需要给全局中的变量赋值,需要使用global关键字找到全局变量
name = 'enki'
def func():
global name # global 关键字 只找全局的变量 【global关键字只查找全局中的变量】
name = 'alex'
- 查找父级【上一级】的变量
# 使用关键noglobal关键字
- 变量命名规范
- 全局变量全大写
- 局部变量全小写
第11节/第12节
1.函数的小高级
1.1 函数的赋值
- 函数名赋值
def func():
pass
v1 = func
v1()
- 函数可以放到list,dict,set,tuple,也可以作为字典的键和值
- 函数名可以当做变量名使用
- 函数可以当做参数传递
def func(arg):
print(arg)
def show():
return 9
func(show)
def func(arg):
arg() #执行函数
def show():
print("执行show函数")
func(show)
1.2lambda表达式
- 基本写法
& 用来表示简单的函数,【函数内部没有复杂代码,只有简单返回值情况】
def func(a,b):
return a + b
func1=lambda a,b:a+b
func2=lambda : 100
func3=lambda a: a+100
func4=lambda *args,**kwargs: len(args)
#默认会将":"后的结果作为返回
lambda表达式不能定义变量,自己查找变量,没有则向父级查找.[lambda表达式就是一个一行的函数]
#一行实现比较两个值大小,返回大的值
func = lambda a,b: a if a > b else b
n = func(33,5)
print(n)
1.3内置函数
- 自定义函数
- 内置函数
-
强制类型转换 【int,str,bool,list,tuple,dict,set】
-
数值相关 【max(),min(),float(),abs():求绝对值,sum()】
- divmod():让两个值相除,得到商和余数 【分页用到】
- round():转化保留几位销售,四舍五入
-
输入输出【print,input】
-
进制相关
- bin 二进制转换,0b开头
- oct 八进制 0o开头
- int 十进制
- hex 十六进制 0x开头
# 二进制转十进制 v1 = '0b1101' result = int(v1,base=2) print(result) # 八进制转十进制 v1 = '0o1101' result = int(v1,base=8) print(result) # 十六进制转十进制 v1 = '0x1101' result = int(v1,base=16 ) print(result)
-
其他 【type,len,range,open,id】
-
编码相关
- chr() # 根据十进制数字在Unicode编码中找到对应字符
- ord() # 根据字符在Unicode编码中找到对应的十进制数字
- 应用:随机验证码的生成【引入random模块 random.randint(10,50)随机返回数字】
-
高级内置函数
- map(func,v1) [处理数据]
& func为一个函数,V1为一个可迭代类型数据,map()函数通过循环V1参数的每个元素,让每个元素执行函数func,将func函数执行的结果添加到一个新列表中返回。
v1 = [11,22,33,44] result = map(lambda x: x+100,v1) print(list(result)) # 特殊 ,result是一个object对象
- filter(func,v1) [过滤数据]
& 循环v1参数中的每个元素并交给func函数执行,如果func函数返回为True,将该元素追加到一个新列表中。 - reduce(func,v1) [整合数据]
& 循环v1参数的中的每个元素交给func函数执行,将func函数最终执行的结果返回;【func函数需要两个参数,第一个参数为函数前一次执行的返回值】
& python3需要导入模块 import functools
v1 = [1,2,3,4,5] result = reduce(lambda x,y: x+y,v1) print(result)
- map(func,v1) [处理数据]
-
2.函数中高级
2.1 函数做返回值
- 闭包
- 为函数创建一块内存空间维护自己的数据(内部变量供自己使用),方便后面函数执行调用【应用场景:装饰器/SQL Alchemy源码】
- 函数是由谁创建的,函数就从哪儿开始执行
- 闭包作用:每次调用函数时,都会为此调用开辟一块内存,内存可以保存自己以后想用的值
- 把函数当做参数传递
- 把函数当做返回值
- 注意:对函数进行赋值
- 执行函数
- 函数不被调用,内部代码永远不会执行
- 执行函数时,会创建一块内存保存自己函数执行的信息【闭包】
# 函数开辟的内存中未使用name,不是闭包
2.2 递归
- 递归默认最大次数为1000,可通过sys模块中的方法调整;效率较低
def func(a):
if a ==5:
return 100000
result = func(a+1) + 10
return result
v = func(1) # 100050
2.3 加密模块
- hashlib模块
import hashlib
def get_md5(data):
obj = hashlib.md5("一套随机字符串",encode='utf-8')
obj.update(data.encode('utf-8')) #python3需要加编码指定
result = obj.hexdigest()
return result
- 密码不不显示,模块 getpass
import getpass
pwd = getpass.getpass('请输入密码:') #密码隐藏不显示
#在终端输入运行(pycharm无法运行不行)
# getpass 在pycharm终端无法直接运行,如果需要请在命令行或者下方terminal窗口输入py文件运行
第十三节/第十四节
1.装饰器
- 作用:在不改变原函数内部代码的基础上,在函数执行的前后自动执行某个功能
- 编写装饰器:
- @x的作用:
& 1.执行x函数,把下面func1函数作为x函数的参数传递。
& 2.将x函数执行的返回值赋值给下面的func1函数名
- @x的作用:
#装饰器的编写
def x(func):
def y():
ret = func()
return ret
return y
#装饰器的应用
@x
def func1():
pass
@x
def func2():
pass
- 应用场景: 为某个或者某些函数做公共功能扩展时使用。
- 装饰器格式:
def 外层函数(参数):
def 内层函数(*args,**kwargs):#注意万能参数传递
return 参数(*args,**kwargs)#注意万能参数传递
return 内层函数
@外层函数
def index():
pass
index()
2.推导式
- 列表推导式
- 基本格式:变量=[for循环的变量;for循环一个可迭代对象]
vals = [ i for i in 'alex' ]
v1 = [i+100 for i in range(10)]
v2 = [100 for i in range(10)]
v3 = [99 if i >5 else 66 for i in range(10)]
i = [lambda:100+i for i in range(10)]
v4[0]() #109
v = [i for i in range(10) if i > 5]
# 条件成立才append进去
- 集合推导式
& v1 = {i for i in 'alex'} # 区别在于集合去重 - 字典推导式
& v1 = {'k'+str(i):i for i in range(10)}
3.带参数的装饰器
# 写一个带参数的装饰器,实现:参数是多少,被装饰的函数就要执行多少次。把每次结果添加到列表中返回
import random
def x(num):
def wrapper(func):
def inner(*args,**kwargs):
results = []
for i in range(num):
value = func(*args,**kwargs)
if value > num:
results.append(value)
return results
return inner
return wrapper
@x(5)
def index():
return random.randint(0,10)
r = index()
print(r)
4.模块
4.1 sys模块 【python解释器相关的数据】
- \n 换行
- \t 制表
- \r 回到当前行的起始位置
##进度条
for i in range(1,101):
msg = "%s%%\r" %i
print(msg,end='')
- 转义
- 字符串前面加字母r,对字符串内容中的特殊字符进行去伪,比如\n不再有它换行的意义。
s = r""D:\code\s21day14\n1.mp4"
- sys.argv常用;【获取用户执行脚本时,传入的参数】
& 获取执行脚本的参数以列表方式存储,默认第0个参数为执行脚本的全路径名
print(arg)
path = sys.argv[1]
print("删除",path)
- sys.exit(0) ; 终止程序
4.2 shutil模块 【删除目录/文件】
import shutil
# 删除目录
ret = shutil.rmtree("")
# 重命名
shutil.move("原文件名","新文件名")
#压缩文件
shutil.make_archive("压缩后的文件名称","压缩成什么格式","需要压缩的目录")
#解压文件
shutil.unpack_archive("需要解压的文件名",extract_dir="解压到哪个目录",format="解压格式")
4.3 os模块 【和操作系统相关的数据】
- os.path.exists(path) # 如果path路径存在返回True
- os.path.abspath() # 获取文件的绝对路径
- os.path.dirname(file) # 获取文件的上级目录
- os.path.join(path,file) # 拼接路径
- os.stas(file).st_size # 获取文件的大小
- os.listdir(path) # 列出一个目录下的所有文件【不包括子目录,第一层】
- os.walk() #列出一个目录(包括)子目录下的所有文件【递归方式】
#查看一个目录下所有的文件
import os
listdir = os.listdir("D:\wuhailuo\python_projects\code\python_jichu\模块作业")
# print(listdir)
# 查询显示指定目录下的所有文件,包括子目录下的所有文件
list_file = os.walk("D:\wuhailuo\python_projects\code\python_jichu\模块作业") #得到一个生成器对象,只有当对其循环是给出结果
for a,b,c in list_file: # a:正在查看的目录,b:此目录下的文件夹,c:此目录下的文件
for filename in c:
print(os.path.join(a,filename))
15课/16课 :模块知识
补充知识点
- range函数:python2/3区别:
- python2:
- range(10): 在内存中立即将序列值创建
- xrang(10): 不会在内存中立即创建,只有当在循环时,边循环边创建
- python3:
- range(10) = p2中的xrang(10)
- python2:
1、模块基础知识
1.1 自定义模块
1.1.1 定义模块
- 定义模块可以把一个py文件或一个文件夹(包)当做一个模块,以便于以后其他py文件的调用。
- 对于包的定义:【python2/3的区别】
py2: 文件夹中必须有 __init__.py
py3:不需要 __init__.py 【推荐写代码时,加上此文件】
1.1.2 模块调用
- import 模块 模块.函数()
- form 模块 import 函数 函数()
- form 模块 import 函数 as 别名 别名()
总结
- 模块和要执行的文件在同一目录且需要模块中的很多功能时,推荐使用import导入模块
- 其他推荐:from 模块 import 模块 模块.函数()
- 其他推荐:from 模块.模块 import 函数 函数()
1.1.3 补充
-
import
- import 模块1 模块1.函数()
- import 模块1.模块2.模块3 模块1.模块2.模块3.函数()
- 特殊: import 文件夹 内部加载 init.py
-
from xxx import xxx
- 特殊:from src import xxx 【内部加载src文件夹的__init__.py】
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# 导入模块,加载此模块中所有的值到内存
import os
# 导入模块中某个函数功能
from lizhongwei import func,show
from lizhongwei import * #导入这个模块的所有功能
from lizhongwei import func as f # 避免函数重复覆盖,取别名
1.2 内置模块
1.2.1 os 模块 import os
- os.mkdir("") 在当前运行脚本的目录创建一个目录(只能生成一级)
- os.makedirs(r"dd\xx\aa") 递归创建目录
- os.rename("") 重命名
1.2.2 sys 模块 import sys
- sys.path 默认Python去导入模块时,按照这个这个值的路径去查找,python文件执行时会将当前文件的路径加载进sys.path里面
import sys
### 给Python添加查找模块的路径
sys.path.append('D:\\ ')
1.2.3 json模块 【常用】
- json是一个特殊的字符串。【长的像列表、字符串、字典、数字】
- json中内部包含的字符串必须要用双引号
- json字符串最外层必须是一个容器【列表/字典】
- 元组序列化后成列表,集合不能序列化
- json格式数据的序列化/反序列化
- 序列化:将python的值转换成json格式字符串 json.dumps()
- 反序列化:将json格式字符串 转换Python的数据类型 json.loads()
- 字典或列表中有中文,序列化要保留中文显示 【ensure_ascii=False】
# 保留中文显示
val = json.dumps(v,ensure_ascii=False)
v = [12,3,4,{'k1':'v1'},True,'asdf']
import json
# 序列化,将python的值转换为json格式的字符串
v1 = json.dumps(v)
s = '["alex",123]'
#反序列化,将json格式的字符串转换为python的数据类型
s1 = json.loads(s)
- json支持python的数据类型
+-------------------+---------------+
| Python | JSON |
+===================+===============+
| dict | object |
+-------------------+---------------+
| list, tuple | array |
+-------------------+---------------+
| str | string |
+-------------------+---------------+
| int, float | number |
+-------------------+---------------+
| True | true |
+-------------------+---------------+
| False | false |
+-------------------+---------------+
| None | null |
+-------------------+---------------+
1.2.4 pickle模块 【与json模块类似】
- json 优点:所有语言通用; 缺点:只能序列化基本的数据类型(字符串,列表,字典,数字)
- pickle 优点:python中所有的东西都能被他序列化(socket对象); 缺点:序列化的内容只有python能认识。
- pickle.dumps(v) 序列化直接打印是二进制内容,通过pickle.loads(val)处理可正常显示。 【示例下面代码】
- 字节类型pickle序列化后是一个字节类型 比如 b'xxxx' 【示例下面代码】
v = {1,2,3,4,"abc"}
val = pickle.dumps(v)
print(val) # b'\x80\x03cbuiltins\nset\nq\x00]q\x01(K\x01K\x02K\x03K\x04X\x03\x00\x00\x00abcq\x02e\x85q\x03Rq\x04.'
******************************
file_obj = open("x.txt",mode='wb')
data = "abc".encode("utf-8")
print(data,type(data)) # b'abc' <class 'bytes'>
file_obj.write(data)
file_obj.close()
1.2.5 time&datetime时间模块
- UTC/GMT:世界时间
- 本地时间:本地时区的时间
- time模块【获取时间戳】
- time.time() :时间戳:1970-1-1 00:00 【随机值可以用到】
- time.sleep(10) 休眠时间/等待秒数
- time.timezone 时区
- datetime模块
from datetime import datetime,timezone,timedelta
vl = datetime.now() #当前本地时间
v2 = datetime.utcnow() # 当前UTC时间
tz = timezone(timedelta(hours=7)) # 当前东7区时间
v3 = datetime.now(tz)
- datetime时间格式转换
from datetime import datetime,timezone,timedelta
v1 = datetime.now()
# datetime时间格式转换字符串
v1.strftime('%Y-%m-%d %H-%M-%S')
#
v2 = datetime.strptime('2020-03-22','%Y-%m-%d')
- datetime与时间戳的关系
ctime =time.time()
v1 = datetime.fromtimestamp(ctime) # 时间戳转datetime
v2 = datetime.now()
v2.timestamp() #datetime转时间戳
1.3 第三方模块【下载/安装/使用】
1.3.1 前提安装pip包管理工具 ,通过pip安装第三方模块
- 先需要安装pip,然后通过pip下载安装需要的第三方模块 https://pypi.org
- 默认在python的安装目录 \Lib\site-packages
# pip.exe所在目录添加到环境变量中
pip install 需要安装的模块名称
- 常用第三方模块 [requests,xlrd]
1.3.2 源码安装第三方模块
- 下载源码文件:压缩文件
- 解压文件并通过命令进入此目录
- 执行 python3 setup.py(模块安装文件名) build 【编译检查】
- 执行 python3 setup.py(模块安装文件名) install 【安装】
1.4 自定义模块
1.4.1 步骤
- 创建xxx.py文件
def func1():
pass
def func2():
pass
- 导入自定义模块并调用功能
import xxx
xxx.func1()
xxx.func2()
2、异常处理
- 基本语法
try:
程序处理
except exception as e:
print("异常处理")
- try包含的代码执行报错,会直接捕获异常,try块内代码将不再继续执行。所以在循环内部try和try包裹循环,执行结果是不一样的。
17节课/18节课
1、迭代器
- 迭代器:对可迭代对象中的元素进行逐一获取,且存在__next__方法。
- 可迭代对象:可被for循环或内部有__iter__方法且返回一个迭代器。
# 列表转换成迭代器的两种方式:
v = [1,2,3,4]
#方式一
v1 = iter(v)
#方式二
v2 = v.__iter__()
# 迭代器逐一获取元素,反复调用__next__()方法
val = v1.__next__()
2、生成器
2.1 生成器
- 生成器:
& 函数内部具有yield关键字即为生成器函数
& 生成器函数不在函数调用时调用,调用函数会返回一个生成器,只有当生成器在被for循环时生成器函数内部代码才会执行,
每次for循环都会获取yield返回的值
def func():
yield 1
print("f1")
yield 2
print("f2")
yield 3
print("f3")
v = func()
# item只拿函数中yield的值
for item in v:
print(item)
#输出结果:
# 1
# f1
# 2
# f2
# 3
# f3
- 可迭代对象:被for循环且此类对象都拥有iter方法,且返回一个迭代器(也可以是生成器)
- 生成器:可被for循环且拥有__iter__方法,同时也拥有__next__()方法,所以生成器也可以称为特殊的迭代器,或者特殊的可迭代对象
- 可以通过div(函数对象)来查看函数对象拥有的方法
- 生成器经典示例,【模拟redis分批读取数据】
#通过生成器读取大数据文件 [模拟redis数据读取]
import time
"""生成所需数据
with open("data.txt",mode='a+',encoding='utf-8') as fileobject:
for i in range(1,100):
fileobject.write("你领取到的号牌是:"+str(i)+"\n")
"""
"""生成器函数"""
"""分批去读取文件中的内容,将文件的内容返回给调用者"""
def func():
index=0
while True:
time.sleep(2)
with open("data.txt",mode='r',encoding='utf-8') as fileobject: #连接上redis
li = []
fileobject.seek(index)
for i in range(10):
line = fileobject.readline().strip()
if not line:
break
li.append(line)
index=fileobject.tell()
# fileobject.close()
for i in li:
yield i
v=func()
for l in v:
print(l)
2.2 生成器推导式
- 列表推导式和生成器推导式的区别
#列表推导式
v1 = [i for i in range(10)]
#生成器推导式
v2 = (i for i in range(10))
- 列表推导式立刻执行,返回for循环0~9的一个列表。
- 生成器推导式返回的v2是一个生成器,内部for循环没有立刻执行,只有当后面存在for循环调用v2进行循环时,内部for循环才会执行,返回0~9元素
v1 = [lambda : i for i in range(10)] # 列表推导式
v1 = (lambda : i for i in range(10)) # 生成器推导式
# 两者区别
# 列表推导式
def func():
result = []
for i in range(10):
def f():
return i
result.append(f)
return result
v = func()
for item in v:
print(item()) # 9*9
#上面函数与下面推导式相等
v1 = [lambda : i for i in range(10)]
for item in v1:
print(item())
#########################################
# 生成器推导式,
def func():
for i in range(10):
def f():
return i
yield f
v = func()
for item in v:
print(item()) # 0~9
# 上面函数与下面推导式相等
v2 = (lambda : i for i in range(10))
for item in v2:
print(item)
2.3 yield from
- yield from 后面的值需要返回一个生成器,【比如下面test()函数中的返回值不能是return】
- 详见代码
def test():
yield 1
yield 2
yield 3
def func():
yield "alex"
yield "enki"
yield from test()
v = func()
for item in v:
print(item)
# 执行结果
"alex"
"enki"
1
2
3
3、前面知识的补充
py2/py3的区别补充
- str字符串类型和编码相关
- py3中,str字符串类型 【一般用于内存中做数据操作,存储编码为unicode】
- py3中,bytes字节类型 【一般用于网络传输和数据存储,具体编码有执行py文件的文件头编码类型决定】
- py2中的unicode类型 ---> 为py3中的str类型
- py2中的 str类型 ----> 为py3中的bytes类型
- 字典中返回值的不同
- items
- py2 返回的列表
- py3 迭代器 【不能通过索引取值】
- values
- py2 返回的列表
- py3 迭代器 【不能通过索引取值】
- keys
- py2 返回的列表
- py3 迭代器 【不能通过索引取值】
- 同理 map/filter 也一样
- items
其他知识补充
- 导入模块
- import 模块
- from 模块.模块 import 模块
- from 模块.模块.模块 import 模块
- 相对导入 【模块必须有父级目录,不能再根目录下进行该操作】
- from .. import 模块
- from . import 模块
- 注意:文件和文件夹的命名不能是导入的模块名称相同,否则就会直接在当前目录中查找。
- 主文件【主函数】 (运行的py文件)
- 通过 属性 name 来区分,属性__name__的值为
__main__
,表示为主文件
- 通过 属性 name 来区分,属性__name__的值为
#判断是否为主文件,如果是主文件则执行
if __name__ == '__main__':
run() #执行入口