• 10.函数的基本使用


    • 引子
    • 函数的基本使用

    • 先定义,后调用

    • 定义函数的三种形式

    • 调用函数的三种形式

    • 函数的返回值

    • 函数参数的使用

    • 形参系列

    • 实参系列

    • 可变长系列


    函数的基本使用


    • 什么是函数?

      ps:函数就是盛放代码的容器

      具备某一功能的工具--->函数

      事先准备工具的过程--->函数的定义

      遇到应用场景拿来就用--->函数的调用

      函数的使用原则:

      先定义   
      后调用  
    • 为何要用函数?

      解决下述问题:

      1.代码组织结构不清晰、可读性差
      2.可维护性、可扩展性差
    • 如何用函数?

      ​ 先定义

      ​ 三种定义方式

      ​ 后调用

      ​ 三种调用方式

      ​ 返回值

      ​ 三种返回值的形式

      定义的语法:
    def 函数名(参数1,参数2,参数3,...):
    	'''函数的文档注释'''
        函数体(代码1)
        代码2
        代码3
        return 返回值
    
    # def: 定义函数的关键字;
    # 函数名:函数名指向函数内存地址,是对函数体代码的引用。函数的命名应该反映出函数的功能;
    # 括号:括号内定义参数,参数是可有可无的,且无需指定参数的类型;
    # 冒号:括号后要加冒号,然后在下一行开始缩进编写函数体的代码;
    # """文档注释""": 描述函数功能,参数介绍等信息的文档,非必要,但是建议加上,从而增强函数的可读性;
    # 函数体:由语句和表达式组成;
    # return 值:定义函数的返回值,return是可有可无的。
    
    
    • 一、定义函数、

    定义函数发生的事情

    1、申请内存空间把函数体代码放进去

    2、将函数内存地址绑定给函数名

    强调:定义函数只检测语法,不执行代码

    def login():  # login = 函数的内存地址
        print(111)   # 函数体代码
        print(222)
        print(333)
        print(444)
        
    x = 10       # x = 10的内存地址
    print(x)     # 原则上打印应该返回内存地址,但是返回的是值。变量名受到python解释器特殊照顾由内存地址直接找到返回值打印。
    print(login) # 但函数名不同,打印显示的是内存地址。定义函数的目的是为了把代码丢到容器,只需要运行不需查看。则无需被照顾。
    
    • 二、调用函数

    调用函数发生的事情:

    1、先通过函数名定为到函数的内存地址

    2、函数内存地址()--->触发函数体代码的运行

    强调:调用函数才会执行函数体代码

    def login():
        print(111)   
        print(222)
       
    login()  
    
    
    # 例1
    def func():
        print(11111   # 语法错误 定义阶段都无法通过
    
    
    # 例2:
    def func():
        print(1111)
        x            # 逻辑错误,x 没有定义,变量名也需要先定义后引用
        print(2222)
    
    func()
    
    
    # 例3:
    # ================
    def bar():
        print('from bar')
    
    def foo():
        print('from foo')
        bar()
    
    foo()
    ================
    # 例4:         
    def foo():
        print('from foo')
        bar()
              
    foo()               # 语法错误,bar没有定义,调用肯定出错
              
    def bar():
        print('from bar')
    
    
    • 三、定义函数的三种形式

    1.无参函数
    # 例1:函数体不需要外部传参数进行,它本身代码就是固定的,所以就是无参函数
    def say():
        print('========')
        print('welcome to here')
        print('========')
    say()
    
    # 参数是函数的调用者向函数体传值的媒介,有参无参是根据函数体代码去走的,看函数体代码是否需要外部传参数
    def login():
        inp_name = input("username>>>: ").strip()  
        inp_pwd = input("password>>>: ").strip()
        if inp_name == "egon" and inp_pwd == "123":
            print('login successful')
        else:
            print("username or password error")
    
    login()  # 直接调用无需传参数,input功能已经实现与用户交互
    
    2.有参函数
    # 函数体代码需要外部传参数进行,这种函数就需要定义为有参函数
    def max2(x,y):  # 参数---》原材料 
        if x > y:
            print(x)
        else:
            print(y)
    max2(10,20)
    
    
    3.空函数
    # 函数体为pass代表什么都不做,称之为空函数。定义空函数通常是有用的,因为在程序设计的开始,往往是先想好程序都需要完成什么功能,然后把所有功能都列举出来用pass充当函数体“占位符”,这将使得程序的体系结构立见,清晰且可读性强。例如要编写一个程序,我们可能想到的功能有用户认证,下载,上传,等功能,可以先做出如下定义:
    
    def auth_user():
        """user authentication function"""
        pass   # 代表占位符
    
    def download_file():
        """download file function"""
        pass
    
    def upload_file():
        """upload file function"""
        pass
    
    • 四、调用函数的三种形式

    # 1.语句
    
    len("hello")   # 单纯的调用,例如len统计hello的长度
    
    # 2.表达式
    
    res = len("hello")    # 将调用函数的返回值赋值给res
    
    res = len("hello") * 10  # 将调用函数的返回值乘以10的结果赋值给res
    print(res)
    
    # 3 .可以当做参数传给另外一个函数
    len("hello")             # 从形式上看就是将函数调用,从本质讲是跟2同理
    print(len("hello"))      # 先调len的返回值然后再赋值给print
    
    • 五、函数的返回值

    return详解:
    def max2(x,y): 
        if x > y:
            return x
        else:
            return y
        
    res = max2(10,20)
    print(res)
    
    # 1、return是一个函数结束的标志,函数可以有多个return,但只要执行一次return,整个函数就立即结束,并且将return后的值当做本次调用的结果返回:
    def func():
        print("=====")  # 只运行到了此行
        return 111      # return后的值当做本次调用的结果返回  # 111
        print("****")
        return 222
        print("----------")
        return 333
    
    res = func()
    print(res)
    
    # 2、return后的返回值有三种情况
    # (1)return 值:返回的就是这一个值
    # (2)return 值1,值2,值3:返回的一个元组
    def func():
        return 111,"xxx",[22,33]
    
    res = func()
    print(res)   # (111,"xxx",[22,33])返回的是元组
    # (3)函数内可以没有return、或者return None、或者return:返回的都是None
    def func():
        print(111)
        return
        print(2222)
    
    
    res = func()
    print(res)
    

    函数参数的使用

    函数参数总体分为两大类:

    1、形参:在函数定义阶段括号内指定的参数,称之为形式参数,简称形参----》变量名

    2、实参:在函数调用阶段括号内传入的值,称之为实际参数,简称实参----》变量的值

    形参与实参的关系是:
    在调用函数时,实参值会绑定给形参名,在函数调用完毕后解除绑定
    def func(x,y):    # x,y是形参,在定义阶段()内传值。形参指的是变量名。   
        print(x,y)
        
    func(111,222)     # 111,222是实参,在调用阶段传送的值,实参指的是变量值
    
    • 形参系列:

    • 一、位置形参:在定义函数时,按照从左到右的顺序依次定义的变量名,称之为位置形参
      特点:每次调用必,须被赋值
    def func(x,y):   # 定义位置形参:x,y,两者都必须被传值
        print(x)
        print(y)
    
    func(1,2)      # 可以正常赋值,必须刚刚好
    func(1,2,3)    # 报错,多了一个值
    func(1)        # 报错,少了一个值      
    
    • 二、默认形参:在定义函数时,就已经为某个形参赋值了,称之为默认形参
      特点:调用函数时,可以不用为其赋值
    def func(name,age=18):     # age=18是默认形参,无需赋值,也可以被赋值
        print(name)
        print(age)
    func("egon")       # name正常赋值
    func("egon",19)       # 正常赋值
    

    注意: 可以混用位置形参与默认形参,但是

    1、位置形参必须在前面
    def func(age = 18, name):
        print(name)
        print(age)        # 报错
    
    2、默认形参的值通常应该是不可变类型
    # 例一:
    def func(name,hobby,hobbies = []): # 三次调用都用的是同一列表
        hobbies.append(hobby)
        print('%s的爱好是%s'%(name,hobbies))
    func('egon','read')     # egon的爱好是['read']
    func('tom','play')      # tom的爱好是['read', 'play']
    func('jack','movie')    # jack的爱好是['read', 'play', 'music']
    
    # 例二:
    def func(name,hobby,hobbies = None):   # 设定hobbies为None
        if hobbies is None:         # 如果没有为hobbies传值,hobbies默认就是None
            hobbies = []            # 每次传值给hobbies,就会产生新的列表
        hobbies.append(hobby)
        print('%s的爱好是%s' %(name,hobbies))
    
    func('egon','read')
    func('tom','play')
    func('jack','music')
    func('lili','eat',["movie"])
    
    3、默认形参的值是在函数定义阶段赋值的
    m = 111
    def func(x,y,z = m):   # 在定义阶段就把111赋值给了z
        print(x)
        print(y)
        print(z)
    m = 666
    func(1,2)
    
    • 实参系列:

    • 一、位置实参:在调用函数时,按照从左到右的顺序依次传入的值,称之为位置实参
      特点:按照位置为形参赋值,一一对应
    def func(name,age):    # 定义位置形参:name,age,两者都必须被传值
        print(name)
        print(age)
        
    func("egon")     # 报错,少了一个值
    func("egon",19)  # 正常传值
    
    • 二、关键字实参:在调用函数时,按照key = value的形式传值,称之为关键字实参
      特点:可以打乱顺序,但是仍然能够指定道姓的为指定的形参赋值
    def func(name,age):         # 定义位置形参:name,age,两者都必须被传值
        print(name)
        print(age)
        
    func(age = 18,name = "egon")   # 正常传值
    
    # 注意:可以混用位置实参与关键字实参,但是
    # 1、位置实参必须在关键字实参的前面
    
    func("egon",age = 18)    # 正常传值
    func(age = 18,"egon")    # 报错,语法错误
    
    # 2、不能为同一形参重复赋值
    
    def foo(x,y,z):
        pass
    foo(1,y=2,3)        # 报错,语法错误
    foo(1,y=2,z=3,x=4)  # 报错,语法错误
    
    
    • 可变长系列

    • 可变长系列:

    可变长参数指的是在调用函数时,传入的实参个数不固定,对应着必须有特殊形式的形参来接收溢出的实参
    实参无非两种形式
    溢出的位置实参----->*
    溢出的位置关键字实参----->**

    *与**在形参中是一种汇总行为

    1、*在形参中的应用:*会将溢出的位置实参合并成一个元组,然后赋值给紧跟其后的那个形参名
    def func(x,*y):   # *是接收位置溢出实参的功劳,不是y变量名的功劳。*后面可以跟任意变量名。
        print(x)
        print(y)
        
    func(1,2,3,4,5)  #  x = 1 , y = (2,3,4,5)
    # 1
    # (2,3,4,5)
    
    def func(x,*args):  # args变量名(译:参数) 通常搭配*使用 *args接收位置实参的溢出
        print(x)
        print(args)
    
    func(1,2,3,4,5)  # 同上是一个道理
    
    
    def my_sum(*args):  # 求和运算的函数
        res = 0
        for i in args:
            res += i
        print(res)
    
    my_sum(1,2)
    # 3
    
    2、**在形参中的应用:**会将溢出的关键字实参合并成一个字典,然后赋值给紧跟其后的那个形参名
    def func(x,**kwargs):  # kwargs = {"a":2,"c":4,"b":3}
        print(x)
        print(kwargs)
    
    func(1,a=2,b=3,c=4)
    # 1
    # {'a': 2, 'b': 3, 'c': 4}
    

    =*与**在实参中是一种打散行为===

    *在实参中的应用:*后可以跟可以被for循环遍历的任意类型,*会将紧跟其后的那个值打散成位置实参
    def func(x,y,z):
        print(x)
        print(y)
        print(z)
    
    
    func([11,22,33])      # 报错
    func(*[11,22,33])     # func(11,22,33) *会把列表这种实参打散成位置实参
    func(*"hello")        # func("h","e","l","l","o") 报错,但能证明*的打散行为
    func(*{"k1":111,"k2":2222})  # func("k1","k2") 报错,但证明*能把字典打散成key
    
    
    **在实参中的应用:**只能跟字典类型,**会将字典打散成关键字实参
    func(**{"k1":111,"k2":2222})  # func(k2=2222,k1=111) 报错,没有k关键字,打散后对应不上
    
    func(**{"x":111,"y":2222,"z":333})  # **将字典打散成关键字实参
    # 111
    # 2222
    # 333
    
    # 例1:
    def wrapper(*args, **kwargs):   # 形参中带*和**是一种汇总行为
        print(args)
        print(kwargs)
    
    wrapper(1,2,3,4,5,6,a=1,b=2,c=3)
    # (1, 2, 3, 4, 5, 6)
    # {'a': 1, 'b': 2, 'c': 3}
    
    # 例2:
    def index(x,y,z):
        print(x,y,z)
    
    def wrapper(*args,**kwargs):  
        index(*args,**kwargs)   # 实参中带*和**是一种打散行为
                                # index(*(1,2,3,4,5,6),**{"a":1,"b":2,"c":3})
                                # index(1,2,3,4,5,6,a=1,b=2,c=3)
    wrapper(1,y=2,z=3)
    # 1 2 3
    
    
    了解(**):命名关键字形参: 在*与**中间的形参称之为命名关键字形参
    特点: 必须按照key=value的形式传值
    def func(x,m=333,*args,y=222,z,**kwargs):
        print(x)
        print(args)
        print(y)
        print(z)
        print(kwargs)
    
    func(1,2,3,z=4,a=1,b=2,c=3)
    # 1
    # (3,)
    # 222
    # 4
    # {'a': 1, 'b': 2, 'c': 3}
    func(1,2,3,4,5,6,7)   # 报错,命名关键字都是跟在*的后面
    
  • 相关阅读:
    Tomcat example 应用信息泄漏漏洞及修复
    Tomcat远程代码执行漏洞(CVE-2017-12615)修复
    Oracle安装和使用说明
    关于乱码的问题
    js 判断字符串中是否包含某个字符串
    com.alibaba.fastjson.JSONPathException: expect '], but 'y'
    java.util.UnknownFormatConversionException: Conversion = ''';
    nested exception is java.lang.NoClassDefFoundError: org/codehaus/jettison/json/JSONObject异常的解决办法
    复选框做成单选的效果
    sFlow-rt安装部署
  • 原文地址:https://www.cnblogs.com/gfeng/p/14203702.html
Copyright © 2020-2023  润新知