标签:类对象 地址映射 表达 math 传值 出现 名称 开发 作用
一. 人生三问
1. 什么是函数
函数就是用def关键字声明的为了实现一组功能的代码块。 2. 为什么要用函数
在开发程序的过程中,我们可能会遇到一些相同的功能,为了避免写重复的代码,从而出现了函数。 3. 怎么使用函数
函数分为定义和调用两个阶段,函数名()就是调用函数的过程
# 函数的定义
def fun1(x, y, z):
‘‘‘注释‘‘‘
code1
code2
return x, y, z
# 函数调用
fun1(1, 2, 3)
二. 函数的使用原则
# 函数在调用过程中必须要先定义才能进行使用
1. 函数的定义阶段
只检测函数体中是否存在语法错误 2. 函数的调用阶段
调用过程才会去真正的执行代码块,查看是否有逻辑错误
测试:
def fun1(): print(‘from fun1‘) bar() # 当执行fun1代码的时候发现要执行bar # 但是bar函数还没有定义,所以报错 fun1() def bar(): print(‘from bar‘)
1. 函数的三种定义方式
1. 无参函数 2. 有参函数 3. 空函数
2. 函数的三种调用方式
1. 语句的形式 =====》 register() 2. 表达式调用========》 res = register() * 12 3. 作为参数传递调用 ===========》
3. return的特点
功能 1. 可以返回值 1.1 函数的返回值没有类型的限制 1.2 函数的返回值没有个数的限制
<1>.返回的是一个值就是函数本身
<2>.返回多个值就是元祖
<3>.返回0个值或者干脆没有就返回None
2. 可以结束函数的执行 函数内可以有多个return,只要执行了任意一个return函数就结束了
三. 参数详解
参数的分类:
1. 形式参数(形参)
在函数定义阶段,传递的参数就是形参 2. 实际参数(实参)
在函数调用阶段,传递的参数就是实参
细分:
1. 位置参数
2. 关键字参数(默认形参)
3. 可变长参数
# 这个是函数的定义阶段 # 里面的参数x, y, z是函数的形参 def fun(x, y, z): print(‘hhhh‘) # 这个是函数的调用阶段 # 里面的参数1,2,3是实参 fun(1, 2, 3)
1. 位置参数
位置参数:
1. 位置实参
在调用阶段,按照从左到右的顺序依次定义的参数叫做位置实参
# 特点:与形参的值一一对应
2. 位置形参
在定义阶段,按照从左到右的顺序依次定义的参数叫做位置形参
# 特点:必须被传值,多一个不行,少一个不行
验证:
# 形参和实参的值必须一一对应 def fun1(x, y, z): print(x, y, z) fun1(1) # 会报错 fun1(1, 2, 3) fun1(1, 2, 3, 4) # 会报错
2. 关键字参数
1. 关键字实参 在函数调用阶段,按照key=value的形式定义的实参叫做关键字实参 # 特点:
# 1. 关键字实参必须放在位置实参的后面
# 2. 不能给同一个形参赋多个值
2. 关键字形参(默认形参) 在函数定义阶段,按照key=value的形式定义的形参叫做关键字形参。我们一般称之位默认形参
# 特点:
# 1. 在定义阶段已经有值,意味着在调用阶段可以不用传值
# 2. 位置形参必须放在默认形参的前面
# 3. 默认形参的值在定义阶段已经固定死了,之后的更改不会影响
# 4. 默认形参的值通常应该是不可变类型
验证:关键字参数
# 关键字参数必须放在位置参数的后面 def fun1(x, y, z): print(x, y, z) fun1(1, y=2, 3) # 报错 fun1(1, 2, z=3)
# 不能给同一个形参传递多个值 def fun1(x, y, z): print(x, y, z) fun1(1, 2, 3, x=1)# 会报错
验证:默认形参
# 调用阶段可以不用传值 def func1(x, y, z=2): print(x, y, z) func1(1, 2)
# 位置形参必须在默认形参之前 def func1(x,z=2, y):# 会报错 print(x, y, z) func1(1, 2)
# 默认形参的值在定义阶段已经固定死了 m = 10 def func1(x, y, z = m): print(x, y, z) m = 100 func1(1, 2) # 答案依然是10
# 默认形参通常应该是不可变类型 # 以下例子的耦合性非常高 m = [] def fun1(x, y, z = m): z.append(x) z.append(y) print(z) fun1(1,2) fun1(3,4) fun1(5,6) print(m) # 结果: # [1, 2] # [1, 2, 3, 4] # [1, 2, 3, 4, 5, 6] # [1, 2, 3, 4, 5, 6]
3. 可变长参数
1. 可变长实参 在函数调用阶段,实参值的个数是不固定的。 2. 可变长形参 在函数定义阶段,形参值的个数是不固定的。
可变长形参
* ====》会将溢出的位置实参存到一个元祖中,然后赋值给*后面的形参中
** =====》会将溢出的关键字实参以key和value的形式存成字典,然后赋值给**后面的形参中
可变长实参
* ========》会将*后面的值打散成一个个的位置实参,然后与形参一一对应
** ========》会将**后面的值以key=value的形式打散成一个个的关键字参数,然后与形参一一对应
(1) 多出来的位置实参赋值给*args
def fun(x, y, *args): # args=(3, 4, 5,6) print(x, y, args) fun(1, 2, 3, 4, 5, 6)# 多出来3,4,5,6四个位置实参
(2)任意数求和:
# 任意数求和 def sum2(*args): # args=(1,2) res = 0 for i in args: res += i return res res = sum2(1, 2,3) print(res)
(3)形参和实参的对应关系
def fun(x,y,*z):# z = (1,2,3,4 ) print(x, y, z) fun(11,22,*[1, 2,3,4]) # fun(11, 22, 1,2,3,4)
(4)*args, **kwargs的应用
# *args,**kwargs可以被当作参数传递
def index(name, age, sex): print(name, age, sex) def wrapper(*args, **kwargs): # args = (‘egon‘) # kwargs = {‘sex‘: ‘male‘, ‘agse‘: 18} index(*args, **kwargs)# index(‘egon‘, sex=‘male‘, agse=18) wrapper(‘egon‘,sex=‘male‘, age=‘18‘)
4. 命名关键字参数
关键字参数: 在*和**之间的定义的参数称为命名关键字参数 关键字参数: 命名关键字参数必须按照key=value的形式进行传值
# 在*号后面的形参在实参传递的过程中必须是关键字参数 def fun(x, *, y, z): print(x, y, z) fun(1, y=2, z=3)
四. 函数对象
函数对象:
函数是第一类对象:函数的内存地址可以像一个变量值一样去使用
变量值的使用方法:
1. 可以被引用
a = 1
b = a
2. 可以当作参数传递
3. 可以作为返回值
4. 可以当作容器内的元素
1. 函数被引用
def f1(): print(‘from f1‘) f = f1 f1 = f f() f1()
2. 可以被当作参数进行传递
def f1(func): func() def f2(): print(‘from f2‘) f1(f2)
3. 可以作为返回值
def f1(func): return func def f2(): print(‘from f2‘) f1(f2)()
4. 作为容器内的元素
作为功能字典使用:
def login(): print(‘login.....‘) def register(): print(‘register.....‘) func_dict = {‘1‘: login, ‘2‘: register} choice = input(‘>>‘).strip() if choice in func_dict: func_dict[choice]() else: print(‘wrong!‘)
五. 函数嵌套
函数嵌套的两种类型 1. 函数的嵌套调用 2. 函数的嵌套定义
1. 函数的嵌套调用
# 函数的嵌套调用就是把一个复杂的功能拆分成 # 更小的功能,然后去调用它来解决问题 def max2(a, b): if a > b: return a else: return b def max4(a,b,c,d): res = max(a, b) res = max(res,c) res = max(res, d) return res print(max4(1, 2, 3, 4))
2. 函数的嵌套定义
# 从这个例子可以看出来,函数的嵌套声明可以把一类函数 # 打包到一块,然后通过传入一个参数执行不同的函数 from math import pi def circle(banjing, choice): ‘‘‘choice == 1计算周长,其他的计算面积‘‘‘ def zhouchang(): return banjing * 2 * pi def mianji(): return pi * banjing ** 2 if choice == ‘1‘: res = zhouchang() else: res = mianji() return res
六. 名称空间
名称空间
名称空间就是python的一个专门用来存储名字和值的内存地址映射关系的一个空间。
名称空间的分类
1. 内置名称空间
2. 全局名称空间
3. 本地名称空间
内置名称空间:
存放的名字:存放的是python解释器自带的名字
产生:打开python解释器的时候会产生
销毁:关闭python解释器的时候会销毁
全局名称空间:
存放的名字:存放的是顶格写入的p名字
产生:在执行python文件的时候会产生
销毁:在python文件执行完毕之后销毁
局部名称空间:
存放的名字:存放的是函数内的名字
产生:在执行函数代码体的时候会产生
销毁:在函数执行完毕之后会销毁
名称空间的加载顺序: 内置名称空间----》全局名称空间-------》局部名称空间
名称空间的销毁顺序: 局部名称空间----》全局名称空间-------》内置名称空间
名称空间的查找顺序: 从当前名称空间一层一层往上查找
七. 作用域
作用域: 作用域其实就是把名称空间分成了两大类 1. 全局作用域: 内置名称空间和全局名称空间的名称
特点: 全局存活,全局有效 2. 局部作用域: 局部名称空间的名称
特点: 临时存活,局部有效
作用域关系在函数定义阶段已经定义死了,与调用的位置无关:
# 例一:作用域关系在定义阶段已经定义死了 xxx = 2 def f1(): print(xxx) xxx = 1 # 此时函数执行的时候是会报错的 # 原因:当定义函数f1的时候发现局部命名空间中是有xxx这个变量的 # 因此无论什么时候调用f1函数都会使用局部命名空间,因此在调用 # f1()函数的时候,执行print(xxx)中的xxx的时候,发现局部名称空间 # 目前还没有这个变量,因此会报错。 f1()
八. 闭包函数
闭包函数运用的知识: 函数嵌套: 闭包函数就是在一个函数外面包上一层函数 函数对象: 会返回内部函数的内存地址 作用域关系:会传递值给内部函数进行使用
# 创建了一个闭包函数innter def outter(): x = 1 def innter(): # 函数的嵌套 print(‘from inner‘, x) # 函数的作用域关系 return innter # 函数的对象
什么是闭包函数呢?
闭包函数本质上就是一个函数的嵌套。在嵌套的过程中会牵涉到函数的作用域关系。应用广泛的是装饰器。
标签:类对象 地址映射 表达 math 传值 出现 名称 开发 作用
原文地址:https://www.cnblogs.com/huwentao/p/9783202.html