/**
* @file
* @author jUicE_g2R(qq:3406291309)————彬(bin-必应)
* 一个某双流一大学通信与信息专业大一在读的技术彩笔
*
* @brief python小白入门笔记
*
* @copyright 2022.8
* @COPYRIGHT 原创技术笔记:转载需获得博主本人同意,且需标明转载源
*
* @language python
* @Version 1.0还在学习中
*/
#27
# #闭包
'''本质: 内层函数对'''
"""特点:
1.可以使得一个变量常驻于内存
应用:计数器
2.保护变量不被修改(全局变量易被修改)
引入:
a=10
a=20
a=30最后print出来是30 (只会打印最终值)
"""
def func():
a=10
def inner(): #闭包部分@
print(a) #@
return a #@
return inner #@
ret=func()
ret()
'''
a=10被inner使用,inner被外层函数func函数作为返回值进行返回
'''
#ret(即inner)=>什么时候被执行
#可能立马ret()执行,或数行代码后编写ret()执行
'''应用原理:使得inner里的变量常驻于内存'''
#仿计数器制作
'''写法一:在全局调用局部执行'''
def func():
a=0 #设置初始量为0
def inner():
nonlocal a
a+=1
print(a)
return a
return inner
ret=func()
ret()
'''写法二:返回到全局,在全局print'''
def func():
a=0 #设置初始量为0
def inner():
nonlocal a
a+=1
return a
return inner
ret=func()
r1=ret() #计数第一次
r2=ret() #计数第二次
print(r1,r2)
'''应用:
利于编写出更安全的程序'''
#28
# #装饰器
'''(结论很关键,推导过程难可略过)'''
#装饰器: 本质上就是一个闭包
'''可以在不改变原有函数调用的情况下,
给函数增加新的功能'''
#即:可在函数前后添加新功能,但不用改原来程序
#引子:
'''相关知识回顾:
1.函数可以做为参数进行传递
{ func(inner) 表示传递inner函数本身
inner() 表示传递inner执行后的程序 }
2.函数可以作为返回值返回
3.函数名称可以当成变量一样进行赋值操作
'''
#1 函数可以做为参数进行传递
def func():
print("我是func")
def g(fn):
fn() #fn()即func()
g(func)
'''调用g,传递func函数,fn=func
fu()发出执行指令,执行func中的print任务'''
#2 函数可以作为返回值返回
def func():
def inner():
print(123)
return inner
i=func()
i() #调用func后执行inner
#worry:
def func():
def inner():
print(123)
return inner
i=func()
print(i) #打印返回值inner内存地址
#详看>15.1
#3 函数名称可以当成变量一样进行赋值操作
def func1():
print("i am func1")
def func2():
print("i am func2")
func1=func2
func1() #执行func2里的程序
#28.1 装饰器雏形
#模拟管家操控外挂
'''对两功能函数封装新功能'''
def guard(game): #管家负责外挂的开启与关闭
def inner(): #对inner进行闭包封装@
print("开启外挂") #@
game() #@
print("关闭外挂") #@
return inner #将inner函数返回给了guard函数@
@guard #艾特guard注意此函数的特殊性
def play_dnf(): #相当于执行了play_dnf=guard(play_dnf)
print("DNF运行")
@guard
def play_lol():
print("LOL运行")
play_dnf=guard(play_dnf) #重新定义pl_
# '''pl_得到的赋值来自于guard的返回值->来自于inner的返回值'''
play_dnf() #实际上运行的是inner函数
play_lol()
'''应用:
用户登录时,日志
(便于后续的修改,且安全保护以前的数据不被篡改)'''
#雏形模板
'''
def wrapper(fn): #wrapper:装饰器,fn: 目标函数
def inner():
( print(1) ) #目标函数执行前(检查用户登录情况)
fn() #调用inner函数执行
( print(2) ) #目标函数执行后(日志)
return inner # 返回函数,非函数执行结果
'''
#28.2 被装饰函数的参数问题
def guard(game):
def inner(user_name,password): #接收相关参数
game(user_name,password) #按需接收参数并运行
return inner
@guard
def play_lol(user_name,password):
print("开始游戏")
print("user_name:",user_name)
print("password:",password)
play_lol("admin","123") #调用时,提供给inner相关参数的值
#如果多个功能参数要求不同数目的
#solution:
"""inner添加参数<args得到是一个元组,kwargs得到是一个字典>"""
def guard(game):
def inner(*args,**kwarge): # *表示接收所有参数,打包成元组和字典
game(*args,**kwarge) # *把元组和字典打散成位置与关键字参数传递进去
return inner
'''注: 打散后都是参数,不再存在外壳括号,否则不能对'''
@guard
def play1(user_name,password):
print("开始游戏")
print("user_name:",user_name)
print("password:",password)
@guard
def play2(user_name, password,hero):
print("user_name:", user_name)
print("password:", password)
print("hero:",hero)
play1("ntzjake","1")
play2("joker","2","jake")
'''易错点:尤其要注意game()运行的那一行注释*******************
是个特例'''
'''优化:
def guard(fn):
def inner(*args,**args):
fn(*args,**args)
...
'''
#28.3 装饰器的返回问题
def guard(game):
def inner(*args,**kwarge):
ret=game(*args,**kwarge)
'''这里是目标函数的执行,这里能够拿到从目标函数返回的返回值'''
#solution:
return ret
'''给inner返回返回值, 该返回值来自game的调用,
即调用被装饰函数play1,获得play1的返回值,并赋值给ret,
将play1的返回值返回给inner,再由inner返回给guard'''
return inner
@guard
def play1(user_name,password):
print("开始游戏")
print("user_name:",user_name)
print("password:",password)
return "一把屠龙刀"
ret=play1("ntzjake","1") #加了@的play1实际调用的是inner函数
print(ret) #所以由于inner内部没有return返回返回值,print出None
'''再优化:'''
#通用装饰器的模板
'''
def wrapper(fn): #fn实际调用的是target函数
def inner(*args,**kwargs):
(函数执行前干......)
ret= fn(*args,**kwargs) #实际调用的是target
(函数执行后干......)
return ret
return inner
@wrapper
def target():
...
target() =>实际调用的是inner =>inner()
'''
#28.4 一个函数被多个装饰器装饰
def wrapper1(fn): #2^1 fn: wrapper2.inner
def inner(*args,**kwargs):
print("there's the@entrance of wrapper@1") #!1
ret=fn(*args,**kwargs) #!(2)执行wrapper2的inner
print("there's the@exit of wrapper@1") #!10
return ret #!(11)
return inner #!(12)返回值返给w1
def wrapper2(fn): #1^1 fn:target
def inner(*args,**kwargs):
print("there's the@entrance of wrapper@2") #!3
ret=fn(*args,**kwargs) #!(4)执行target
print("there's the@exit of wrapper@2") #!7
return ret #!(8)
return inner #!(9)返回给wrapper2,
#继续执行w1中的i
'''局部不影响全局:内部可为同名局部函数'''
@wrapper1 #把wrapper2与target包装的装饰器再进行装饰
'''2^2 target=target(wrapper2.inner) => taregt:wrapper1.inner'''
'''先从外包装运行而后内包装运行'''
@wrapper2 #1^2 target=wrapper2(target) => target: wrapper2
def target():
print("i am target") #!5
target() #!(6)调用wrapper2的inner,
#(继续读取w2的i中的程序).
"""result:there's the@entrance of wrapper@1
there's the@entrance of wrapper@2
i am target
there's the@exit of wrapper@2
there's the@exit of wrapper@1
"""
#原因解释:
'''就近原则:target函数靠近w2,先被w2所装饰,
包装成一个装饰器后,整体被再修饰'''
'''结论'''
#简要过程: w1>w2>target>w2>w1.
#28.5 装饰器的实战*********************************************
"""模拟员工注册与销注"""
'''添加,删除,修改,寻找'''
login_flag=False #先默认未完成登录验证
def login_verify(fn): #登录账户的验证
def inner(*args,**kwargs):
global login_flag #使全局变量进入局部
if login_flag==False: #与下面fn()居于同一垂直线
'''if判断解决了重复登录的问题'''
print("请继续完成登录操作...")
# 在此处完成登录操作中的输入:
while 1: #若一直登录不成功将一直停留在这层
user_name=input(">>>请输入用户名:")
password=input(">>>请输入您的密码:")
#在此处完成登录验证:
if user_name=="admin" and password=="123456":
print("登录成功...")
login_flag=True
break
else:
print("验证失败...")
print("用户名或密码错误>请重新输入")
ret=fn(*args,**kwargs) #实现后续的添加等操作
return ret
return inner
@login_verify
def add():
print("进入添加员工页面中...")
lst=[]
while 2:
a=input("请输入新员工姓名: ")
button = input("是否结束员工加入操作: (是/否)")
lst.append(a)
if button =="是":
print("正在添加中,请稍后...")
print("成员名单:",lst)
break
elif button=="否" :
print("请继续输入员工姓名...")
add()
其他同理:
def delete():
print("进入删除员工页面中...")
lst=[]
p=input("输入被删除员工姓名")
lst.pop(p)
def update():
print("进入更新(修改)信息页面中...")
lst=[]
u = input("输入需要修改员工姓名")
lst[ ]=u
def search():
print("进入检索员工页面中...")
#29
# #迭代器
'''可迭代的数据类型都会提供一个叫迭代器的东西,
这个迭代器可以帮我们把数据类型中的所有数据逐一的拿到'''
#29.1
#引子:
'''
for 变量 in 可迭代:
pass
'''
for c in "呵呵哒":
print(c) #result:呵(/n) 呵(/n) 哒
for c in 123:
print(c) #报错: 'int' object is not iterable
'''iterable: 可迭代的
iterator: 迭代器
可迭代的数据类型str, list, tuple, dict, set, open()'''
#关键知识点
'''
A.获取迭代器的两种方案:
1.iter()内置函数可以直接拿到迭代器(*****)
2. .__iter__()特殊方法[注意:双下划线]***************
B.从迭代器中拿到数据:
1.next()内置函数
注意:a.一次只拿一个
b.已经拿完时再次提取会报错: StopIteration
2. .__next__()特殊方法
C.for里面一定要拿迭代器,所以所有不可迭代的东西不能for循环
'''
#A1.
it=iter("呵呵哒")
print(it) #得到str的迭代器的内存地址
#A2.替代(不常用)
it="呵呵哒".__iter__()
print(it.__next__())
#模拟for循环工作原理:
s="i am date"
it=s.__iter__() #拿到迭代器
while 1:
date=it.__next__()
print(date) #进行for循环的循环体,最后会报错
# 原因:迭代结束后继续循环会报错
#solution:#试探性循环
'''py中异常处理:'''
s="date"
it=s.__iter__()
while 1:
try:
date=it.__next__()
print(date)
except StopIteration: #当报错时马上停止循环
break
print("完成")
"""
总结:1.迭代器统一了所有不同(可迭代的)数据类型的遍历工作
2.迭代器本身也是可迭代的
迭代器本身的特性:
1. 只能向前,不能反复
2. 特别节省内存(内部存放仿指针)
极小内存可以处理庞大数据集
3. 惰性机制
调用一次运行一次,不自动一次性全部运行完,
等待下一次调用
"""
#30
# #生成器
'''
生成器的本质就是迭代器, *************************
创建生成器的两种方案:
1.生成器函数
2.生成器表达式
'''
#30.1 生成器函数
#引子:
def func():
print(666)
return 999
ret=func() #调用func运行
print(ret) #打印出返回值
#关键笔记:
'''
1. generator: 生成器
2.生成器函数中有一个关键字yield
只要函数中出现yield,就是一个生成器函数,
作用:
A。可以返回数据( 相当于return)
B。可以分段的执行函数的内容,
通过__next()__可以执行到下一个yield位置前停止
3.生成器函数执行时, 并不会执行函数, 得到的是生成器
'''
def func():
print(666)
yield 999
ret=func()
print(ret) #<generator object func at 0x00000277662ACD60>
'''基于生成器本质是迭代器的原理:'''
def func():
print(666)
yield 999
ret=func()
print(ret.__next__()) #正常地输出print数据和返回值
'''可以分段的执行函数的内容'''
def func():
print(123)
return 999
print(456) #return后的同级程序无效
func()
'''但是yield:'''
def func():
print(123)
yield 999
print(456)
yield 666
ret=func()
print(ret.__next__()) #注意迭代器惰性特征
print(ret.__next__())
'''生成器的实战项目'''
# 去工厂定制10000件衣服
def order():
lst=[]
for i in range(10000):
lst.append(f"衣服(编号{i})") #将每件的码随着衣服打出
return lst #返回lst的最后结果
lst=order()
print(lst)
'''存在的问题:严重浪费内存, 需求<<供给'''
#solution:
def order():
lst=[]
for i in range(10000):
lst.append(f"衣服(编号{i})")
if len(lst)==10: #按需少量取出数据
yield lst #直到10次
#下一次拿数据将lst清空:
lst=[]
gen=order()
print(gen.__next__()) #负责每次拿数据的命令发出
'''注意:1~49,50件'''
print(gen.__next__()) #第二批次
'''
优势:
用好了,特别节省内存
'''
#30.2 推导式
'''优点:简化代码'''
'''缺点:逻辑不清晰'''
'''语法:
1.列表推导式: [数据 for循环 (if循环)](两个间有一个空格)
2.集合推导式: {数据 for循环 (if循环)}
3.字典推导式: {k,v for循环 (if循环)}
#注意:
1.元组没有推导式
原因:列表,集合,字典都是可以增删改查数据的,但是元组不能
2. (数据 for循环 (if判断)) =>不是元组推导式
而是生成器表达式
'''
#源码
lst=[]
for i in range(10): #程序都是从0开始数的
lst.append(i)
print(lst)
修改成 列表推导式
lst=[i for i in range(10)] #其中得到的数据就是i
print(lst)
# 创建奇数的列表1~9
lst=[i for i in range(1,10,2)]
print(lst)
#写法二:
lst=[i for i in range(10) if i % 2==1]
print(lst)
'''结: 利用奇数除二余一的特性作为条件判断'''
#将列表中的英文字母变为大写
lst=["zhang","wang","jake","rose"]
lst1=[item.upper() for item in lst]
'''由此得知:列表中植入的数据应该是期望得到的数据'''
print(lst)
#将列表修改成字典,要求索引作为key, 数据作为value
lst=["潘长江","赵本山","高达","奥特曼"]
dic={i:lst[i] for i in range(len(lst))}
print(dic)
# '''这里的key用i表示,value用lst[i]'''
#30.3 生成器表达式
'''语法:
(数据 for循环 (if判断))'''
#list(), set(), dict()本身内部存在循环迭代的过程有迭代器
'''list() =>for 循环 =>next()'''
s=list("周杰伦")
print(s) #['周', '杰', '伦']
#31
# #匿名函数
'''就是一个lambda表达式'''
'''语法规则:
变量= lambda 参数1,参数2...: 返回值
'''
#引子:
def func(a,b):
return a+b
ret=func()
print(ret)
#改为lambda
fn=lambda a,b:a+b
print(fn) #得到的是lambda function
ret=fn(12,13)
print(ret)
'''优势:简洁'''
#常和filter, map一起出现
#32
# #内置函数的补充(1)
#32.1 #zip
'''把多个可迭代内容进行合并'''
lst1=["赵本山","范伟","苏有朋"] #姓名
lst2=[60,40,30] #年龄
lst3=["卖拐","耳朵大有福","情深雨蒙蒙"] #作品
#按照位置将其分组放在一起
result=zip(lst1,lst2,lst3) #相当于for循环,将其先分类
for item in result: #对分出来的数据集分开
print(item)
#32.2 #locals,globals
#locals
'''查看****当前位置****的局部的内容'''
# a=188
# print(locals())
'''locals被写在全局作用域范围内,此时看到的就是全局作用域的内容'''
'''同理: 放在局部作用域,只看得到同级的内容'''
#globals
'''看到的是全局作用域的内容'''
#33
# #内置函数补充(2)
'''关键笔记:
zip: 可以把多个可迭代的内容合并
sorted:排序
filter: 筛选
map: 映射
'''
#33.1 #sorted
'''sort:排序
格式:
sorted(__iterable,key,reverse)*****************************
((可迭代的数据类型)数据,排序排序方法,是否翻转)
'''
lst=[123,4,56,7.8]
s=sorted(lst, reverse=False) #升序排列可以不写reverse翻转
print(s)
#非数字的排列
lst=["瑞秋","牛魔王","简"]
def func(item): #func负责接收item参数, item就是列表中的每一项数据
return len(item) #依据字符长短决定排列顺序
s=sorted(lst,key=func,reverse=False)
print(s)
'''fn 作为排序函数, 对字符进行数字化处理,
按照处理后得到的数据排序'''
#33.2 #filter
'''筛选
格式:
filter(__function,__iterable)******************************
'''
#筛选出姓张的人
lst=["张无忌","张三丰","张雪莉","唐家三少","王大爷"]
f=filter(lambda x:x.startswith("张"),lst)
print(list(f))
#反筛选
f1=filter(lambda x:not x.startswith("张"),lst)
print(list(f1))
#33.3 #map
"""映射"""
#平方口诀表
lst=[1,2,3,4,5,6,7,8,9]
result=[item*item for item in lst]
print(result)
#换做映射处理:
r=map(lambda x:x*x,lst)
print(list(r))
'''应用:
数据分析批量处理'''
'''区别:filter与map在匿名函数处理
x=xxx(lambad x : ...,__iterable)
filter: ...处进行for循环是判断参数是否传入
map: ...处进行for循环是要求得到的最终数据 (形态)
'''