13 函数

函数

函数是盛放一系类代码功能的容器,先定义后调用

使用函数的好处
1.提高组织结构清晰,增强可读性
3.可重复使用,减少相同代码的重复
2.可扩展性提高

函数的两个阶段

定义阶段:申请内存空间将函数体放进去,将内存地址绑定给函数名 
调用阶段: 通过函数名等到函数体的地址
定义阶段时只检测语法不执行代码,调用阶段才会执行函数体逻辑错误才会被检查到。
def 函数名(参数1,参数2):  函数名一般是动词    # 定义阶段  下面所有缩进的代码都是函数体
    """
   为函数添加说明说明
    """
    
    代码1...
    代码2...
    
    return 值

函数名(参数1,参数2#  调用阶段

# 定义检测语言
def aa():
	qwe     #  没有定义qwe是什么,但语法上没有错误
            #  运行程序 进程已结束,退出代码为 0   
# 调用时翻译代码并执行
aa()     
#  NameError: name 'qwe' is not define
#  没有定义 qwe 逻辑错误  不调用就不会出错,一调用就出错

函数名指向函数体的内存地址

print(变量名)------> 被处理 ----- 显示内存地址存放的值 不能在加()
print(函数名)------> 没处理 ------ 显示值所在内存的地址 加()进行处理
函数名—>内存地址 + ()----> 函数可以加括号是语法定义的,找到内存地址处理代码得到结果

def aa():
    print(1)
    
print(aa)   # <function aa at 0x00000000012F70D0>

将函数内存地址引用给其他变量

def aa():
    print(1)
    
bb = aa     # 内存地址给 bb 这是一个没有被处理的程序
bb()        # 加上括号,找到内存地址处理代码得到结果
       # 显示为 1

函数的 参数 与 返回值取 取决于是否需要对函数传入值,和需要返回值。
定义函数的三种类型

# 无参    -------->   不需要传入值
def aa():
    x = 10
    y = 10
    print(x + y)  
         

# 有参    -------->   需要传入值
def bb(x,y):
    print(x + y)
    
bb(10, 10)


# 空函数
def cc():
    pass      # 第一种, 兼容python 2

def dd():
	...      # 第二种

调用函数的三种格式

def aa():
	return 123

aa()               # 直接调用
res = aa() * 10    # 表达式
print(aa( ))       # 作为其他函数的参数

返回值 return

一个函数中可以有多个return,只要执行一次,立刻结束当前所在函数,并将return 后的值设置为函数的返回值

1.return#  返回单个值
2.return1,值2,值3                              #  返回多个值(元组类型)
3.returnreturn None 或 不写                     #  没有返回值,默认返回为None
#  返回单个值
def aa():
    return 1

print(aa())            # 1

#  返回多个值(元组类型)
def aa():
    return 1, 2, 3

print(aa())            # (1, 2, 3)

# 没有返回值,默认返回为None
def aa():
	return   

print(aa())  # None

# 不写return 
def aa():
	pass    

print(aa())  # None

# 返回值 赋值给 变量
def ee():
    return 1, 2, 3

num1, num2, num3 = ee()   # 解压赋值
# return 结束当前函数
def aa():
    return
	print(666)	

def bb():
    aa()
    print(123)

bb()   # 123

参数类型提示功能

函数的参数可以是任意类型但是,但传入的值不符合要求,就会报错
参数设置提示,:参数提示 -> 返回值提示
def 函数名 (参数1:int, 参数2:‘必须传入字符串’)-> “返回值是整型”

def aa(x: '传入字符串', y: '传入整型') -> '返回值为字符串':
    z = x * y
    return z

print(aa('asd', 5))

提示简单明了,修改后:

def aa(x:str, y: int) -> str
    z = x * y
    return z

print(aa('asd', 5))

实参 与 形参

形参:函数定义阶段,括号内指定的参数(变量名)
实参:函数调用阶段,括号内传入的值 (变量值)

函数调用阶段 —> 实参值绑定给形参名,函数调用完毕 ----> 解除绑定

def aa(x, y):  #  x, y   是形参
    z = x + y

aa(10, 20)     #  10, 20 是实参

a = 10
b = 20
aa(a, b)       #  a, b   是实参

位置形参 与 位置实参

定义函数阶段,按照从左到右的顺序依次定义的形参,称为位置参数
特点:形参必须被传值

在函数调用阶段,按照从左到右的顺序依次穿入的值,称为位置实参
特点:按顺序依次为形参赋值
def aa(x, y, z):    # (不能多,不能少,一个萝卜一个坑)
    print(x, y, z)
 
aa(1, 2, 3)         # 实参的长度与形参相匹配
aa(3, 2, 1)

关键字实参

​ 在函数调用阶段,按key = value 的格式传入值,称为关键字实参
​ 特点:不用记住形参的顺序,可打乱顺序赋值

def bb(x, y, z):           # 指定赋值
    print(x, y, z)
   
bb(x=1,z=3,y=2)            # 顺序可乱
bb(z=3,x=1,y=2)            

位置实参与关键字实参在一起混用时:
1.关键字实参不能位置参数前
2.不能为同一个形参多次赋值

def aa(x, y, z):
    print(x, y, z)

aa(x=1, 2, z=3)     # 关键字 在 位置实参 前面
# SyntaxError: positional argument follows keyword argument
def aa(x, y, z):
    print(x, y, z)

aa(1, 2, 3, z=3)   # z 被赋值两次
# TypeError: aa() got multiple values for argument 'z'

默认形参

在函数定义阶段,为形参赋值,称为默认形参,如果传值,以实参值为准。
特点:定义阶段已经为形参赋值,在调用阶段可以不用为其传值

位置形参和默认形参混用
1.位置形参在前,位置实参在后面
2.默认形参只在函数定义阶段赋值一次
3.默认形参的值推荐指向不可变类型

def aa(x, y=2, z=3):
    print(x, y, z)

aa(1)                   #  1 2 3
aa(1, 5, 6)             #  1 5 6
aa()                    # 第一次调用函数,创建一个空列表,1被添加进y的列表内     [1]
aa()            	    # 第二次调用函数,不在创建空列表,1被添加进原来的列表内  [1, 1]
aa()                    # 第三次调用函数,不在创建空列表,1被添加进原来的列表内  [1, 1, 1]


x = 100                 # 申请一个内存空间   把值100放进去  绑定给 变量名 x
y = x                   # 将x 的内存空间地址给 y 引用   x y 同时指向 内存地址
x = 200                 # 申请一个内存空间   把值200放进去  绑定给 变量名 x , 原来的绑定断开
print(y)                # y 不受影响

a = [1, 2, 3]           # 申请一个内存空间   把值[1, 2, 3]放进去  绑定给 变量名 a
b = a                   # 将a 的内存空间地址给 b 引用   a b 同时指向 内存地址
a = 200                 # 申请一个内存空间   把值200放进去  绑定给 变量名 a , 原来的绑定断开
print(b)                # b 不受影响

k = [1, 2, 3]           # 申请一个内存空间   把值[1, 2, 3]放进去  绑定给 变量名 k
v = k                   # 将k 的内存空间地址给 v 引用   k v 同时指向 内存地址
k.append(200)           # 在内存空间   把值200放进去
print(v)                # b 受影响影响

# 一个使用场景,利用在不对z传值的情况下的利用
def aa(x, y, z=123):    # z 值不变
    if z == 123:        # 每次都为123
        z = {}          # 在将{}空字典赋值给z
    z[x] = y
    print(z)

aa('西瓜', 5)           # {'西瓜': 5}
aa('香蕉', 4.5)         # {'香蕉': 4.5}

可变长参数 * 与 **

在位置形参中带 * : * 将溢出的位置实参汇总成元组,赋值给紧跟其后的变量

def aa(x, *y):
    print(x, y)

aa(1)        # 1 ()     没有溢出就输出空元组
aa(1, 2)     # 1 (2,)   
aa(1, 2, 3)  # 1 (2, 3)

在关键字形参中带 * *: ** 将溢出的位置实参汇总成字典,赋值给紧跟其后的变量

# 实参与形参值长度相等
def aa(x, **y):      # 字典是无序的
    print(x, y)

aa(1)                # 1 {}
aa(1, a=1, b=2)      # 1 {'a': 1, 'b': 2}

在实参中带* :* 能被for循环的 字符串 ,元组,列表等都使用

# 实参与形参值长度相等

def aa(x, y, z):
    print(x, y, z)

aa(*[1, 2, 3])   # 1 2 3   
aa(*'qwe')       # q w e

在关实参中带 * *: ** key=value 类型

# 实参与形参值长度相等
def aa(x, y, z):
    print(x, y, z)  

aa(**{'x': 5, 'y': 4.5, 'z': 5.2})

混用

通常,将 * 赋值给 args
将 * * 赋值 给 kwargs

参数的长度 指定着 参数的个数 长度固定
可变长参数的长度不可以固定

# 位置形参 几乎用不上
def num(x, *y, z):     # *y 后面的z 就不能能是位置形参,z在这为位置形参
    print(x, y, z)     # 通过位置实参,赋值给 z

num(10, 20, z=11)      # 10 (20,) 11

混用,位置实参*args在前,位置实参 **kwargs 在后

def num(x, *y, **z):
    print(x, y, z)

num(10, 20, **{'z': 1})

接收任意长度的的参数

def num(*x, **y):
    x1, x2 = x               # 元组的值解压给 x1 x2
    y1, y2 = y.values()      # 字典的值解压复制给 y1 y2
    print(x1, x2, y1, y2)    # 10 20 30 40

num(10, 20, **{'y': 30, 'a': 40})
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值