欢迎来到python的世界
博客主页:卿云阁欢迎关注点赞收藏⭐️留言
本文由卿云阁原创!
本阶段属于练气阶段,希望各位仙友顺利完成突破
首发时间:2021年4月3日
✉️希望可以和大家一起完成进阶之路!
作者水平很有限,如果发现错误,请留言轰炸哦!万分感谢!
一、参数
(1)形参与实参
def calc(x,y): res = x**y print(res) a = 5 b = 4 calc(a,b)
(2)默认参数
def zongce(name,mid,end,mid_rate=0.4): zongce=mid*mid_rate+end*(1-mid_rate) print("----学⽣信息------") print("期中成绩:", mid) print("期末成绩:", end) print("综测成绩:{0:<5}".format( zongce)) zongce("qingyun",98,99) zongce("zhangxveqing",98,99,0.5) 结果 ----学⽣信息------ 期中成绩: 98 期末成绩: 99 综测成绩:98.6 ----学⽣信息------ 期中成绩: 98 期末成绩: 99 综测成绩:98.5
(3)可变参数
def sum(a,b,*c): print(c) total=a+b for i in c: total=total+i return total print(sum(1,2,3,4,5,6,7)) 结果 (3, 4, 5, 6, 7) 28
def sum(a,b,*c,**d): print(c) print(d) total=a+b for i in c: total=total+i for key in d: total=total+d[key] return total print(sum(1,2,3,4,5,6,7,qingyun=1,zxq=2)) 结果 (3, 4, 5, 6, 7) {'qingyun': 1, 'zxq': 2} 31
二. 返回值return
函数外部的代码要想获取函数的执⾏结果,就可以在函数⾥⽤ return 语句把结果返回注意函数在执⾏过程中只要遇到 return 语句,就会停⽌执⾏并返回结果, so 也可以理解为 return 语句 代表着函数的结束 如果未在函数中指定return, 那这个函数的返回值为 Nonedef zuowen(name,f,s,*o): max=f if f
多条return语句
import math def is_prime(n): if n<2: return False i=2 while(i
返回多个值
import random def randomarry(n): a=[] for i in range(n): a.append(random.random()) return a b=randomarry(5) print(b) 结果: [0.6068501158240774, 0.0761204880150359, 0.8275832346568391, 0.3464213540970127, 0.8964706536915046]
三,变量的作用域
name = "qingyun" def change_name(): name = "qingyunqingyunge" print("after change", name) change_name() print("now name",name)
传递列表、字典产⽣的现象d = {"name":"qingyun","age":19,"hobbie":"pinpang"} l = ["Rebeeca","Katrina","Rachel"] def change_data(info,girls): info["hobbie"] = "学习" girls.append("XiaoYun") change_data(d,l) print(d,l)
四、内置函数
前面使用过一些函数,有的同学会疑问我没有导入这个函数,为什么可以直接使用?因为这些函数都是一个叫做 builtins 模块中定义的函数,而 builtins 模块默认在Python环境启动的时 候就自动导入,所以你可以直接使用这些函数。abs()绝对值函数。如abs(-1)= 1print(abs(-10)) f = abs print(f(-1)) abs=id print(abs(1)) 以abs()函数为例,展示两个特性。一是,内置函数是可以被赋值给其他变量的,同样也可以将其他对象赋 值给内置函数,这时就完全变了。所以,内置函数不是Python关键字,要注意对它们的保护,不要使用和 内置函数重名的变量名,这会让代码混乱,容易发生难以排查的错误。
all()
接收一个可迭代对象,如果对象里的所有元素的bool运算值都是True,那么返回True,否则False
print(all([1,1,1])) 结果: True
any()接收一个可迭代对象,如果迭代对象里有一个元素的bool运算值是True,那么返回True,否则False。与all()是一 对兄弟。print(any([0,0,1])) 结果 True
bin()、oct()、hex()三个函数是将十进制数分别转换为2/8/16进制i = 10 print(bin(i)) 结果 0b1010
zip()
组合对象。将对象逐一配对。等等
range函数
a = ['Google', 'Baidu', 'Huawei', 'Taobao', 'QQ'] for i in range(len(a)): print(i, a[i]) 结果 0 Google 1 Baidu 2 Huawei 3 Taobao 4 QQ
五、匿名函数
当我们在创建函数时,有些时候,不需要显式地定义函数,直接传入匿名函数更方便。这省去了我们挖空心思为 函数命名的麻烦,也能少写不少代码,很多编程语言都提供这一特性。Python语言使用 lambda 关键字来创建匿名函数。所谓匿名,即不再使用 def 语句这样标准的形式定义一个函数。1. lambda只是一个表达式,而不是一个代码块,函数体比def简单很多。2. 仅仅能在lambda表达式中封装有限的逻辑。3. lambda 函数拥有自己的命名空间lambda x: x * x
它相当于下面的函数def f(x): return x*x 关键字lambda表示匿名函数,冒号前面的x表示函数参数,x*x是执行代码
匿名函数只能有一个表达式,不用也不能写return语句,表达式的结果就是其返回值。 匿名函数没有函数名字, 不必担心函数名冲突,节省字义空间。此外,匿名函数也是一个函数对象,也可以把匿名函数赋值给一个变量, 再利用变量来调用该函数.f = lambda x: x * x print(f(6)) #也可以把匿名函数作为别的函数的返回值返回 def count(i,j): return lambda : i*j f = count(6,7) print(f) print(f())
匿名函数的应用
对列表中的字典进行排序lis = [1,-2,4,-3] lis.sort(key=abs) print(lis) infors = [{'name':'cangls','age':18},{'name':'bols','age':20},{'name':'jtls','age':25}] infors.sort(key = lambda x:x['name']) print(infors)
匿名函数当做实参def test(a,b,func): result = func(a,b) return result nums = test(11,22,lambda x,y:x+y) print(nums)
六、推导式
Python语言有一种独特的推导式语法,相当于语法糖的存在,可以帮你在某些场合写出比较精简酷炫的代码。列表推导式lis = [x * x for x in range(1, 10)] print(lis)
字典推导式
dic = {i:i**3 for i in range(5)} print(dic)
集合推导式
s = {i for i in 'abasrdfsdfa' if i not in 'abc'} print(s) #把abc排除剩余字符串
七、迭代器
在介绍迭代器之前,先说明下迭代的概念:迭代:通过for循环遍历对象的每一个元素的过程。Python的for语法功能非常强大,可以遍历任何可迭代的对象。在Python中, list/tuple/string/dict/set/bytes 都是可以迭代的数据类型。可以通过collections模块的 Iterable 类型来判断一个对象是否可迭代:from collections import Iterable isinstance('abc', Iterable) # str是否可迭代 True isinstance([1,2,3], Iterable) # list是否可迭代 True isinstance(123, Iterable) # 整数是否可迭代 False
迭代器是一种可以被遍历的对象,并且能作用于next()函数。迭代器对象从集合的第一个元素开始访问,直到所 有的元素被访问完结束。 迭代器只能往后遍历不能回溯,不像列表,你随时可以取后面的数据,也可以返回头取 前面的数据。迭代器通常要实现两个基本的方法: iter() 和 next() 。 字符串,列表或元组对象,甚至自定义对象都可用于创建迭代器:from collections.abc import Iterable,Iterator print(isinstance([],Iterable)) #是否可迭代 print(isinstance([],Iterator)) #是否是迭代器 lis=[1,2,3,4] it = iter(lis) # 使用Python内置的iter()方法创建迭代器对象 print(next(it)) # 使用next()方法获取迭代器的下一个元素 print(next(it)) # 使用next()方法获取迭代器的下一个元素 print(next(it)) # 使用next()方法获取迭代器的下一个元素 print(next(it))# 使用next()方法获取迭代器的下一个元素 结果 True False 1 2 3 4
Python的迭代器表示的是一个元素流,可以被next()函数调用并不断返回下一个元素,直到没有元素时抛 出StopIteration错误。可以把这个元素流看做是一个有序序列,但却不能提前知道序列的长度,只能不断通过 next()函数得到下一个元素,所以迭代器可以节省内存和空间。 迭代器(Iterator)和可迭代(Iterable)的区别:1. 凡是可作用于for循环的对象都是可迭代类型;2. 凡是可作用于next()函数的对象都是迭代器类型;3. list、dict、str等是可迭代的但不是迭代器,因为next()函数无法调用它们。可以通过iter()函数将它们转换成 迭代器。4. Python的for循环本质上就是通过不断调用next()函数实现的。
八、生成器
有时候,序列或集合内的元素的个数非常巨大,如果全制造出来并放入内存,对计算机的压力是非常大的。比 如,假设需要获取一个10**20次方如此巨大的数据序列,把每一个数都生成出来,并放在一个内存的列表内,这 是粗暴的方式,有如此大的内存么?如果元素可以按照某种算法推算出来,需要就计算到哪个,就可以在循环的 过程中不断推算出后续的元素,而不必创建完整的元素集合,从而节省大量的空间。在Python中,这种一边循环一边计算出元素的机制,称为生成器:generator。生成生成器:g = (x * x for x in range(1, 4)) print(g)
可以通过next()获得generator的下一个返回值,这点和迭代器非常相似:
g = (x * x for x in range(1, 4)) print(g) print(next(g)) print(next(g)) 结果: 1 4
除了使用生成器推导式,我们还可以使用 yield 关键字。
def createNums(): print("----func start------") a,b = 0,1 for i in range(5): print(b) print("--1--") yield b print("--2--") a,b = b,a+b # a,b = 1, 1 a,b = 1,2 print("--3--") print("----func end------") g= createNums() print(next(g)) # 如果想得到yield的值,可以打印next(g) print(next(g)) 结果 ----func start------ 1 --1-- 1 --2-- --3-- ----func end------ 1 --1-- 1
在 Python中,使用yield返回的函数会变成一个生成器(generator)。 在调用生成器的过程中,每次遇到yield 时函数会暂停并保存当前所有的运行信息,返回yield的值。并在下一次执行next()方法时从当前位置继续运行。生成器的应用实现多任务def test1(): while True: print("--1--") yield None def test2(): while True: print("--2--") yield None t1 = test1() t2 = test2() while True: next(t1) next(t2) break 结果 --1-- --2--
九、装饰器
装饰器(Decorator):从字面上理解,就是装饰对象的器件。可以在不修改原有代码的情况下,为被装饰的对 象增加新的功能或者附加限制条件或者帮助输出。装饰器有很多种,有函数的装饰器,也有类的装饰器。装饰器 在很多语言中的名字也不尽相同,它体现的是设计模式中的装饰模式,强调的是开放封闭原则。装饰器的语法是 将@装饰器名,放在被装饰对象上面。@dec def func(): pass
在介绍装饰器之前,先要了解几个知识点重名函数会怎么样?def test(): print('1') def test(): print('2') test() #这个时候会输出什么? 会输出2,后面的会覆盖前面的函数
接下来就是一个比较经典的案例了,有一个大公司,下属的基础平台部负责内部应用程序及API的开发。另外还 有上百个业务部门负责不同的业务,这些业务部门各自调用基础平台部提供的不同函数,也就是API处理自己的业务,情况如下:基础平台部门提供的功能如下def f1(): print("业务部门1的数据接口......") def f2(): print("业务部门2的数据接口......") def f3(): print("业务部门3的数据接口......") def f100(): print("业务部门100的数据接口......") #各部门分别调用基础平台提供的功能 f1() f2() f3() f100()
目前公司发展壮大,但是以前没有考虑到验证相关的问题,即:基础平台提供的功能可以被任何人使用。现在需 要对基础平台的所有功能进行重构,为平台提供的功能添加验证机制,执行功能前,先进行验证 老大把工作交给 A,他是这么做的: 跟每个业务部门交涉,每个业务部门自己写代码,调用基础平台的功能之前先验证。这样一来基础平台就不需要做任何修改了。 当前A被老大开除了 老大又把工作交给B,他是这么做的:def f1(): # 验证1 # 验证2 # 验证3 def f2(): # 验证1 # 验证2 # 验证3 过了一周B也被开除了。。。。。。。。。。
老大又把工作交给C,他是这么做的:def check_login() # 验证1 # 验证2 # 验证3 def f1(): check_login() def f2(): check_login()
老大说写代码要遵循开放封闭的原则,虽然在这个原则是用的面向对象开发,但是也适用于函数式编程,简单来说,已经实现的功能不允许修改,但可以被扩展 。封闭:已实现的功能代码块开放:对扩展开发老大给出了方案, def foo(): def inner(): 验证1 验证2 验证3 result = func() return result return inner @foo def f1(): pass @foo def f2(): pass
看不懂?没关系,接下来写一个简单点的def w1(func): def inner(): print('正在验证权限') func() return inner def f1(): print('f1') innerFunc = w1(f1) # innerFunc = inner innerFunc() # inner() f1 = w1(f1) f1() def outer(func): def inner(): print("认证成功!") result = func() print("日志添加成功") return inner @outer # f1 = outer(f1) = inner def f1(): print("业务部门1数据接口......") f1() 结果: 正在验证权限 f1 正在验证权限 f1 认证成功! 业务部门1数据接口...... 日志添加成功 1 程序开始运行,从上往下解释,读到def outer(func):的时候,发现这是个“一等公民”函数,于是把 函数体加载到内存里,然后过。 2 读到@outer的时候,程序被@这个语法糖吸引住了,知道这是个装饰器,按规矩要立即执行的,于是程序 开始运行@后面那个名字outer所定义的函数。 3 程序返回到outer函数,开始执行装饰器的语法规则。 规则是:被装饰的函数的名字会被当作参数传递给装饰函数。装饰函数执行它自己内部的代码后,会将它的 返回值赋值给被装饰的函数。原来的f1函数被当做参数传递给了func,而f1这个函数名之后会指向inner 函数