Python3.5基础——函数的定义与使

发布时间:2019-07-30 09:43:48编辑:auto阅读(1458)

    1、函数学习框架


    2、函数的定义与格式

    (1)定义




    (2)函数调用


    注:函数名称不能以数字开头,建议函数名称的开头用小写的字母

    (3)函数有四种格式,分别是:无参数无返回值,有参数无返回值、无参数有返回值、有参数有返回值


    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    # Author:ZhengzhengLiu
    
    # 无参数无返回值
    def hello():
        # 函数体/方法体
        print("hello world")
    
    
    hello()
    
    
    # 有参数无返回值
    def add(x, y):
        print(x + y)
    
    
    add(10, 20)
    
    
    # 无参数有返回值
    def sleep():
        return "sleep"
    
    
    s = sleep()
    print(s)
    
    
    # print(sleep())       等价于上面两句
    
    # 有参数有返回值
    def sub(x, y):
        return x * y
    
    
    res = sub(12, 6)
    print(res)
    
    #运行结果
    hello world
    30
    sleep
    72
    

    3、函数的参数



    注:定义再函数体内的参数是形参,调用时传入的参数是实参。


    函数参数包括:位置参数、关键字参数和不定个数参数

    (1)位置参数、关键字参数




    示例代码:

    #位置参数
    def test(x,y,z):
        print(x,y,z)
    
    test(1,2,3)
    
    #关键字参数
    def test1(x,y,z=10):
        print(x,y,z)
    
    test1(1,2,3)
    test1(1,2)      #关键字参数,z采用默认的参数值
    test1(x=2,z=3,y=1)   #调用时的关键字参数
    #运行结果:
    1 2 3
    1 2 3
    1 2 10
    2 1 3
    

    (2)默认参数


    注:带有默认值参数的形参必须放在参数的最后面的位置。


    (3)不定个数参数,用*args   和    **kwarg


    总结:

    1定义时  *的作用  将位置实参装配成元组

    定义时  **的作用  将关键字实参装配成字典

    (2)调用时  *作用  将元组或列表打散成位置参数进行参数传递

    调用时  **作用  将字典打散成关键字参数进行参数传递

    #不定个数参数
    
    def test2(x,y,z,*args):
        print(x,y,z,args)
    
    #定义时  *的作用  将位置实参装配成元组
    test2(1,2,3,4,6,7,8,9)
    
    
    def test3(x,y,z,**kwargs):
        print(x,y,z,kwargs)
    
    #定义时  **的作用  将关键字实参装配成字典
    test3(1,2,3,a=6,b=19,c=8)
    
    def ts(x,*args,**kwargs):
        print(x,args,kwargs)
    
    ts(1,2,3,a=6,b=19,c=8)
    
    def test4(x,y,z):
        print(x,y,z)
    
    x = [1,2,3]
    y = {"x":1,"y":"hello","z":"你好"}
    
    test4(*x)       #调用时  *作用  将元组或列表打散成位置参数进行参数传递
    test4(**y)      #调用时  **作用  将字典打散成关键字参数进行参数传递
    
    #运行结果:
    1 2 3 (4, 6, 7, 8, 9)
    1 2 3 {'b': 19, 'a': 6, 'c': 8}
    1 (2, 3) {'b': 19, 'a': 6, 'c': 8}
    1 2 3
    1 hello 你好

    4、函数的传值:基本类型传值调用、非基本类型参数传递调用(强引用与弱引用)


    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    # Author:ZhengzhengLiu
    
    #基本类型传值调用
    def test(x):
        print(x)
    
    test(10)
    
    #非基本类型参数传递调用
    li = [1,2,3,4]
    print(id(li))    #打印传递前的地址
    
    def test1(x):
        print(id(x))
        x[0] = 2   #修改第一个参数为2
        print(x)
    
    test1(li)    #强引用(传址调用,列表里面的内容会进行修改)
    #test1(list(li))   #弱引用(用list可以消除强引用,不能修改列表里的元素)
    
    for i in li:
        print(i)
    
    #运行结果:(强引用传址调用)
    10
    17741864
    17741864
    [2, 2, 3, 4]
    2
    2
    3
    4
    

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    # Author:ZhengzhengLiu
    
    #基本类型传值调用
    def test(x):
        print(x)
    
    test(10)
    
    #非基本类型参数传递调用
    li = [1,2,3,4]
    print(id(li))    #打印传递前的地址
    
    def test1(x):
        print(id(x))
        x[0] = 2   #修改第一个参数为2
        print(x)
    
    #test1(li)    #强引用(传址调用,列表里面的内容会进行修改)
    test1(list(li))   #弱引用(用list可以消除强引用,传值调用,不能修改列表里的元素)
    
    for i in li:
        print(i)
    
    #运行结果:(弱引用,传值调用)
    10
    18501544
    18613272
    [2, 2, 3, 4]
    1
    2
    3
    4

    #不可变对象——传递对象的值,修改值修改的是另一个复制对象,不影响原来对象本身
    def getNum(a):
        a = 10
        print("函数内变量a的值:",a)
    
    a = 8
    getNum(a)
    print("函数外变量a的值:",a)
    
    #可变对象——传递对象本身,函数内部修改值会影响对象本身
    list01 = [0,1,2,3]
    
    def getNum1(num):
        num.append(4)
        print(num)
        print(id(num))
    
    getNum1(list01)
    print(list01)
    print(id(list01))
    
    #运行结果:
    函数内变量a的值: 10
    函数外变量a的值: 8
    [0, 1, 2, 3, 4]
    5908280
    [0, 1, 2, 3, 4]
    5908280
    
    5、函数的返回值

    示例代码:

    #多个返回值
    def re(a,b):
        a *= 10
        b *= 10
        return a,b
    
    num = re(1,2)
    print(type(num))        #如果返回多个值,并且存在一个变量中,会以元组的形式保存
    print(num)
    
    #分别获取多个返回值
    re1,re2 = re(3,4)
    print(type(re1))
    print(re1,re2)
    
    #运行结果:
    <class 'tuple'>
    (10, 20)
    <class 'int'>
    30 40

    简单实例练习:


    def operation(a,b,opt):
        if opt == "+":
            return a+b
        elif opt == "-":
            return a-b
        elif opt =="*":
            return a*b
        elif opt =="/":
            return a/b
        else:
            return "输入有误"
    
    num1 = int(input("请输入第一个字符:"))
    num2 = int(input("请输入第二个字符:"))
    op = input("请输入运算符:")
    result = operation(num1,num2,op)
    print(result)
    
    #运行结果:
    请输入第一个字符:1
    请输入第二个字符:2
    请输入运算符:+
    3

    6、变量的作用域:全局变量与局部变量

    在函数的内部,不能识别全局变量,想要在函数内部使用全局变量,需要关键字global,但不建议这样使用,使用global具有污染性。




    (1)局部变量


    (2)全局变量


    (3)当全局变量与局部变量同名时,优先使用局部变量

    #全局变量与局部变量同名
    a = 10      #全局变量
    print("全局变量a:%d"%a)
    
    def test01():
        a = 20
        print("test01中的a:%d"%a)
    
    def test02():
        print("test02中的a:%d"%a)
    
    test01()
    test02()
    
    #运行结果:
    全局变量a:10
    test01中的a:20
    test02中的a:10

    (4)修改全局变量


    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    # Author:ZhengzhengLiu
    
    i = 20
    
    def test():
        #i += 10        #函数内部直接修改全局的值(错误)
        global i       #函数内部修改全局的值用global关键字
        i += 10
        print(i)        #获取全局变量的值
    
    test()
    #运行结果:
    30

    注:上边代码中,函数内修改不可变类型的全局变量,需要通过global关键字


    总结:对不可变类型变量重新赋值,实际上是重新创建一个不可变类型对象,并将原来的变量指向新创建的对象。

    如果没有其他变量引用原有对象的话(即:引用计数为0),原有对象就会被回收。

    (5)可变类型的全局变量:函数内修改可变类型的全局变量,可以不使用global关键字


    #函数内修改可变类型的全局变量——直接修改,无需使用global关键字
    a = [100,200,300]
    print("可变类型全局变量a:",a)
    print("可变类型全局变量a的地址:%d" %id(a))
    
    def test01():
        a.append(400)        
        print("test01函数内修改可变类型全局变量a:",a)
        print("test01函数内修改可变类型全局变量后a的地址:%d" %id(a))
    
    
    def test02():
        print("test02函数内使用可变类型全局变量a:",a)
        print("test02函数内使用可变类型全局变量a的地址:%d" %id(a))
    
    test01()
    test02()
    
    #运行结果:
    可变类型全局变量a: [100, 200, 300]
    可变类型全局变量a的地址:18241896
    test01函数内修改可变类型全局变量a: [100, 200, 300, 400]
    test01函数内修改可变类型全局变量后a的地址:18241896
    test02函数内使用可变类型全局变量a: [100, 200, 300, 400]
    test02函数内使用可变类型全局变量a的地址:18241896

    7、匿名函数


    示例代码:

    #匿名函数——lambda
    #语法:lambda arg1[,arg2...]:表达式    默认return
    
    num = lambda a,b:a+b
    print(num(1,2))
    
    #运行结果:
    3

    简单应用(一):

    #四则运算——利用lambda表达式
    def operation(a,b,opt):
        re = opt(a,b)
        return re
    
    
    num1 = int(input("请输入第一个字符:"))
    num2 = int(input("请输入第二个字符:"))
    result = operation(num1,num2,lambda a,b:a+b)
    print(result)
    
    #运行结果:
    请输入第一个字符:2
    请输入第二个字符:3
    5

    简单应用(二):

    #列表中的字典元素进行排序——lambda表达式
    
    students = [
        {"name":"Joe","age":"18"},
        {"name":"Tom","age":"20"},
        {"name":"Susan","age":"16"}
    ]
    
    students.sort(key=lambda x:x["name"])       #对字典按照关键字name排序
    print(students)
    
    #运行结果:
    [{'age': '18', 'name': 'Joe'}, {'age': '16', 'name': 'Susan'}, {'age': '20', 'name': 'Tom'}]

    8、递归函数



    代码示例:

    #函数的嵌套
    def test1():
        print("in test1...")
    
    def test2():
        test1()
        print("in test2...")
    
    def test3():
        test2()
        print("in test3...")
    
    test3()
    
    #运行结果:
    in test1...
    in test2...
    in test3...

    #递归函数
    
    def func(n):
        print("进入第%d层梦"%n)
        if n ==3:
            print("进入潜意识区")
        else:
            func(n+1)
        print("从第%d层梦中醒来"%n)
    
    func(1)
    
    #运行结果:
    进入第1层梦
    进入第2层梦
    进入第3层梦
    进入潜意识区
    从第3层梦中醒来
    从第2层梦中醒来
    从第1层梦中醒来

    应用:求阶乘

    #阶乘——利用while
    
    i = 1
    num = 1
    while i <= 4:
        num = num*i
        i+=1
    
    print(num)
    
    #阶乘——利用递归
    
    def func01(n):
        if n ==1:
            return 1
        return n*func01(n-1)
    
    print(func01(4))
    
    #运行结果:
    24
    24

    利用递归实现阶乘的原理过程:


    9、常用内置函数


    示例代码:

    #abs()——绝对值函数
    num = -1
    print(abs(num))
    
    #sorted()——排序函数
    list01 = [1,4,2,7,9,3]
    print(sorted(list01))       #由小到大排序
    print(sorted(list01,reverse=True))      #由大到小排序
    
    #sum()——求和
    print(sum(list01))
    
    #round()——四舍五入,获取指定位数的小数
    print(round(3.1415926,2))
    
    #pow()——乘方数(幂)
    print(pow(2,3))
    
    #isinstance——类型判断
    num1 = 5
    print(isinstance(num1,int))
    
    #eval()——执行表达式或字符串作为运算
    print(eval("1+3"))
    
    #exec()——执行Python语句
    exec('print("Hello")')
    
    #运行结果:
    1
    [1, 2, 3, 4, 7, 9]
    [9, 7, 4, 3, 2, 1]
    26
    3.14
    8
    True
    4
    Hello

    10、高阶函数


    示例代码:

    #常用高阶函数
    
    #map()
    num1 = map(lambda x:x*2,[1,2,3,4,5])
    print(num1)
    for i in num1:      #遍历map对象的内容
        print(i,end=" ")
    
    print()
    
    #filter()
    num2 = filter(lambda x:x%2 == 1,[1,2,3,4,5,6,7,8,9,10])
    print(num2)
    for j in num2:      #遍历filter对象的内容
        print(j,end=" ")
    
    print()
    
    #reduce()
    from functools import reduce
    print(reduce(lambda x,y:x+y,[1,2,3,4],10))  #10是起始值
    
    #运行结果:
    <map object at 0x0059F730>
    2 4 6 8 10 
    <filter object at 0x0059F890>
    1 3 5 7 9 
    20

    name = ["joe","jack","TOM","suSAN"]
    age = [17,18,20,15]
    sex = ["M","M","M","F"]
    
    #案例一——格式化英文名。首字母大写,其他小写
    names = map(lambda t:t[0:1].upper()+t[1:].lower(),name)
    for stu_name in names:
        print(stu_name,end=" ")
    
    print()
    
    #案例二——将三个序列结合到一起,形成一个集合
    newStu = map(lambda n,a,s:(n,a,s),name,age,sex)
    student = []
    for tup in newStu:
        student.append(tup)
    
    print(student)
    
    #案例三——过滤性别为男的用户
    males = filter(lambda x:x[2] == "M",student)
    man = []
    for m in males:
        man.append(m)
    
    print(man)
    
    #案例四——求性别为男的用户的平均年龄
    from functools import reduce
    man_count = len(man)
    total_age = reduce(lambda x,y:x+y[1],man,0)
    print("总年龄:",total_age)
    print("平均年龄:%.2f" %(total_age/man_count))
    
    #运行结果:
    Joe Jack Tom Susan 
    [('joe', 17, 'M'), ('jack', 18, 'M'), ('TOM', 20, 'M'), ('suSAN', 15, 'F')]
    [('joe', 17, 'M'), ('jack', 18, 'M'), ('TOM', 20, 'M')]
    总年龄: 55
    平均年龄:18.33

    11、约瑟夫环

    (1)一群人围在一起坐成环状(如:N)

    (2)从某个编号开始报数(如:K)

    (3)数到某数(如:M)的时候,此人出列,下一个人重新报数

    (4)一直循环,直到所有人出列,约瑟夫环结束



    约瑟夫环实现代码:

    #约瑟夫环问题
    # n=9(总人数)  m = 3(报数) k:索引
    #k = (k+(m-1))%len(list)
    
    def func(n,m):
        #生成一个列表
        people = list(range(1,n+1))
        k = 0       #定义开始的索引
    
        #开始循环报数
        while len(people) > 2:
            k = (k+(m-1))%len(people)
            print("kill:",people[k])
            del(people[k])
            print(k)
        return people
    
    print(func(9,3))
    
    #运行结果:
    kill: 3
    2
    kill: 6
    4
    kill: 9
    6
    kill: 4
    2
    kill: 8
    4
    kill: 5
    2
    kill: 2
    1
    [1, 7]

    12、函数重载

    在Python中,没有函数重载,若非要使用函数重载,则后边的同名函数会覆盖掉前面的函数。

    #函数重载
    def test(x):
        print(x)
    
    def test(x,y):
        print(x+y)
    
    #test(1)  #出错
    test(1,2)   #覆盖test(x)
    
    #运行结果:
    3
    13、函数的嵌套和闭包

    (1)函数嵌套:在函数内部再定义新的函数

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    # Author:ZhengzhengLiu
    
    #函数嵌套
    def test():
        def test1():
            def test2():
                print("hello")
            return test2
        return test1
    
    
    res = test()      #test函数返回值res是一个函数,等价于res ==> test1
    re = res()       #res() ==>test1()  ,test1函数返回值re是一个函数,re==>test2
    re()            #re() ==> test2()
    
    #运行结果:
    hello
    (2)闭包:内部函数可以取到外部函数的局部变量

    #闭包:内部函数可以取到外部函数的局部变量
    def test(x):
        def test1(y):
            def test2(z):
                print(x+y+z)
            return test2
        return test1
    
    res = test(10)
    re = res(20)
    re(30)
    
    #运行结果:
    6

    14、装饰器

    (1)形象举例:照片与相框


    照片:被装饰的对象,相框:装饰对象。

    装饰作用:动态扩展装饰,即:不会改变被装饰的对象(照片)的内容,只是动态改变装饰的对象(相框)。

    (2)装饰器修饰无参数的函数

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    # Author:ZhengzhengLiu
    
    #装饰器——日志管理
    def log(func):              #log(func)==> func = delete(delete函数作为实参传入到func)
        def warp():
            print("logger strating...")
            func()          #运行delete
            print("logger ending...")
    
        return warp
    
    @log   #用log来装饰delete,等价于delete = log(delete) = warp
    def delete():
        print("deleting...")
    
    delete()            #执行warp
    
    #运行结果:
    logger strating...
    deleting...
    logger ending...

    (3)装饰器修饰有参数和返回值的函数

    #装饰器修饰有参数、有返回值的函数
    def log(func):              #log(func)==> func = delete(delete函数作为实参传入到func)
        def warp(*args,**kwargs):
            print("logger strating...")
            res = func(*args,**kwargs)          #运行delete
            print(res)
            print("logger ending...")
    
        return warp
    
    @log   #用log来装饰delete,等价于delete = log(delete) = warp
    def delete(name,age):
        print("deleting...")
        print(name,age)
        return "delete success"
    
    delete("liu",20)            #执行warp
    
    #运行结果:
    logger strating...
    deleting...
    liu 20
    delete success
    logger ending...

    (4)装饰器自身带有参数

    #装饰器带有参数
    def log(i):
        def warp1(func):
            def warp2(*args,**kwargs):
                print("logger strating...")
                if i>0:
                    print("logging success...")
                    func(*args, **kwargs)
                else:
                    print("logging failed...")
    
                print("logger ending...")
    
            return warp2
        return warp1
    
    @log(1)
    def delete():
        print("deleting...")
    
    delete()
    
    #运行结果:
    logger strating...
    logging success...
    deleting...
    logger ending...

    #装饰器带有参数
    def log(i):
        def warp1(func):
            def warp2(*args,**kwargs):
                print("logger strating...")
                if i>0:
                    print("logging success...")
                    func(*args, **kwargs)
                else:
                    print("logging failed...")
    
                print("logger ending...")
    
            return warp2
        return warp1
    
    @log(-1)
    def delete():
        print("deleting...")
    
    delete()
    
    #logger strating...
    logging failed...
    logger ending...

    15、迭代器

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    # Author:ZhengzhengLiu
    
    #迭代器——笛卡尔积
    
    import itertools
    
    x = range(1,6)
    coml = itertools.combinations(x,3)   #排列
    coml2 = itertools.permutations(x,4)  #组合
    
    y = ["a","b","c"]
    
    coml3 = itertools.product(x,y)  #笛卡尔积
    
    coml4 = itertools.chain(coml,coml2,coml3)
    for h in coml4:
        print(h)
    运行结果:

    (1, 2, 3)
    (1, 2, 4)
    (1, 3, 4)
    (2, 3, 4)
    (1, 2, 3, 4)
    (1, 2, 4, 3)
    (1, 3, 2, 4)
    (1, 3, 4, 2)
    (1, 4, 2, 3)
    (1, 4, 3, 2)
    (2, 1, 3, 4)
    (2, 1, 4, 3)
    (2, 3, 1, 4)
    (2, 3, 4, 1)
    (2, 4, 1, 3)
    (2, 4, 3, 1)
    (3, 1, 2, 4)
    (3, 1, 4, 2)
    (3, 2, 1, 4)
    (3, 2, 4, 1)
    (3, 4, 1, 2)
    (3, 4, 2, 1)
    (4, 1, 2, 3)
    (4, 1, 3, 2)
    (4, 2, 1, 3)
    (4, 2, 3, 1)
    (4, 3, 1, 2)
    (4, 3, 2, 1)
    (1, 'a')
    (1, 'b')
    (1, 'c')
    (2, 'a')
    (2, 'b')
    (2, 'c')
    (3, 'a')
    (3, 'b')
    (3, 'c')
    (4, 'a')
    (4, 'b')
    (4, 'c')
    





关键字