说明: 1.三元运算、函数的基本结构,参数、返回值的相关基础概念; 2 主要了解在 python 中以函数为作用域的相关用法; 3.函数小高级:lambda 用法,内置函数,自定义函数等; 4 函数中高级:函数作为返回值、参数以及赋值的用法,这部分难懂很绕,需要多看几遍。还有函数执行的流程分析,闭包,map / filter / reduce 的高级用法。 5.学习模块、装饰器(包括带参数的装饰器)、推导式(列表、集合、字典)等。 PS: 以下内容全部是自己整理的笔记,代码也是自己一个一个敲上去之后运行无误才粘贴上的。
函数的思维导图如下:
对于函数编程:
● 本质:将 N 行代码拿到别处并给他起个名字,以后通过名字就可以找到这段代码,并执行。
● 场景:
● 代码重复执行
● 代码量特别多,超过一屏,可以选择通过函数进行代码的分割
三元函数是为了赋值的。前面的值 if 条件真 --> 前面的值 else 后面的值
if 条件 : v = 前面 else: v = 后面 v = 前面 if 条件 else 后面 # 一行就可以实现练习
# 假如,管理员、业务员、老板用的是同一个邮箱。发送邮件的例子,输入管理员、业务员、老板显示发送成功 def send_email(): print('邮件发送成功,假设有20行代码') message = input('请输入角色:') if message == '管理员': send_email() if message == '业务员': send_email() if message == '老板': send_email() ● 任意个数
● 任意类型
def func(a1,a2,a3): print(a1,a2,a3) func(1,'alex',True) ● 补充:对于函数的默认值慎用可变类型。
# 如果要想给 value 设置默认是空列表 # 不推荐(坑) def func(data,value=[]) pass # 推荐 def func(data,value=None) if not value: value = []举例:
def func(a,b=[]): b.append(a) return b # 分开打印 l1 = func(1) print(l1) # [1] l2 = func(2,[11,22]) print(l2) # [11,22,2] l3 = func(3) print(l3) # [1,3] # 默认是同一个地址,如果不传参数,那么 b = [] 会随着添加进来的元素而改变。现在的 l1 变成了 [1,3] # 如果有参数传入,则用自己传入的参数问题:
● def func(a,b=[]) 有什么陷阱?
b=[] 是可变类型,如果不传参数,默认是同一个地址。
● 看代码写结果
def func(a,b=[]): b.append(a) return b l1 = func(1) # [1] l2 = func(2,[11,22]) # [11,22,2] l3 = func(3) # [1,3] # 一起打印 print(l1,l2,l3) # [1,3] [11,22,2] [1,3] def func(a,b=[]): b.append(a) return b # 分开打印 l1 = func(1) print(l1) # [1] l2 = func(2,[11,22]) print(l2) # [11,22,2] l3 = func(3) print(l3) # [1,3] ● 看代码写结果
def func(a,b=[]): b.append(a) print(b) func(1) # [1] func(2,[11,22]) # [11,22,2] func(3) # [1,3] ● 关键字传参数和位置传参数可以混合使用 (位置传参一定在关键字传参前面)
def func(a1,a2,a3): print(a1,a2,a3) func(1,2,a3=9) func(1,a2=2,a3=9) func(a1=1,2,9) # 报错 ● 位置传参数在前 + 关键字传参数在后 = 参数总个数
● 先处理位置传参,再处理关键字传参
例子:
def func(a1,a2,a3=9,a4=10): print(a1,a2,a3,a4) func(1,2) # 1 2 9 10 func(1,a2=18) # 1 18 9 10 func(a1=123,a2=999) # 123 999 9 10 func(1,2,a3=33,44) # 报错 前面若有关键字传参,后面一定也是关键字传参,位置传参一定是在关键字传参前面 func(1,a2=2,a3=33,a4=44) # 1 2 33 44 func(a1=1,a2=2,a3=33,a4=44) # 1 2 33 441.*args 是多个变量组成的元组,输出的类型都是元组
def func(*a): print(a) print(type(a)) func(1) # (1,) <class 'tuple'> func(1,2) # (1, 2) <class 'tuple'> func((1,2,3,4,5)) # ((1, 2, 3, 4, 5),) <class 'tuple'> func('alex',1,True,[11,22,33],(1,2)) # ('alex', 1, True, [11, 22, 33], (1, 2)) <class 'tuple'> func(*(1,2,3,4,5)) # (1, 2, 3, 4, 5) <class 'tuple'> func(*('alex',1,True,[11,22,33],(1,2))) # ('alex', 1, True, [11, 22, 33], (1, 2)) <class 'tuple'> ● *args 只支持位置传参,不支持关键字传参
● 可以接受任意个数的参数,并将参数转换成元组
● 调用函数有 *
def func(a1,*args): print(a1,args) func(1,2,3,4,5) # 1 (2, 3, 4, 5) def func(a1,*args,a2): print(a1,args,a2) func(1,2,3,4,5) # 1 (2, 3, 4, 5) 只要a2 前面有args,a2永远拿不到值 def func(a1,*args,a2=10): print(a1,args,a2) func(1,2,3,4,5) # 1 (2, 3, 4, 5) 10 def func(a1=10,*args,a2=10): print(a1,args,a2) func(1,2,3,4,5) # 1 (2, 3, 4, 5) 10 1 把a1 = 10 覆盖了 ● 调用函数无 *
def func(a1,a2=9): pass func(1,2) # 1 2 ● 只能用位置传参
2.**kwargs 关键词传参:输出类型是字典
def func(**kwargs): print(kwargs) ● **kwargs 只支持关键字传参
● 可以接受任意个数的关键字参数,并将参数转换成字典
● 调用函数有 **
func(**{'k1': 1, 'k2': 'alex'}) # {'k1': 1, 'k2': 'alex'} ● 调用函数无 **
func(k1=1,k2='alex') # {'k1': 1, 'k2': 'alex'}3.综合应用
def func(*args,**kwargs): print(args,kwargs) func(1,2,(1,2),k1=1,k2='alex') # (1, 2, (1, 2)) {'k1': 1, 'k2': 'alex'}练习1 发送邮箱
# 邮箱 无返回值 def send_email(role,to): template = '要给%s%s发送邮件'%(role,to,) print(template) message = input('请输入角色:') if message == '管理员': send_email('管理员','jdhsifs@qq.com') # 要给管理员jdhsifs@qq.com发送邮件 if message == '业务员': send_email('业务员','4363657856@qq.com') if message == '老板': send_email('老板','jgdftgdr45s@qq.com') val = send_email('管理员','jdhsifs@qq.com') # 调用返回值 print(val) # None 若有return,有返回值,否则,为None # 邮箱 有返回值 def send_email(role,to): template = '要给%s%s发送邮件'%(role,to,) print(template) return '结束' message = input('请输入角色:') if message == '管理员': val = send_email('管理员','jdhsifs@qq.com') # 要给管理员jdhsifs@qq.com发送邮件 # 调用返回值 if message == '业务员': val = send_email('业务员','4363657856@qq.com') # 调用返回值 if message == '老板': val = send_email('老板','jgdftgdr45s@qq.com') # 调用返回值 print(val) # 结束 若有return,有返回值,否则,为None练习2 让用户输入一段字符串,计算字符串中有多少A字符的个数。有多少个就在文件a.txt中写多少个’你好’
# 方法一 def count_num(arg): count = 0 for i in arg: if i == 'A': count += 1 return count content = input('请输入:') # hhhhhhhdfAAAAAAAAAAAFSDZG val = count_num(content) print(val) # 11 val = int(val) f = open('a.txt',mode = 'w',encoding = 'utf-8') for i in range(0,val): # 前取后不取 等价于for i in range(val): f.write('你好') f.close() # 方法二 def count_num(arg): count = 0 for i in arg: if i == 'A': count += 1 return count def write_file(line): if line == 0: return False # 函数执行过程中,一旦遇到return,则停止函数的执行 f = open('a.txt', mode='w', encoding='utf-8') f.write(content) f.close() return True message = input('请输入:') # hhhAAhhhAAhdfAFSDZGAA val = count_num(message) print(val) # 7 content = '你好'* val write_file(content) status = count_num(message) if status: print('写入成功') else: print('写入失败')练习3 写函数,计算一个列表中有多少个数字,打印:列表中有%s个数字。
提示:type(‘x’) == int 判断是否是数字。
# 方法一: def num_count(list): count = 0 for item in list: if type(item) == int: count += 1 return count num_count(['gf',1,55,7,'fggh']) num = num_count(['gf',1,5,7,'fggh']) message = '列表中有%s个数字'%(num,) print(message) # 方法二: def num_count(list): count = 0 for item in list: if type(item) == int: count += 1 message = '列表中有%s个数字' % (count,) print(message) num_count(['gf',1,55,7,'fggh'])练习4 写函数,计算一个列表中偶数索引位置的数据构造成另外一个列表,并返回。【注】题目没说要打印,因此不需要print()
# 方法一: def new_list(list): new_list = list[::2] return new_list new_list(['gf',1,55,7,'fggh','gf',1,55,7,'fggh']) # 方法二: def new_list(list): new_list =[] list_len = len(list) for i in range(0,list_len): if i % 2 == 0: new_list.append(list[i]) return new_list new_list(['gf',1,55,7,'fggh','gf',1,55,7,'fggh']) # v = new_list(['gf',1,55,7,'fggh','gf',1,55,7,'fggh']) # print(v)练习5 阅读文件,将文件的内容构造成指定格式的数据,并返回,打印出来。
''' a.log文件 alex|123|18 eric|uiuf|19 ... 目标结构: a. ['alex|123|18','eric|uiuf|19'] 并返回 b. [['alex','123','18'],['eric','uiuf','19']] 并返回 c. [ {'name':'alex','pwd':'123','age':'18'} {'name':'eric','pwd':'uiuf','age':'19'} ] ... ''' def write_file(): file_w = open('a.log',mode = 'w',encoding = 'utf-8') content = 'alex|123|18\n'+'eric|uiuf|19\n' file_w.write(content) file_w.close() def list_str(): file_r = open('a.log', mode='r', encoding='utf-8') a = [] for line in file_r: line = line.strip() a.append(line) print(a) # 如果下面有print,此处就不用写了,如果下面没有print,此处就写 file_r.close() return a def list_list(): file_r = open('a.log', mode='r', encoding='utf-8') b = [] for line in file_r: line = line.strip() result = line.split('|') b.append(result) print(b) # 如果下面有print,此处就不用写了,如果下面没有print,此处就写 file_r.close() return b def list_dict(iii): file_r = open('a.log', mode='r', encoding='utf-8') a = [] b = [] c = [] for line in file_r: line = line.strip() a.append(line) result = line.split('|') b.append(result) file_r.close() for i in range(0,2): info = {} info['name'] = b[i][0] info['pwd'] = b[i][1] info['age'] = b[i][2] # print(info) info.update(info) c.append(info) # 如果下面有print,此处就不用写了,如果下面没有print,此处就写 if iii == 'a': print(a) elif iii == 'b': print(b) elif iii == 'c': print(c) return a,b,c # list_str() # list_list() list_dict('a') list_dict('b') list_dict('c')1.python 中:
● py文件:全局作用域 全局变量以后必须要大写
● 函数:局部作用域
a = 1 # 全局变量 def s1(): # 局部变量 x1 = 666 print(a) # 1 print(b) # 2 print(x1) # 666 b = 2 print(a) # 1 s1() # 若s1 放在b的前面,报错 a = 888 def s2(): print(a,b) # 888 2 s1() # s2()函数内部调用另一个函数 s1()的前提是,s1()在全局上有定义 s2() c = a + b print(c) ######## 执行顺序:a = 1--> b = 2--> print(a)--> s1() [print(a)-> print(b) ->print(x1)] --> s2() print(a,b) --> c = a + b -->print(c)2.函数的嵌套
# 函数的嵌套 x = 10 def func1(): x=9 print(x) def func2(): x=999 print(x) print(x) func2() func1() # 先执行func1() 9 --> print(x) 9 -->func2() 999 x = 10 def func1(): x=8 print(x) def func2(): print(x) func2() x = 9 func2() x = 10 print(x) func1() # 8-->8--> 9--> 10 name = 'oldboy' def func(): name = 'alex' # 在自己作用域再创建一个这样的值,无法覆盖父级的值 print(name) # alex func() print(name) # oldboy name = [11,2,33,11] def func(): name.append('alex') # 不是重新赋值,但是可以对可变类型【列表、字典】修改 print(name) # [11, 2, 33, 11, 'alex'] func() print(name) # [11, 2, 33, 11, 'alex']3.global 如果非要对全局变量进行重新赋值,即使函数有嵌套,也是对全局变量修改
# 情况一: name = 'oldboy' def func(): global name name = 'alex' print(name) # alex func() print(name) # alex # 情况二: name = 'oldboy' def func(): name = 'alex' print(name) # alex def inner(): global name name = 999 inner() func() print(name) # 9994.nonlocal 找到上一级进行修改
name = 'oldboy' def func(): name = 'alex' def inner(): nonlocal name name = 999 inner() print(name) # 999 func() print(name) # oldboy5.总结:
● 一个函数是一个作用域
● 作用域中查找数据规则:优先在自己的作用域查找,自己没有就去“父级”–> 下一级“父级” --> 直到全局。全部没有就报错。
● 局部可以用全局的,全局不能用局部的
● 本质:函数自己调用自己,效率不高。【默认递归次数是1000次】
def func(): print(1) func() func() # 不停的循环打印 1 ,最多打印 1000 次 def func(i): print(i) func(i+1) func(1) # 打印 1 2 3 4 ... def func(a,b): print(b) func(b,a+b) func(0,1) # 1 1 2 3 5 8 13 21 ...函数包括自定义函数和内置函数
● input()
● print()
● dict()
● list()
● int()
● tuple()
● str()
● bool()
● set()
1.abs() 绝对值
# abs() 绝对值 v = abs(-1) print(v) # 1 2.float() 转换成浮点型
# float() 转换成浮点型 v = 55 v1 = float(v) print(v1) # 55.0 3.max() 找到最大值
# max() 找到最大值 v = [1,2,331,55] result = max(v) print(result) # 331 4.min() 找到最小值
# min() 找到最小值 v = [1,2,331,55] result = min(v) print(result) # 1 5.sum() 求和
# sum() 求和 v = [1,2,331,55] result = sum(v) print(result) # 389 6.divmod() 两数相除的商和余数
# divmod() 两数相除的商和余数 result = divmod(1001,5) print(result) # (200, 1) a,b = divmod(1001,5) print(a,b) # 200 1 7.pow() 指数
# pow() 指数 ,类似于2**3 v = pow(2,3) print(v) # 8 8.round() 保留几位小数,含四舍五入
# round()保留几位小数,含四舍五入 v = round(1.5468711,2) print(v) # 1.55练习题 请通过分页对数据进行展示
要求:
每页显示10条数据
让用户输入要查看的页面:页码
USER_LIST = [] for i in range(1,836): # 显示1到835条信息 temp = {'name':'李杰-%s'%i,'email':'123%s@qq.com'%i} USER_LIST.append(temp) # 数据总条数 total_count = len(USER_LIST) # 每页显示10条数据 per_page_count = 10 # 总页码数 max_page_num,a = divmod(total_count,per_page_count) if a > 0: max_page_num += 1 """ 第一页:USER_LIST = [0:10] 第二页:USER_LIST = [10:20] 第三页:USER_LIST = [20:30] 第四页:USER_LIST = [30:40] """ while True: pager = input('请输入页码:') pager = int(pager) if pager < 1 or pager > max_page_num: print('页码不合法,必须是1~%s'%max_page_num) else: start = (pager-1) * per_page_count end = pager * per_page_count data = USER_LIST[start : end] for item in data: print(item)1.bin() 将十进制转化成二进制
# bin 将十进制转换成二进制 num = 15 v1 = bin(num) print(v1) # 0b11112.oct() 将十进制转化成八进制
# oct 将十进制转换成八进制 num = 7 # 8 v1 = oct(num) print(v1) # 0o7 0o103.hex() 将十进制转化成十六进制
# hex ,将十进制转换成十六进制 num = 9 # 10/11/15/16 v1 = hex(num) print(v1) # 0x9 0xa 0xb 0xf 0x104.int() 其他进制转换成十进制
① 二进制转化成十进制
# 二进制转化成十进制 v1 = '0b1011' result = int(v1,base=2) # 将二进制转化成十进制 print(result) # 11 ② 八进制转化成十进制
# 八进制转化成十进制 v1 = '0o1011' result = int(v1,base=8) print(result) # 521 ③ 十六进制转化成十进制
# 十六进制转化成十进制 v1 = '0x1011' result = int(v1,base=16) print(result) # 4113练习题1 将 ip = ‘192.168.12.79’,中的十进制转换成二进制,并通过‘,’连接起来,生成一个新的字符串。
ip = '192.168.12.79' ip_list = ip.split('.') v = [] for item in ip_list: item = int(item) v1 = bin(item) v.append(v1) ip_new = ','.join(v) print(ip_new) # 0b11000000,0b10101000,0b1100,0b1001111练习题2 将 ip = '192.168.12.79’中的十进制转换成二进制,
拼接成如下形式:11000000101010000000110001001111 (注:每个字节保留八位,不足八位前面补零,并去掉0b
ip = '192.168.12.79' ip_list = ip.split('.') v = [] for item in ip_list: item = int(item) v1 = bin(item) v2 = v1.lstrip('0b') # 1100 v2_len = len(v2) if v2_len == 8: v.append(v2) else: count = 8-v2_len v3 = ('0' * count)+v2 v.append(v3) ip_new = ''.join(v) print(ip_new) # 110000001010100000001100010011111.chr() 将十进制数字转换成Unicode 编码中对应的字符串
# 1.chr,将十进制数字转换成unicode编码中的对应字符串 v = chr(99) print(v) # c2.ord() 根据字符在Unicode 编码中找到其对应的十进制
v = ord('中') print(v) # 20013 # 练习 v = '中国' for item in v: data = ord(item) print(data) print(bin(data)) # 20013 # 0b100111000101101 # 22269 # 0b1010110111111013.应用。随机验证码的生成
# random.randint(a,b):用于生成一个指定范围内的整数。其中参数a是下限,参数b是上限,生成的随机数n:a<=n<=b # 随机生成6位的验证码 import random data = [] for i in range(6): v = random.randint(65,90) v_chr = chr(v) data.append(v_chr) print(data) result = ''.join(data) print(result) # 随机生成任意位的验证码 import random # 导入一个模块 data = [] def get_random_code(length): for i in range(length): v = random.randint(65,90) # 去模块里找一个生成随机整数的函数来用 data.append(chr(v)) return ''.join(data) code = get_random_code(7) print(code) ● len()
● open()
● id()
● range()
● type()
● 谁调用谁,谁的返回值就是谁
● 用于表示简单的函数,lambda 也叫匿名函数
● lambda 内部不能自己创建变量,只能用传递过来的或者在他的父级上找
# 1 def func1(a1,a2): return a1+100 v1 = func1(1,2) func2 = lambda a1,a2: 1+100 v2 = func2(1,2) print(v1,v2) # 101 101 # 2 func3 = lambda : 100 v3 = func3() print(v3) # 100 # 3 func4 = lambda a1: a1*100 v4 = func4(6) print(v4) # 600 # 4 func5 = lambda *args,**kwargs: len(args)+len(kwargs) v5 = func5(1,2,3,k1=1,k2=2,k3=3) print(v5) # 6 # 5 DATA = 100 func6 = lambda a1 : a1+DATA v6 = func6(1) print(v6) # 101 # 6 DATA = 100 def func(): DATA = 1000 func7 = lambda a1: a1+DATA v7 = func7(1) print(v7) # 1001 func() # 7 def func(n1,n2): if n1>n2: return n1 else: return n2 v = func(4,5) print(v) # 5 func1 = lambda n1,n2: n1 if n1>n2 else n2 v1 = func1(4,5) print(v1) # 5v = bar() 返回的是func的地址,v()执行func函数
name = 'oldboy' def bar(): name = 'alex' def inner(): print(name) return inner v = bar() # 有返回值,返回inner print(v) # <function bar.<locals>.inner at 0x0000000002794EA0> v() # 'alex' name = 'oldboy' def bar(name): # 'alex' def inner(): print(name) return inner v1 = bar('alex') # { name = alex, inner } # 闭包,为函数创建一块区域(内部变量供自己使用),为他以后执行提供数据。 v2 = bar('eric') # { name = eric, inner } v1() # 'alex' v2() # 'eric' name = 'alex' def base(): print(name) def func(): name = 'eric' base() func() # alex 这道题很容易错 name = 'alex' def func(): name = 'eric' def base(): print(name) base() func() name = 'alex' def func(): name = 'eric' def base(): print(name) return base base = func() base()面试题:易错
# 第一题 info = [] def func(): print(item) for item in range(10): info.append(func) # 循环完毕,此时item等于9 info[0]() # info = [func,func,func,func,func,func,func,func,func] # 最后打印的是9 # 第二题 info = [] def func(i): def inner(): print(i) return inner for item in range(10): info.append(func(item)) info[0]() # 0 info[1]() # 1 info[4]() # 4 ● 为函数创建一块区域(内部变量供自己使用),为他以后执行提供数据。
# 结构 def func(name): def inner(): print(name) return inner v1 = func('alex') v1() v2 = func('eric') v2() # 不是闭包 def func(name): def inner(): return 123 return inner # 是闭包:封装置 + 内层函数需要使用 def func(name): def inner(): print(name) return 123 return inner ● 把函数当作参数传递
● 把函数当作返回值
● 注意:对函数进行赋值
● 函数执行的流程分析 (函数到底是谁创建的) 一定要理清楚
● 闭包概念:为函数创建一块区域(内部变量供自己使用),为他以后执行提供数据。【应用场景】装饰器 / SQLAIchemy源码
1.map(函数,可循环的类型) ,循环每个元素(第二个参数),然后让每个元素执行函数(第一个参数),将每个函数执行的结果保存到新的列表中,并返回。
# 1. map()函数应用 # 将列表中元素逐个+100后打印出来 # 1 v1 = [11,22,33,44] def func(arg): print(arg) result = map(func,v1) # 将函数的返回值添加到列表中了。该函数没有返回值,即None # 第一个参数:必须是一个函数 # 第二个参数:必须是可迭代类型【内部元素可以被for循环】 eg:元组,列表,字典,集合 print(list(result)) # 转换成列表才能打印出来 # 11 # 22 # 33 # 44 # [None, None, None, None] # 2 v1 = [11,22,33,44] def func(arg): return arg+100 result = map(func,v1) # 将函数的返回值添加到列表中了 # 第一个参数:必须是一个函数 # 第二个参数:必须是可迭代类型【内部元素可以被for循环】 eg:元组,列表,字典,集合 print(list(result)) # [111, 122, 133, 144] # 3 v1 = [11,22,33,44] result = map(lambda x:x+100,v1) print(list(result)) # [111, 122, 133, 144] ● map只是循环 v1 里面的元素,并不影响v1
2.filter(函数,可循环对象v1),进行筛选
# filter 函数的应用。进行筛选 v1 = [11,'alex',22,'eric',33,True,44] def func(arg): if type(arg) == int: return True return False result = filter(func,v1) print(list(result)) # [11, 22, 33, 44] v1 = [11,'alex',22,'eric',33,True,44] def func(arg): return True if type(arg) == int else False result = filter(func,v1) print(list(result)) v1 = [11,'alex',22,'eric',33,True,44] def func(arg): return type(arg) == int result = filter(func,v1) print(list(result)) v1 = [11,'alex',22,'eric',33,True,44] result = filter(lambda x:True if type(x) == int else False,v1) print(list(result)) v1 = [11,'alex',22,'eric',33,True,44] result = filter(lambda x:type(x) == int,v1) print(list(result))3.reduce (函数(x,y),v1) 对多个元素进行处理。 要调用 functools 模块
# reduce(函数(x,y)必须是两个参数,v1) 函数应用。对多个元素进行处理,比如相加,相乘。。。 # 将列表内元素相加 import functools v1 = [1,2,3,4,5,6] def func(x,y): return x+y result = functools.reduce(func,v1) print(result) # 21 import functools v1 = [1,2,3,4,5,6] result = functools.reduce(lambda x,y:x+y,v1) print(result) # 21字符串的拼接
import functools v1 = ['wo','hao','e'] def func(x,y): return x+y result = functools.reduce(func,v1) print(result) # wohaoe