Python学习笔记——函数

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# 函数的作用:
    # 1.代码重用
    # 2.流程分解


# 例1:函数的定义和调用
    def bar():
        print('hello world')
    bar()
    
# 例2:函数参数
    2.1 形参与实参
        def add(x,y):  #x,y是形参
            print (x+y)
        add(3,5)        #3,5是实参
    2.2参数顺序
        def  people(name,age):
            print ('Name:',name)
            print ('Age:',age)
        people('Tom',23) #参数的传入是有顺序的。形参与实参的顺序要一一对应
    2.3关键字参数
        def  people(name,age):
            print ('Name:',name)
            print ('Age:',age)
        people(age=12,name='Bob')
    2.4默认参数
        def  people(name,age,sex='boy'):
            print ('Name:',name)
            print ('Age:',age)
            print ('Sex:',sex)
        people('Tom',23)
    2.4不定长参数
        >>> def bar(*arg):
        ...     print(arg)
        ...
        >>> bar(1,2,3)
        (1, 2, 3)
    2.5**kwargs 接收键值对参数
        >>> def bar(**kwargs):
        ...     print (kwargs)
        ...
        >>> bar(name='Tom',age=18)
        {'name': 'Tom', 'age': 18}
        
    2.6参数的位置
        >>> def bar(name,age,sex='boy',*args,**kwargs):
        ...     print(name,age,sex,args,kwargs)    
        Tom 18 1 (2, 3, 4) {'city': "xi'an"}
        >>> bar('Tom',18,1,2,3,4,city="xi'an")
        Tom 18 1 (2, 3, 4) {'city': "xi'an"}
        >>> bar('Tom',18,'boy',1,2,3,4,city="xi'an")
        Tom 18 boy (1, 2, 3, 4) {'city': "xi'an"}
        
# 例3:函数的多态
    def add(x,y):
        print (x+y)

    add(3,5)
    add('hello','world')

# 例4:嵌套函数
    def bar():
        def foo():
            print("hello world")
        foo()
    bar()

# 例5:作用域法则LEGB
    # L-Local(function);函数内的名字空间
    # E-Enclosing function locals;外部嵌套函数的名字空间(例如closure)
    # G-Global(module);函数定义所在模块(文件)的名字空间
    # B-Builtin(Python);Python内置模块的名字空间

# 例6:global语句
    x = 88
    def bar():
        global x
        x = 99
    bar()
    print (x)

# 例7:nonlocal ————用于嵌套函数中
    def bar():
        x = 1
        def foo():
            nonlocal x
            x += 1
        foo()
        print(x)

    bar()


# 例8:闭包(closure):在一个内部函数对在外部的作用的作用域进行一个引用,那么内部函数就是一个闭包

    >>> def maker(N):
    ...     def action(X):    #一个内部函数
    ...             return X ** N  #N为上级函数的一个变量
    ...     return action
    ...
    >>> f = maker(2)
    >>> f
    <function maker.<locals>.action at 0x000002C47A1E2A60>
    >>> f(3)
    
    闭包的三个特点:
        1.闭包函数必须有内嵌函数
        2.内嵌函数需要引用该嵌套函数上一级namespace中的变量
        3.闭包函数必须返回内嵌函数
# 例9:函数的返回值
    9.1 默认返回None
        >>> def bar():
        ...     print ("hello")
        ...
        >>> f = bar()
        hello
        >>> print(f)
        None
    
    9.2 指定返回值
        >>> def bar():
        ...     print("hello")
        ...     return 1
        ...
        >>> f = bar()
        hello
        >>> print(f)
        1
    9.3    返回计算结果
        >>> def bar(x,y):
        ...     return x + y
        ...
        >>> f = bar(1,2)
        >>> print(f)
        3
    9.4 结束函数
        >>> def bar():
        ...     print("hello")
        ...     return 1
        ...     print("world")
        >>> bar()
        hello
        1
    9.5 返回元组
        >>> def bar(x,y):
        ...     return x,y
        ...
        >>> bar(1,2)
        (1, 2)
    return的作用:
        1.结束函数
        2.返回某个对象
        
# 例10:三元函数
    >>> print('hello') if True else False
    hello    
    
# 例11:高阶函数

    11.1 变量名可以指向函数
        >>> abs(-10)
        10
        >>> f = abs
        >>> f(-10)
        10
    11.2 函数名可以作为其他函数的参数    
        >>> def bar(x,y,f):
        ...     return f(x)+f(y)
        ...
        >>> bar(-5,-3,abs)
        8
    11.3 函数名可以作为返回值
        >>> def bar():
        ...     def foo():
        ...         return "hello"
        ...     return foo
        ...
        >>> bar()
        <function bar.<locals>.foo at 0x00000194EED32A60>
    
# 例12:装饰器(Decorator):1.在代码运行期间增加功能;2.不改变源代码
        1.在运行期间增加新功能
        def hello():
            print("hello")

        def show_time(func):
            print("------------")
            func()
            print("------------")

        show_time(hello)
        # 或者如下
        # hello = show_time(hello)
        # hello
        # 但调用方式还是发生了改变
        但是这样改变个源函数的调用方式
        2.让hello接收函数名
        #如果把一个函数名赋值给hello,hello()就可以执行函数了,
        #关键问题是如何让show_time(hello)作为函数名赋值给hello
        #想想高阶函数中函数名可以作为返回值返回的特性
        #可以吧上述的函数改为如下
        def hello():
            print("hello")

        def show_time(func):
            def inner():
                print("------------")
                func()
                print("------------")
            return inner    #此时如果调用show_time,返回的就是inner函数的函数名
            
        hello=show_time(hello) #将inner函数赋值给hello
        hello()  #实际执行的是inner函数
        3.@bar
        #在python中hello=show_time(hello)可以写为@show_time,如下:    
        def show_time(func):
            def inner():
                print("------------")
                func()
                print("------------")
            return inner

        @show_time
        def hello():
            print("hello")
            
        hello()
        4.装饰器的参数
        def show_time(func):
            def inner(name):
                print("------------")
                func(name)
                print("------------")
            return inner

        @show_time
        def hello(name):
            print("hello",name)

        hello('Bob')
        5.函数中嵌套装饰器
        import time
        def logger(flag=''):
            def show_time(func):
                def inner(*args,**kwargs):
                    start = time.time()
                    time.sleep(1)
                    func(*args,**kwargs)
                    end = time.time()
                    print('running time:',end - start)
                    if flag == 'true':
                        print('this is loggger')
                return inner
            return show_time

        @logger('true')
        def foo(*args,**kwargs):
            sums = 0
            for i in args:
                sums += i
            print(sums)

        @logger()
        def bar():
            print('bar..')
            
        foo(1,2,3)
        bar()
        6.6 源函数名称的问题————functools.wraps的作用
        def show_time(func):
            def inner(name):
                print("------------")
                func(name)
                print("------------")
            return inner

        @show_time
        def hello(name):
            print("hello",name)

        print(hello.__name__)

        >>inner        
        源函数的名称变成了inner,不是原来的hello,通过引入wraps解决这个问题
        改进如下:
            from functools import wraps

            def show_time(func):
                @wraps(func)
                def inner(name):
                    print("------------")
                    func(name)
                    print("------------")
                return inner

            @show_time
            def hello(name):
                print("hello",name)

            print(hello.__name__)

            >>hello        
        6.7装饰器实例
        import sys
        from functools import wraps
        USERNAME, PASSWORD = 'root','123'
        no_login = True
        def login(func):
            @wraps(func)
            def inner(*args,**kwargs):
                global no_login
                if no_login:
                    print('您还没有登录,请登录---')
                    username = input('username:').strip()
                    password = input('password:').strip()
                    if USERNAME == username and PASSWORD == password:
                        no_login = False
                    else:
                        print('user or password is wrong !')
                        sys.exit()
                func(*args, **kwargs)
            return inner

        @login
        def home():
            print('恭喜来到京东主页')
        @login
        def phone():
            print('这里是手机专卖')
        @login
        def book():
            print('这里是图书商店')

        main = """
        1.home
        2.phone
        3.book
        请选择要进入的主页
        """
        while True:
            print(main)
            choice = input(">>:").strip()
            if  choice == '1':
                home()
            elif choice == '2':
                phone()
            elif choice == '3':
                book()
            else:
                sys.exit()    
        
        总结:装饰器三要素:LEGB、高阶函数、闭包

    

猜你喜欢

转载自www.cnblogs.com/rockley/p/9088338.html
今日推荐