zoukankan      html  css  js  c++  java
  • 函数

    函数

    1 函数的意义

    函数就相当于具备某一功能的工具

    函数可以有效提高代码的复用性,可读性,维护性,可拓展性

    函数的使用必须遵循一个原则:
    先定义, 后调用

    2 函数的语法

    函数语法中必要的是def,函数名,():,函数体

    可选的是参数,文档描述,return

    def 函数名(参数1,参数2,...):
        """文档描述"""
        # 函数体
        return "值"
    

    函数可以有两种产物,一是函数体的执行产物,二是return返回的值

    可以使用变量接受return的值

    3 函数的定义方式

    定义函数发生的事情
    1、申请内存空间保存函数体代码
    2、将上述内存地址绑定函数名
    3、定义函数不会执行函数体代码,但是会检测函数体语法

    3.1 无参函数

    顾名思义,无参函数就是没有参数的函数,它不需要传入任何参数就能运行

    def func():
        print('哈哈哈')
        print('哈哈哈')
        print('哈哈哈')
    
    def interactive():
        name=input('username>>: ')
        age=input('age>>: ')
        gender=input('gender>>: ')
        msg='名字:{} 年龄:{} 性别{}'.format(name,age,gender)
        print(msg)
    
    interactive()
    interactive()
    interactive()
    interactive()
    

    3.2 有参函数

    顾名思义,有参函数就是有参数的函数,它必须输入对应的参数才能执行

    def func(x,y): # x=1  y=2
        print(x,y)
    func(1,2)
    
    def add(x,y):
        res=x + y
        return res 
    res=add(20,30)
    print(res)
    

    3.3 空函数

    空函数函数体代码为pass

    空函数一般用于快速搭建框架

    def auth_user():
        """user authentication function"""
        pass
    
    def download_file():
        """download file function"""
        pass
    
    def upload_file():
        """upload file function"""
        pass
    
    def ls():
        """list contents function"""
        pass
    
    def cd():
        """change directory"""
        pass
    

    4 函数的调用方式

    调用函数发生的事情
    1、通过函数名找到函数的内存地址
    2、然后加括号就是在触发函数体代码的执行

    def func():
        pass
    print(func)
    # <function func at 0x000002326850DF28>
    func()
    

    4.1 只加括号调用函数的形式

    interactive()
    add(1,2)
    

    这种函数调用形式只有代码执行的产物,没有接收返回值

    4.2 表达式形式:

    赋值表达式和数学表达式都属于这个类型

    这个类型主要是为了接收返回值,并将返回值输出或继续进行别的操作

    def add(x,y): # 参数->原材料
        res=x + y
        return res # 返回值->产品
    # 赋值表达式
    res=add(1,2)
    print(res)
    # 数学表达式
    res=add(1,2)*10
    print(res)
    

    4.3 函数调用可以当做参数

    这个类型主要是为了用返回值进行别的操作

    res=add(add(1,2),10)
    print(res)
    

    5 定义与调用

    5.1 示例1

    示范1代码的执行为

    1.定义bar

    2.定义foo

    3.调用foo,执行print(bar)

    4.foo调用bar------------->执行print('from bar')

    5.继续执行foo,执行print('from foo')

    6.代码结束

    # 示范1
    def bar(): # bar=函数的内存地址
        print('from bar')
    def foo():
        print(bar)
        bar()
        print('from foo')
    foo()
    
    # <function bar at 0x00000265609FDF28>
    # from bar
    # from foo
    
    

    5.2 示例2

    示范2代码的执行为

    1.定义foo

    2.定义bar

    3.调用foo,执行print(bar)

    4.foo调用bar------------->执行print('from bar')

    5.继续执行foo,执行print('from foo')

    6.代码结束

    # 示范2
    def foo():
        print(bar)
        bar()
        print('from foo')
    
    def bar():  # bar=函数的内存地址
        print('from bar')
    
    foo()
    # <function bar at 0x00000265609FDF28>
    # from bar
    # from foo
    # <function func at 0x00000265609FDEA0>
    

    5.3 示例3

    示范3代码的执行为

    1.定义foo

    2.调用foo,执行print(bar)

    3.由于未定义bar,报错

    4.定义bar-------未执行

    # 示范3
    def foo():
        print(bar)
        bar()
        print('from foo')
    foo()
    def bar():  # bar=函数的内存地址
        print('from bar')
    
    # NameError: name 'bar' is not defined
    

    6 函数返回值

    return是函数结束的标志,即函数体代码一旦运行到return会立刻
    终止函数的运行,并且会将return后的值当做本次运行的结果返回:

    6.1 返回None:

    返回None的三种情况:

    1. 函数体内没有return

    2. return

    3. return None

    6.2 返回一个值:return 值

    def func():
        return 10
    
    res=func()
    print(res)
    

    6.3 返回多个值:

    用逗号分隔开多个值,会被return返回成元组

    def func():
        return 10, 'aa', [1, 2]
    
    res = func()
    
    print(res, type(res))
    # (10, 'aa', [1, 2]) <class 'tuple'>
    

    7 函数的参数

    7.1 参数的类型

    形参:在函数定义阶段定义的参数称之为形式参数,简称形参,相当于变量名

    def func(x, y):  # 定义阶段中的x,y全都是形参
        print(x, y)  # 定义阶段中的x,y全都是形参
    

    实参:在调用函数阶段传入的值称之为实际参数,简称实参,相当于变量值
    func(1,2)

    实参: 调用函数时传入的值,但值可以是以下形式

    # 形式一:直接传值
    func(1,2)
    
    # 形式二:传入变量值
    a=1
    b=2
    func(a,b)
    
    # 形式三:传入函数的结果
    func(int('1'),2)
    func(func1(1,2,),func2(2,3),333)
    

    形参与实参的关系:
    1、在调用阶段,实参(变量值)会绑定给形参(变量名)
    2、这种绑定关系只能在函数体内使用
    3、实参与形参的绑定关系在函数调用时生效,函数调用结束后解除绑定关系

    7.2 形参

    形参是在函数定义阶段定义的参数称之为形式参数,相当于变量名

    可以分为位置参数,关键字参数,默认参数,不定长参数

    7.2.1 位置参数

    位置参数:在函数定义阶段,按照从左到右的顺序依次定义的参数称之为位置参数

    特点:每个位置参数都必须被传值,多一个不行少一个也不行

    def func(x,y):
        print(x,y)
    func(1,2)	# 1,2
    func(1,2,3) # 报错
    func(1,)    # 报错
    

    7.2.2 默认参数

    默认形参:在定义函数阶段,就已经被赋值的形参,称之为默认参数
    特点:在定义阶段就已经被赋值,在调用阶段可以不用为其传参

    def func(x,y=3):
        print(x,y)
        
    func(x=1)
    # 1,3
    func(x=1,y=44444)
    # 1,44444
    
    # 默认参数的运用场景: 
    # 某个参数一般都为同一个值,很少改变时可以用默认参数减少调用时的传参数
    def register(name,age,gender='男'):
        print(name,age,gender)
    
    register('三炮',18)
    register('二炮',19)
    register('大炮',19)
    register('没炮',19,'女')
    

    7.2.3 位置形参与默认形参混用

    位置形参与默认形参混用时必须遵守的规则:

    1、位置形参必须在默认形参的左边

    def func(y=2,x):
        pass
    # 报错
    

    2、默认参数的值是在函数定义阶段被赋值的,准确地说被赋予的是值的内存地址

    # 示范1:
    m=2
    def func(x,y=m):
        print(x,y)
    # 默认参数y此时指向2的内存地址,而不是m的值
    m=3333
    func(1)
    # 输出1,2
    
    # 示范2:
    m = [1, ]
    def func(x, y=m): 
        print(x, y)
    # 默认参数y此时指向[111111, ]的内存地址
    m.append(3)
    # 在该列表中增加值,未改变内存地址
    func(1)
    # 输出1,[1,3]
    

    3、默认参数不使用可变数据类型,如有需求可以将可变数据类型写入函数体中

    虽然默认值指定为任意数据类型不会报错,但是不推荐使用可变类型

    函数最理想的状态:

    函数的调用只跟函数本身有关系,不外界代码的影响

    使用可变数据类型可能导致意外情况出现

    # 如有需求可以将可变数据类型写入函数体中
    def func(x,y,z,l=None):
        if l is None:
            l=[]
        l.append(x)
        l.append(y)
        l.append(z)
        print(l)
    
    func(1,2,3)
    # [1,2,3]
    
    new_l=[111,222]
    func(1,2,3,new_l)
    # [111,222,1,2,3]
    

    7.2.4 可变长度的形参(*args和**kwargs)

    可变长度的形参可以接收所有传入的多余的实参

    其中*args用来接收所有传入的多余的位置参数

    **kwargs用来接收所有传入的多余的关键字参数

    7.2.4.1 可变长度的位置参数

    *+形参名:用来接收溢出的位置实参,*会把溢出的位置实参保存成元组的格式然后传给紧跟其后的形参名

    在调用函数的过程中,溢出的位置实参会被*保存成元组的格式然后传给紧跟其后的形参名
    *后跟的可以是任意名字,但是约定俗成应该是args,即*args

    def func(x,y,*z): # z =(3,4,5,6)
        print(x,y,z)
    func(1,2,3,4,5,6)
    # 1,2,(3,4,5,6)
    
    def my_sum(*args):
        res=0
        for item in args:
            res+=item
        return res
    
    res=my_sum(1,2,3,4)
    print(res)
    # 10
    

    *可以用在实参中,实参中带*,会先把*后的值打散成实参

    如把列表,字符串,元组变成多个独立的元素按位置传入参数

    def func(x,y,z):
        print(x,y,z)
    
    func(*[11,22,33]) # func(11,22,33)
    func(*[11,22]) # func(11,22)
    
    l=[11,22,33]
    func(*l)
    
    

    形参与实参中都使用*的情况

    def func(x,y,*args): # args=(3,4,5,6)
        print(x,y,args)
    
    func(1,2,[3,4,5,6])	 	 # 此时为传入3个位置参数,分别为1,2,列表[3,4,5,6]
    # 1 2 ([3, 4, 5, 6],)	 # 这是不打散,打包
    
    func(1,2,*[3,4,5,6]) 	 # 此时为传入6个位置参数,func(1,2,3,4,5,6)
    # 1 2 (3, 4, 5, 6)	 	 # 这是打散,再打包
    
    func(*'hello') 		 	 # 传入5个位置参数func('h','e','l','l','o')
    # h e ('l', 'l', 'o')	 # 这是打散,再打包
    

    7.2.4.2 可变长度的关键字参数

    **+形参名:用来接收溢出的关键字实参,**会将溢出的关键字实参保存成字典格式,然后赋值给紧跟其后的形参名
    **后跟的可以是任意名字,但是约定俗成应该是kwargs,即**kwargs

    def 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}
    

    **可以用在实参中(**后跟的只能是字典),实参中带**,会把**后的字典打散成独立的关键字实参,即key=value的形式

    def func(x,y,z):
        print(x,y,z)
    
    func(*{'x':1,'y':2,'z':3}) # func('x','y','z')
    func(**{'x':1,'y':2,'z':3}) # func(x=1,y=2,z=3)
    
    # 错误演示
    func(**{'x':1,'y':2,}) # func(x=1,y=2)
    func(**{'x':1,'a':2,'z':3}) # func(x=1,a=2,z=3)
    

    形参与实参中都使用**的情况:

    def func(x,y,**kwargs):
        print(x,y,kwargs)
    
    func(y=222,x=111,a=333,b=444)	
    # 传入了4个关键字参数,其中ab为多余的关键字参数,打包成字典
    # 111 222 {"a": 333, "b": 444}
    
    func(**{'y':222,'x':111,'a':333,'b':4444}) 
    # 传入了4个关键字参数,其中ab为多余的关键字参数,打包成字典
    # 先打散,再打包
    # 111 222 {"a": 333, "b": 4444}
    

    7.2.4.2 可变长度的参数混用

    混用*与**时必须遵守的规则:

    *args必须在**kwargs之前

    def func(a,*args,**kwargs):
        print(args)
        print(kwargs)
    
    func(1,2,3,4,5,6,7,8,x=1,y=2,z=3) 
    # 传入8个位置参数,其中7个为多余的,打包成元组(2,3,4,5,6,7,8)
    # 传入3个关键字参数,全为多余的,打包成字典{"x":1,"y":2,"z":3}
    # 运行结果:
    # (2,3,4,5,6,7,8)
    # {"x":1,"y":2,"z":3}
    
    def index(x,y,z):
        print('index=>>> ',x,y,z)
    
    def wrapper(*args,**kwargs): #args=(1,) kwargs={'z':3,'y':2}
        index(*args,**kwargs)
        # index(*(1,),**{'z':3,'y':2})
        # index(1,z=3,y=2)
    
    wrapper(1,z=3,y=2) 
    # 为wrapper传递的参数是给index用的
    # 传入wrapper的参数都为多余的,打包成(1,)和{"z":3,"y":2}
    # 执行index(*args,**kwargs)时为实参,即*将实参元组打散,**将字典打散,即得1,z=3,y=2
    # 传入index 得到结果1,2,3
    # 原格式--->打包---->打散
    # 原格式--->汇总---->打回原形
    

    7.2.5 命名关键字参数

    命名关键字参数:

    在定义函数时,*后定义的参数,称之为命名关键字参数

    特点:
    1、必须按照key=value的形式才能为命名关键字参数传值,按照位置传参数时全会被*拦截,不可能传参数到命名关键字参数

    2、传参时不要求顺序

    3、不设定默认值时必须传值

    def func(x,y,*,a,b): # 其中,a和b称之为命名关键字参数
        print(x,y)
        print(a,b)
    
    func(1,2,b=222,a=111)
    # 1,2
    # 111,222
    

    可以用key=value的形式为命名关键字参数设定默认值

    设定默认值后可以不用传参数

    def func(x,y,*,a=11111,b):
        print(x,y)
        print(a,b)
    
    func(1,2,b=22222)
    # 1,2
    # 11111,22222
    

    7.2.6 所有形式参数混用

    形参混用的顺序:

    位置新参,默认形参, *args, 命名关键字形参,**kwargs

    def func(x,y=111,*args,z,**kwargs):
        print(x,y,args)
        print(z,kwargs)
    

    7.3 实参

    实参是调用函数时传入的值

    默认参数可以不传入参数

    实参可以通过以下方法传参:

    1.按位置传参

    2.按关键字传参

    3.位置,关键字混合传参

    7.3.1 按位置传参

    按位置传参: 按照从左到右的顺序依次传入参数
    特点:必须按照顺序,与形参一一对应

    def fun(a,b):
        print(a,b)
    func(1,2)
    # 1-->a ,   2-->b
    # 1,2
    func(2,1)
    # 2-->a ,   1-->b
    # 2,1
    

    7.3.2 按关键字传参

    按关键字传参:按照key=value的形式传入参数
    特点:指名道姓给某个形参传值,可以完全不参照顺序

    def func(x,y):
        print(x,y)
    
    func(y=2,x=1)
    # 2-->y ,   1-->x
    # 1,2
    

    7.3.3 位置传参与关键字传参混用

    位置传参与关键字传参混用必须遵守的规则:

    1、位置实参必须放在关键字实参前

    def func(x,y):
        print(x,y)
    func(1,y=2)		# 正确示范 
    # 1,2
    func(y=2,1)		# 错误示范
    # 报错
    

    2、不能能为同一个形参重复传值

    def func(x,y):
        print(x,y)
    func(1,y=2)		# 正确示范 
    # 1,2 
    func(1,y=2,x=3) # 错误示范
    # 报错
    

    7.3.3 所有传参方式混用

    只要保证按位置传的参数写在按关键字传的参数之前就行

    *args (打散)可以看作多个按位置传的参数

    **kwargs (打散)可以看作多个按关键字传的参数

    def func(x,y,z,a,b,c):
    	print(x,y,z,a,b,c)
    
    func(111,y=222,*[333,444],**{'b':555,'c':666})	
    # 错误
    
    func(111,y=222,333,444,b=555,c=666)
    # 错误
    
    func(111,*[333,444],a=222,**{'b':555,'c':666})
    # 正确
    
    func(111,333,444,a=222,b=555,c=66)
    # 正确
    
    func(111,*[333,444],**{'b':555,'c':666},a=222,)
    # 正确
    

    8 函数对象

    函数也是一个对象,可以把函数当成变量去用

    8.1 可以赋值

    # func=内存地址
    def func():
        print('from func')
    
    f=func
    print(f,func)
    f()
    

    8.2 可以当做函数当做参数传给另外一个函数

    # func=内存地址
    def func():
        print('from func')
    
    def foo(x): # x = func的内存地址
        # print(x)
        x()
    
    foo(func) # foo(func的内存地址)
    

    8.3 可以当做函数当做另外一个函数的返回值

    def foo(x): # x=func的内存地址
        return x # return func的内存地址
    
    res=foo(func) # foo(func的内存地址)
    print(res) # res=func的内存地址
    
    res()
    

    8.4 可以当做容器类型的一个元素

    l=[func,]
    # print(l)
    l[0]()
    
    dic={'k1':func}
    print(dic)
    dic['k1']()
    

    8.5 函数对象应用示范

    示范1:

    def login():
        print('登录功能')
    
    
    def transfer():
        print('转账功能')
    
    
    def check_banlance():
        print('查询余额')
    
    def withdraw():
        print('提现')
    
    
    def register():
        print('注册')
    
    func_dic={
        '1':login,
        '2':transfer,
        '3':check_banlance,
        '4':withdraw,
        '5':register
    }
    
    
    while True:
        print("""
        0 退出
        1 登录
        2 转账
        3 查询余额
        4 提现
        5 注册
        """)
        choice = input('请输入命令编号:').strip()
        if not choice.isdigit():
            print('必须输入编号,傻叉')
            continue
    
        if choice == '0':
            break
    
    
        if choice in func_dic:
            func_dic[choice]()
        else:
            print('输入的指令不存在')
    
    
    
    

    示范2:

    def login():
        print('登录功能')
    
    
    def transfer():
        print('转账功能')
    
    
    def check_banlance():
        print('查询余额')
    
    
    def withdraw():
        print('提现')
    
    
    def register():
        print('注册')
    
    
    func_dic = {
        '0': ['退出', None],
        '1': ['登录', login],
        '2': ['转账', transfer],
        '3': ['查询余额', check_banlance],
        '4': ['提现', withdraw],
        '5': ['注册', register]
    }
    
    
    
    while True:
        for k in func_dic:
            print(k, func_dic[k][0])
    
        choice = input('请输入命令编号:').strip()
        if not choice.isdigit():
            print('必须输入编号,傻叉')
            continue
    
        if choice == '0':
            break
    
        # choice='1'
        if choice in func_dic:
            func_dic[choice][1]()
        else:
            print('输入的指令不存在')
    

    9 函数的嵌套

    函数嵌套有两种:

    调用的嵌套 和 定义的嵌套

    9.1 函数的嵌套调用

    函数的嵌套调用就是在调用一个函数的过程中又调用其他函数

    def max2(x,y):
        if x > y:
            return x
        else:
            return y
    # 比较大小,返回较大值
    
    def max2(x,y):
        if x > y:
            return x
        else:
            return y
    # 比较大小,返回较大值
    
    # 嵌套调用
    def max4(a,b,c,d):
        # 第一步:比较a,b得到res1
        res1=max2(a,b)
        # 第二步:比较res1,c得到res2
        res2=max2(res1,c)
        # 第三步:比较res2,d得到res3
        res3=max2(res2,d)
        return res3
    
    res=max4(1,2,3,4)
    print(res)
    

    9.2 函数的嵌套定义

    函数的嵌套定义就是在函数内定义其他函数

    def f1():
        def f2():
            pass
    
    # 圆形
    # 求圆形的求周长:2*pi*radius
    # radius 半径
    # pi=π
    def circle(radius,action=0):
        from math import pi
        def perimiter(radius):
            return 2*pi*radius
    
        # 求圆形的求面积:pi*(radius**2)
        def area(radius):
            return pi*(radius**2)
    
        if action == 0:
            return 2*pi*radius
    
        elif action == 1:
            return area(radius)
    
    circle(33,action=0)
    

    1

  • 相关阅读:
    上海最适合拍照的旅游地点
    九款优秀的企业项目协作工具推荐
    九款优秀的企业项目协作工具推荐
    就如何快速免费提高网站排名小结
    就如何快速免费提高网站排名小结
    科博会|人工智能时代的到来
    科博会|人工智能时代的到来
    JS数组去重的6种算法实现
    JS数组去重的6种算法实现
    八款前端开发人员更轻松的实用在线工具
  • 原文地址:https://www.cnblogs.com/achai222/p/12513095.html
Copyright © 2011-2022 走看看