AI智能
改变未来

day008|python之函数


函数

[TOC]

1 Type hinting

# Type hintingdef add(x: int, y: int) -> int:res = x + yreturn resprint(add.__annotations__)# {\'x\': <class \'int\'>, \'y\': <class \'int\'>, \'return\': <class \'int\'>}

2 函数参数

2.1 概述

  • 函数参数可以分为两大类形参:在定义函数时,在括号内指定的参数/变量名,称之为形式参数,简称形参形参的本质就是变量名实参:在调用函数时,括号内传入的值,称之为实际参数,简称实参实参的本质就是变量值
  • 实参与形参的关系:在调用函数时,实参的值会绑定给形参,该绑定关系可以在函数内使用在函数调用结束后,会解除绑定关系

2.2 参数详解

  • 位置形参
位置形参: 在定义函数时,按照从左到右的顺序依次定义的变量名,称之为位置形参特点:必须被传值,多一个不行,少一个也不行def func(x, y):print(x, y)func(1, 2)func(1, 2, 3)       # 报错func(1)             # 报错
  • 位置实参
位置实参:在调用函数时,按照从左到右的顺序依次传入的值,称之为位置实参特点:按照位置与形参一一对应def func(x, y):print(x, y)func(1, 2)func(2, 1)
  • 默认形参
默认参数(具有默认值的形参):在定义函数时,就已经为某个形参赋值了,该形参就称之为默认参数特点:在调用阶段可以不用给默认形参传值def func(x, y=111):print(x, y)func(1, 2)          # 1 2func(1)             # 1 111
def register(name, age, gender="male"):print(name, age, gender)register("egon", 18)register("lxx", 38)register("hxx", 32, "female")register("李建国", 30)register("alex", 31)register("xxx", 18)
  • 关键字实参
关键字实参:在调用函数时,按照key=value的形式指定的实参,称之为关键字实参特点:可以打乱顺序,但仍能指名道姓为指定的形参赋值def func(x, y=2222):print(x, y)func(y=222, x=1212)         # 1212 222func(x=111)                 # 111 2222

2.3 参数的使用

  • 实参的混用
实参的混用:位置实参和关键字实参可以混用,但必须注意Ⅰ 位置实参必须放在关键字实参的前面Ⅱ 不能为同一个形参重复赋值def func(x, y=2222):print(x, y)func(1, y=2)              # 1 2func(y=2, 1)            # 报错func(1, y=2, x=3)       # 报错
  • 形参的混用
形参的混用:位置形参和默认形参可以混用,但必须注意位置形参必须放在默认形参的前面def func(x, y=111):print(x, y)def func(y=111, x):     # 报错print(x, y)
  • 默认形参使用的注意点
默认形参使用的注意点默认形参的值最好是不可变类型m = 222def func(x, y=m):print(x, y)m = 666func(111)               # 得到111 222
def register(name,hobby,hobbies=[]):hobbies.append(hobby)print(\'%s 的爱好是 %s\' %(name, hobbies))def register(name, hobby, hobbies=None):if hobbies is None:hobbies=[]hobbies.append(hobby)print(\'%s 的爱好是 %s\' %(name, hobbies))register("egon", "smoke")register("lxx", "dance")register("hxx", "drink")

2.4 可变长函数–>*与**的应用

  • 可变长指的是在调用函数时,传入参数个数不固定,而实参是为形参赋值的

  • 所以必须有对应格式的形参来接受溢出的实参

  • 用在形参中

在形参中带*,*会将溢出位置实参汇总成元组,然后赋值给其后变量名,通常是argsdef func(x, y, *z):print(x, y, z)func(1, 2, 3, 4, 5)         # 1 2 (3, 4, 5)func(1, 2)                  # 1 2 ()func(1)                     # 报错def my_sum(*args):res = 0for i in args:res += iprint(res)my_sum(1)               # 1my_sum(1, 2)            # 3my_sum(1, 2, 3)         # 6在形参中带**,**会将溢出关键字实参汇总成字典,然后赋值给其后变量名,通常是kwargsdef func(x, y, **kwargs):print(x, y, kwargs)func(1, y=2, a=1, b=2, c=3)        # 1 2 {\'a\': 1, \'b\': 2, \'c\': 3}
  • 用在实参中
在实参中带*:*会将紧跟其后的实参打散成位置实参,注意*后跟的应该是一个可以被for循环循环的类型def func(a, b, c, d):print(a, b, c, d)func(*"hello")                        # 报错,不对应func(*"hell")                           # h e l lfunc(*[11, 22, 33, 44])                 # 11 22 33 44func(11, 22, *[33, 44])                 # 11 22 33 44func(11, 22, *{"k1": 111, "k2": 222})   # 11 22 k1 k2在实参中带**:**会将紧跟其后的实参打散成关键字实参,注意*后跟的必须是一个字典def func(a, b, c, d):print(a, b, c, d)func(**{"k1": 333, "k2": 444})                              # 报错func(**{"d": 333, "b": 444, "a": 111, "c": 222})            # 111 444 222 333func(**[("d", 333), ("b", 444), ("a", 111), ("c", 222)])    # 报错
  • 混用
混用Ⅰ 在形参中,*必须在**前Ⅱ 在实参中,*必须在**前def index(x, y, z):print(\'index------>\', x, y, z)def wrapper(*arges, **kwargs):index(*arges, **kwargs)# wrapper(1, 2, 3, 4, a=1, b=2, c=3)      # 不能一一对应 报错wrapper(1, 2, 3)                # index------> 1 2 3wrapper(z=3, y=2, x=1)          # index------> 1 2 3def wrapper(*arges,**kwargs):print(arges)print(kwargs)wrapper(1, 2, a=1,b=2,c=3)      # (1, 2) {\'a\': 1, \'b\': 2, \'c\': 3}

2.6 命名关键字形参

  • 在*与**之间定义的形参
  • 必须按照key=value的形式传值
def func(x, y=1, *args, a=666, b, **kwargs):print(x)print(y)print(args)print(a)print(b)print(kwargs)func(1, 2, 3, 4, 5, 6, 7, a=111, b=222, c=333)      # 1 2 (3, 4, 5, 6, 7) 111 222 {\'c\': 333}func(1, 2, 3, 4, 5, 6, 7, b=222, c=333)             # 1 2 (3, 4, 5, 6, 7) 666 222 {\'c\': 333}func(1, 2, 3, 4, 5, 6, 7, b=222, 333)               # 报错

3 函数对象

  • 函数是第一等公民(可以当变量使用)
def func():print(\'from func\')

3.1 可以赋值

f = funcf()             # 输出from func

3.2 可以当参数传给另一个函数

def bar(x):print(x)mmm = 11111bar(mmm)           # 11111bar(func)          # <function func at 0x000002D4F29B63A0>

3.3 可以当作一个函数的返回值

def add(x):         # x=函数func的内存地址return x        # return 函数func的内存地址res = add(func)     # 相当于add(函数func的内存地址)print(res)          # <function func at 0x000002D4F29B63A0>

3.4 可以当容器类型的元素

x = 10l = [x, func]print(l)            # [10, <function func at 0x000002C48C4463A0>]l[-1]()             # from func
# 练习# 新的功能只需要在字典中加入即可,无需动循环def login():print(\'login\')def register():print(\'register\')def transfer():print(\'transfer\')def withdraw():print(\'withdraw\')func_dic = {"1": [login, "登录"],"2": [register, "注册"],"3": [transfer, "转账"],"4": [withdraw, "提现"]}while True:print("0 退出")for k in func_dic:print(k, func_dic[k][-1])choice = input("请输入操作编号:").strip()if choice == "0":breakif choice in func_dic:func_dic[choice][0]()else:print("输入的操作不存在")

4 函数嵌套

4.1 函数的嵌套定义

def f1():print(\'from f1\')def f2():print(\'from f2\')print(f2)f2()x=1111f1()输出结果如下:# from f1# <function f1.<locals>.f2 at 0x00000274E0EB8700># from f2
from math import pidef circle(radius, mode=0):def perimiter(radius):return 2 * pi *radiusdef area(radius):return pi * (radius ** 2)if mode == 0:return perimiter(radius)elif mode == 1:return area(radius)res1 = circle(10, mode=0)print(res1)                 # 62.83185307179586res2 = circle(10, mode=1)print(res2)                 # 314.1592653589793

4.2 函数的嵌套调用

def max2(x, y):if x > y:return xelse:return ydef max4(a, b, c, d):res1 = max2(a, b)res2 = max2(res1, c)res3 = max2(res2, d)return res3res = max4(1, 2, 3, 4)print(res)              # 4
赞(0) 打赏
未经允许不得转载:爱站程序员基地 » day008|python之函数