Python函数编程
⼀函数的介绍和基本使⽤
为什么要使⽤函数?
避免代码重⽤
提⾼代码的可读性
函数的定义与调⽤
def 函数名(参数1,参数2)
''' 函数注释'''
print('函数体')
return 返回值
定义:def关键字开头,空格之后接函数名和圆括号,最后还要加⼀个冒号。
函数名:函数名是包含字母,数字,下划线的任意组合,但是不能以数字开头。虽然函数名可以随便取名,但是⼀般尽量定义成可以表⽰函数功能的。
函数的返回值
return的作⽤:结束⼀个函数的执⾏
⾸先返回值可以是任意的数据类型。
函数可以有返回值:如果有返回值,必须要⽤变量接收才有效果
没有返回值的时候分三种情况:
当不写return的时候,函数的返回值为None
当只写⼀个return的时候,函数的返回值为None
return None的时候,函数的返回值为None(⼏乎不⽤)
return返回⼀个值(⼀个变量)
return返回多个值(多个变量):多个值之间⽤逗号隔开,以元组的形式返回。
接收:可以⽤⼀个变量接收,也可以⽤多个变量接收,返回⼏个就⽤⼏个变量去接收
函数的参数
def fun(s):#参数接受:形式参数,简称形参
'''
计算字符串长度的函数---------函数的功能
参数s:接受要计算的字符串--------参数的信息
return:要计算字符串长度 ---------返回值得信息
'''
length=0
for i in s:
length+=1
return length
ret=fun('helloword')#参数传⼊:实际参数,简称实参
print(ret)
实参和形参
形参:是函数定义时候定义的参数
实参:函数调⽤的时候传进来的参数
传递多个参数
可以传递多个参数,多个参数之间⽤逗号隔开。
站在传参的⾓度上,调⽤函数时传参数有两种⽅式:
按照位置传参数
按照关键字传参数
动态参数
按位置传值多余的参数都由args统⼀接收,保存成⼀个元组的形式
按关键字传值接受多个关键字参数,由kwargs接收,保存成⼀个典的形式
args:
def fun(a,b,*args):
sum=a+b
for i in args:
sum+=i
return sum
print(fun(1,5,6,4))#输出1+5+6+4的和
kwargs:
def fun(a,b,**kwargs):
print(a,b,kwargs)
# 按照关键字传参数
fun(a = 10,b = 20,cccc= 30,dddd = 50)#输出10 20 {'cccc': 30, 'dddd': 50}
def f(a,b,*args,defult=6,**kwargs):
#位置参数,*args, 默认参数,**kwargs
# print(a,b,args,defult,kwargs)
return a,b,args,defult,kwargs
#传参数的时候:必须先按照位置传参数,再按照关键字传参数
print(f(1,2,7,8,ccc=10,der=5))
⼆函数嵌套及作⽤域链
1 函数命名空间
全局命名空间:创建的存储“变量名与值的关系”的空间叫做全局命名空间
局部命名空间:在函数的运⾏中开辟的临时的空间叫做局部命名空间
内置命名空间:内置命名空间中存放了python解释器为我们提供的名字:input,print,str,它们都是我们熟悉的,拿过来就可以⽤的⽅法。
三种命名空间之间的加载顺序和取值顺序:
加载顺序:内置(程序运⾏前加载)-->全局(从上到下顺序加载进来的)-->局部(调⽤的时候加载)--->内置
取值:在局部调⽤:局部命名空间--->全局命名空间--->内置命名空间
2 作⽤域:就是作⽤范围
命名空间和作⽤域是分不开的
作⽤域分为两种:
全局作⽤域:全局命名空间与内置命名空间的名字都属于全局范围,在整个⽂件的任意位置都能被引⽤,全局有效
局部作⽤域:局部命名空间,只能在局部范围内⽣效
站在全局看:
使⽤名字的时候:如果全局有,⽤全局的
如果全局没有,⽤内置的
globals⽅法:查看全局作⽤域的名字【print(globals())】
locals⽅法:查看局部作⽤域的名字【print(locals())】
在函数内部创
global name
name = 'hahha'
3 闭包
闭:内部的函数
包:包含了对外部函数作⽤域中变量的引⽤
闭包的定义:如果在⼀个函数⾥,对在外部作⽤域(但不是全局作⽤域)的变量进⾏引⽤,内部函数就被认为是闭包
闭包=函数块(内部函数)+定义函数时的环境
def outer():
x = 10
def inner(): #条件1 inner就是内部函数
x =20
print(x) #条件2 外部环境的⼀个变量
return inner
# outer()()
f = outer() # 返回的是inner的内存地址
print(f)
f()
三嵌套,匿名和⾼阶函数
1 嵌套函数
函数⾥不仅可以写代码, 还可以嵌套函数
name = "harry"
def change():
name = "caishuang_harry"
def change2():
name = "harry0000"
print("第三层打印", name)
change2() # 调⽤内层函数
print("第⼆层打印", name)
change()
print("最外层打印", name)
输出结果:
第三层打印 harry0000
第⼆层打印 caishuang_harry
最外层打印 harry
2 匿名函数
匿名函数就是不需要显⽰的指定函数名
# 这段代码
def calc(x,y):
return x**y
# 换成匿名函数
calc = lambda x,y:x**y
print(calc(2,5))
匿名函数结合map处理数据
res = map(lambda x:x**2,[1,5,7,4,8])
3 ⾼阶函数
将⼀个函数作为参数传⼊另外⼀个函数
def get_abs(n):
return int(str(n).strip("-"))
def add(x, y, f):
return f(x) + f(y)
print(add(5, -10, get_abs))
四递归函数
1 递归的定义
什么是递归:在⼀个函数⾥在调⽤这个函数本⾝
最⼤递归层数做了⼀个限制:997,但是也可以⾃⼰限制
最⼤层数限制是python默认的,可以做修改,但是不建议你修改。(因为如果⽤997层递归都没有解决的问题要么是不适合使⽤递归来解决问题,要么就是你的代码太烂了)
结束递归的标志:return
递归解决的问题就是通过参数,来控制每⼀次调⽤缩⼩计算的规模
使⽤场景:数据的规模在减少,但是解决问题的思路没有改变
2 递归的特性
必须有⼀个明确的结束条件
没次进⼊更深⼀层递归时,问题规模相⽐上次递归都应有所减少
递归效率不⾼, 递归层次过多会导致栈溢出
3 递归函数实现斐波那契数列
def fib(n):
print("-----",n)
if n==1:
return 1
elif n==2:
return 1
else:
return fib(n-1)+fib(n-2)
print(fib(5))
4 迭代器实现阶乘
def fact(n):
if n==1:
return 1
return n*fact(n-1)
print(fact(5))
五装饰器
1 为什么要使⽤装饰器呢?
装饰器的功能:在不修改原函数及其调⽤⽅式的情况下对原函数功能进⾏扩展
装饰器的本质:就是⼀个闭包函数
字符串函数是什么函数2 装饰器实现代码运⾏时间统计
import time
def warp(func):
def inner():
start_time = time.time()
func()
end_time = time.time()
print('执⾏%s' % str(float(end_time) - float(start_time)))
return inner
@warp
def foo():
time.sleep(2)
print('haha')
@warp
def bar():
time.sleep(3)
print('hehe')
foo()
bar()
3 带参数的装饰器
当加了很多装饰器的时候,现在忽然⼜不想加装饰器了,想把装饰器给去掉了,但是那么多的代码,⼀个⼀个的去闲的⿇烦,那么,我们可以利⽤带参数的装饰器去装饰它,这就他就像⼀个开关⼀样,要的时候就调⽤了,不⽤的时候就去掉了。
给装饰器⾥⾯传个参数,那么那个语法糖也要带个括号。在语法糖的括号内传参。在这⾥,我们可以⽤三层嵌套,弄⼀个标识为去标识
def warpper(f):
def inner (a,b):
f(a,b)
print("inner")
return inner
@warpper
def foo (a,b):
print(a+b)
foo(1,2)
# 嵌套三层函数
# 带参数的装饰器:(相当于开关)为了给装饰器传参
# F=True#为True时就把装饰器给加上了
F=False#为False时就把装饰器给去掉了
def outer(flag):
def wrapper(func):
def inner(*args,**kwargs):
if flag:
print('before')
ret=func(*args,**kwargs)
print('after')
else:
ret = func(*args, **kwargs)
return ret
return inner
return wrapper
@outer(F)#@wrapper
def hahaha():
print('hahaha')
@outer(F)
def shuangwaiwai():
print('shuangwaiwai')
hahaha()
shuangwaiwai()
4 多个装饰器装饰⼀个函数
def foo(fun):
def inner(*args,**kwargs):
print('in foo(: before')
ret = fun(*args,**kwargs)
print('in foo(: after')
return ret
return inner
def bar(fun):
def inner(*args,**kwargs):
print('in bar: before')
ret = fun(*args,**kwargs)
print('in bar: after')
return ret
return inner
@foo
@bar
def fun():
print('饿了吗')
fun()
'''
@foo和@bar的执⾏顺序:先执⾏foo⾥⾯的 print('in foo: before'),然后跳到了bar⾥⾯的
print('in bar: before')
ret = fun(*args,**kwargs)
print('in bar: after'),完了⼜回到了foo⾥⾯的 print('in foo: after')。
'''
六迭代器和⽣成器
1 什么是⽣成器
通过列表⽣成式,我们可以直接创建⼀个列表。但是,受到内存限制,列表容量肯定是有限的。⽽且,创建⼀个包含100万个元素的列表,不仅占⽤很⼤的存储空间,如果我们仅仅需要访问前⾯⼏个元素,那后⾯绝⼤多数元素占⽤的空间都⽩⽩浪费了。
所以⽣成器就出现了,他弥补了直接⽣成⼤列表的不⾜,改成为定义某种计算过程,然后在需要的时候进⾏计算后得出想要的结果,从⽽节省了⼤量的内存空间。这就是⽣成器:generator
如果列表元素可以按照某种算法推算出来那么就可以在循环的过程中不断推算后续的元素
2 创建⼀个⽣成器
#⽣成器不会将数据直接存⼊内存,⽽是在调⽤时才会⽣成数据加载到内存当中
#⽣成器就是⼀个可迭代对象
#⽣成器⼀共有两种创建⽅式 1 是通过()的⽅式 2 是通过yield
# s=(i*2 for i in range(1,1000))
# print(s)
# print(next(s)) #等价于s.__next__() in ()
# print(next(s))
#
# for i in s:
# print(i)
def foo():
print('ok')
yield 1
g=foo()
next(g)
#可迭代对象⼀般可以是字典列表迭代器⽣成器,对象⼀般有___iter___⽅法
3 ⽣成器推算斐波那契
# 不使⽤⽣成器
def fib(max):
n,before,after=0,0,1
while n < max:
print(before)
before,after=after,before+after
n+=1
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论