python函数基础
函数的基本使用
1、什么是函数
ps:函数就是盛放代码的容器 具备某一功能的工具 ---> 函数 事先准备工具的过程 ---> 函数的定义 遇到应用场景拿来就用 ---> 函数的调用 所以函数的使用原则: 先定义 后调用
2、为何要用函数
解决下述问题: 1、代码组织结构不清晰,可读性差 2、可扩展性差
3、如何用函数
定义的语法
def 函数名(参数1,参数2,...): """文档描述""" 函数体 return 返回值 1、def:定义函数的关键字 2、函数名:函数名指的是函数内存地址,是对函数体代码的引用。函数的命名应该反映出函数的功能 3、括号:括号内定义参数,参数是可有可无的,且无需指定参数的类型 4、冒号:括号后面要加冒号,然后在下一行开始缩进编写函数体的代码 5、''''文档描述''':描述函数功能,参数介绍等信息的文档,非必要,但是建议加上,从而增强函数的可读性 6、函数体:由语句和表达式组成 7、return 返回值:定义函数的返回值,return是可有可无的,不一定要加在最后一行
调用的语法
函数的调用 1、先找到名字 2、根据名字调用代
一、定义函数
定义函数发生的事情
1、申请内存空间把函数体代码放进去 2、将函数内存地址绑定给函数名 强调:定义函数只检测语法,不执行代码
def login(): # login = 函数的内存地址 print(111) print(222) print(333) print(login) >>>: <function login at 0x000002193ECEC1F0>
二、调用函数
调用函数发生的事情
1、先通过函数名定位到函数内存地址 2、函数内存地址() ---> 触发函数体代码的运行 强调:调用函数才会执行函数体代码
login() # >>>: # 111 # 222 # 333
三、定义函数的三种形式
无参
def func(): print('hello world')
有参
def max2(x,y): if x > y: print(x) else: print(y) max2(10,20) # 20
空
def login(): pass # pass代表什么都不做 # ...
四、调用函数的三种方式
语句
len('hello')
表达式
res = len('hello') * 10 print(res) # 50
可以当做一个参数传给另一个参数
print(len('hello')) # 5
函数的参数
形参
在函数定义阶段括号内指定的参数,称之为形式参数,简称形参
位置形参
在定义函数时,按照从左到右的顺序依次定义的变量名,称之为位置形参 特点:每次调用,必须被赋值 def func(x,y): print(x) print(y) func(1,2)
默认形参
在定义函数时,就已经为某个形参赋值了,称之为默认形参 特点:调用函数时,可以不用为其赋值 def func(name,age=18): print(name) print(age) func('egon') >>>: egon 18
注意
注意:可以混用位置形参与默认形参,但是: 1、位置形参必须在前面 2、默认形参的值,通常应该是不可变类型 3、默认形参的值是在函数定义阶段赋值的
实参
在函数调用阶段括号内传入的值,称之为实际参数,简称实参
位置实参
在调用函数时,按照从左到右的顺序依次传入的值,称之为位置实参 特点:按照位置为形参赋值,一一对应 func(1,2) # 1 2 func(2,1) # 2 1
关键字实参
在调用函数时,按照key=value的形式传值,称之为关键字实参 特点:可以大乱顺序,但是仍然能够指名道姓的为指定的形参赋值 def func(name,age): print(name) print(age) func(age=18,name='egon') >>>: egon 18
注意
可以混用位置实参与关键字实参,但是: 1、位置实参必须在关键字实参的前面 2、不能为同一形参重复赋值
形参与实参的关系
在调用函数时,实参值会绑定给形参名,在函数调用完毕之后解除绑定
# 形参 def func(x,y): # x = 111 # y = 222 print(x,y) # 实参 m = 111 n = 222 func(111,222)
可变长系列
详情参见:https://www.cnblogs.com/ZhZhang12138/p/14200978.html#hanshudefanhuizhi 可变长参数指的是在调用函数时,传入的实参个数不固定,对应着必须有特殊形式的形参来接收移除实参 实参无非两种形式 溢出的位置实参 ---> * 溢出的位置关键字实参 ---> **
函数的返回值
return详解
1、函数可以有多个return,但只要执行一次return,整个函数就立即结束,并且将return后的值当做本次调用的结果返回
2、return后返回值有三种情况 (1)return 值:返回的就是这一个值 (2)return 值1,值2,值3:返回的是一个元组 (3)函数内可以没有return、或者return None、或者return:默认返回None
函数对象
在python中,函数时第一类对象,函数是第一等公民
本质:函数可以当变量使用
函数对象指的是函数可以被当做’数据’来处理,具体可以分为四个方面的使用,如下 def func(): # func = 函数的内存地址 print('from func') # # 1、可以赋值 f = func print(f) f() # 2、可以当做参数传给另外一个函数 def foo(x): print(x) foo(func) # <function func at 0x000001FF3854C1F0> # 3、可以当做函数的返回值 def foo(x): return x res = foo(func) print(res) # <function func at 0x000001F48080C1F0> # 4、可以当做容器类型的元素 l = [func,] print(l) # [<function func at 0x000001F132A5C1F0>] l[0]() # from func
函数的嵌套
函数的嵌套调用
def ma2(x,y): if x > y: return x else: return y def max4(a,b,c,d): res1 = ma2(a,b) res2 = ma2(res1,c) res3 = ma2(res2,d) return res3 print(max4(11,99,33,12)) # 99
函数的嵌套定义
def f1(): x = 10 def f2(): print(x) print(x) print(f2) f1() >>>: 10 <function f1.<locals>.f2 at 0x00000255051DA0D0>
名称空间与作用域
名称空间与作用域的关系是在函数定义阶段(扫描语法时)就确立的,与什么时候调用以及调用位置无关
namespace名称空间:存放名字的地方
内置名称空间:存放内置的名字 生命周期:python解释器启动则产生,关闭则销毁 全局名称空间:存放的是顶级的名字 生命周期:运行python文件时则产生,python文件运行完毕则销毁 局部名称空间:存放的是函数内的名字 生命周期:调用函数则产生,函数调用完毕则销毁 核心:名字的访问优先级: 基于当前所在的位置向外查找 函数内 ---> 外层函数 ---> ... ---> 全局 ---> 内置 LEGB L:内置 E:外层函数 G:全局 B:内置
作用域
全局作用域:内置名称空间+全局名称空间
特点:全局存活,全局有效
局部作用域:局部名称空间
特点:临时存活,局部有效
在函数内,无论嵌套多少层,都可以查看到全局作用域的名字,若要在函数内修改全局名称空间中名字的值,当值为不可变类型时,则需要用到global关键字
# 案例一: l = [] def func(): l.append(111) # l = [11,22,33] # 定义了一个新列表,与全局无关 func() print(l) # [111] # 案例二: x = 111 def func(): global x x = 222 func() print(x) # 222
对于嵌套多层的函数,使用nonlocal关键字可以将名字声明为来自外部嵌套函数定义的作用域(非全局) def f1(): x = 2 def f2(): nonlocal x # 声明变量名是来自于外层函数的,不是全局 x = 3 f2() # 调用f2(),修改f1作用域中名字x的值 print(x) #在f1作用域查看x f1()