zoukankan      html  css  js  c++  java
  • 02

    函数

    概念

    函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段。

    函数的返回值 

    return [表达式] 语句用于退出函数,选择性地向调用方返回一个表达式。不带参数值的return语句返回None。

    # return a,b,c等价于 return (a,b,c)
    def test():
        a,b = 10,20
        return a,b
    print(test())

    不定长参数传递

    加了星号(*)的变量args会存放所有未命名的变量参数,args为元组;

    而加**的变量kwargs会存放命名参数,即形如key=value的参数, kwargs为字典。

    def function(a,b,*args,**kwargs):#装箱
        print(a,b)
        print(args)#元组存放
        print(kwargs)#字典存放
    A = (33,44,55)
    B = {"name":"jerry","age":6}
    function(11,22,*A,**B)        #拆包元组和字典

    全局变量

    在python中,创建变量时默认是定义新的变量(局部变量),除非显式声明global。

    对于不可变对象(数值,字符串,元祖)的全局变量来说,因其指向的数据不能修改,所以不使用global时无法修改全局变量。

    a = 1
    def f():
        a += 1    # a = a+1,默认局部变量,变量a没有指向,就被引用计算,故报错
        print(a)
    f()
    
    UnboundLocalError: local variable 'a' referenced before assignment

    对于可变对象(比如list和dictionary)的全局变量来说,因其指向的数据可以修改,所以不使用global时也可修改全局变量。

    a = [1,2,3]
    def f():
        a.append(4)  # 对可变对象的全局变量a的操作,id相同
    f()
    print(a)
    
    #结果:[1, 2, 3, 4]

    函数传递参数类型

    函数传递参数类型,引用传递or值传递。

    """对变量赋值时的地址变化"""
    a = [1,2,3]
    b = [1,2,3]
    c = 1
    d = 1
    
    print(id(a))    #2190918037640
    print(id(b))    #2190920543560    
    print(id(c))    #1929604576 多个变量会指向同一个地址
    print(id(d))    #1929604576 

    实例1

    a = 1
    print(id(a))        #1929604576
    def function(b):
        print(id(b))    #1929604576 引用传递,指向关系相同
        b += 1          #判断变量b是否可修改,不是则默认执行b = b+1
        print(b)        #2
        print(id(b))    #1929604608 变量b改变指向(不可变对象)
    function(a)
    print(a)            #1

    实例2

    a = [1,2,3]                 a = [1,2,3]
    def function(b):            def function(b):
        b = b+[4]               b += [4]   #和b.append(4)结果相同
        print(b)                print(b)    
    function(a)                 function(a) 
    print(a)                    print(a) 
    
    #结果:[1, 2, 3, 4]          结果:[1, 2, 3, 4]
    #     [1, 2, 3]                  [1, 2, 3, 4]

    总结:赋值相当于变量指向了新的地址(+=除外), 在python中,不可变对象是共享的,创建可变对象永远是分配新地址。

    缺省参数

    注意:带有默认值的参数一定要位于参数列表的最后面。

    def test(a,b=12,c=20):
        pass
    test(10,c=10)  #默认b=12,test(10,12,10) 

    默认参数的坑

    def func(x,l=list()):
        for i in range(x):
            l.append(i*2)
        print(l)
    
    func(2)             #[0, 2]
    func(3,[1,2,3])     #[1, 2, 3, 0, 2, 4]
    func(3)             #[0, 2, 0, 2, 4]
    func(4)             #[0, 2, 0, 2, 4, 0, 2, 4, 6]
    func(3,[1,2,3])     #[1, 2, 3, 0, 2, 4]

     匿名函数

    语法:变量 = lambda 参数:返回值

    ls = lambda  x:x+2
    print(ls(5))
    #结果:7

    内置函数:eval()将字符串str当成有效的表达式来求值并返回计算结果。

    def test(a,b,fun):
        return fun(a,b)    #匿名函数的调用
    lamb = input("请输入匿名函数:")
    test(10,20,eval(lamb))            #eval()原样输出
     #请输入匿名函数: lambda x,y:x+y
     #结果:30

    匿名函数的应用

    # 取出最大工资对应的人名
    
    salaries = {
        'qiu': 2000,
        'xi': 30000,
        'qiuxi': 2500,
        'rufeng': 3000
    }
    
    def func(k):
        return salaries[k]
    
    print(max(salaries,key=func))   # xi
    
    # 1. 将可迭代对象salaries变成迭代器对象iter_obj
    # 2. next(iter_obj)得到一个人名,然后将该人名当作参数传给key指定的函数,然后调用函数将函数的返回值当作比较依据
    # 3. 比较大小,取出最大值对应的人名
    
    # 上面的函数还可以用匿名函数来实现
    print(max(salaries, key=lambda k: salaries[k]))
    # 同样,取出最小的使用函数min
    print(min(salaries, key=lambda k: salaries[k]))
    max与lambda

    内置函数:sorted(),排序并返回新的值

    a = {k1:v1,k2:v2}
    # 从大到小
    print(sorted(salaries, key=lambda k: a[k], reverse=True))
    # 从小到大
    print(sorted(salaries, key=lambda k: a[k]))

    内置函数:map()提供的函数对指定序列做映射。

    map(function, iterable, ...)

    name = [a,b,c,d]
    # 列表生成式
    new_names = [name+'_1' for name in names]
    print(new_names)
    
    # map+匿名函数
    res = map(lambda x: x+'_1', names)
    print(res)  #打印函数地址
    print(list(res))

    functools模块函数 :reduce()对参数序列中元素进行累积。

    reduce(function, iterable[, initializer])

    from functools import reduce
    reduce(lambda x, y: x+y, [1,2,3,4,5])  # 使用 lambda 匿名函数
    #结果:15

    内置函数:filter() 函数用于过滤序列,过滤掉不符合条件的元素,返回由符合条件元素组成的新列表。

    filter(function, iterable)

    a = [1,2,3,4,5,6,7,8]
    b = filter(lambda x:x%2==0,a) #满足函数条件的留下,即返回值是True,b为迭代器对象
    print(list(b))

    闭包

    函数的嵌套

    #函数的嵌套定义
    def test1():
        print('-------text1-------')
        def test2():
            print('-------text2-------')
        return test2()
    # 嵌套的内部函数只能在test1()里面调用
    test1()
    #结果
    #-------text1-------
    #-------text2-------

    作用域

    全局变量

    num = 1
    def fun1():
        global num  # 需要使用 global 关键字声明
        print("全局变量:",num)
        num = 12
        print("修改后的值",num)
    
    fun1()
    print("全局变量:",num)
    #全局变量: 1
    #修改后的值 12
    #全局变量: 12

    nonlocal关键字用来在函数或其他作用域中使用外层(非全局)变量.

    def fun():
        a = 100
        def fun_in():
            nonlocal a    #嵌套作用域enclosing,外层非全局作用域
            # 创建的变量,默认为局部变量,在引用前赋值操作就会报错(a = a+20)
            a =20+a
            return a
        return fun_in()
    print(fun())

    LEGB规则查找变量

    locals -> enclosing function -> globals -> builtins

    即:在局部找不到,便会去局部外的局部找(例如闭包),再找不到就会去全局找,再者去内建中找。

    闭包函数

    闭包:在一个内部函数里对外部作用域(不包括外部函数的外部作用域)的变量进行引用,内部函数就会被认为是闭包。

    注意:1、函数名指向的地址变量是可变对象。

       2、闭包函数可以保留其用到的变量的引用。

    def test():
        num = 100
        def test_in(a):
            a = a+num
            print(a)
        return test_in
    re = test()    #num=100,并返回了test_in函数的引用
    re(100)

    带参数的闭包

    def test(a,b):
        def test_in(x):
            print(a*x+b)
        return test_in
    
    ls1 = test(2,4)    
    ls1(3)          #10
    ls2 = test(3,5)
    print(id(ls1))        #验证ls1和ls2是否指向同一个地址ID:1967395159032
    print(id(ls2))
    ls2(4)                            #17
    ls1(4)                            #12

    装饰器

    装饰器是用来为被装饰对象添加新功能的一种工具

    必须遵循:

    1、不能修改被装饰对象的源代码

    2、不能修改被装饰对象的调用方式

    通用装饰器(带返回值和参数)

    import time
    
    current_user={'login':False}#全局变量
    
    def outter(func):  #传递被装饰函数地址
        def wrapper(*args,**kwargs): #传递被装饰函数的参数
            #条件判断
            if current_user['login']:
                return func(*args,**kwargs)
    
            user=input('username>>>: ').strip()
            pwd=input('password>>>: ').strip()
            if user == 'tom' and pwd == '123':
                current_user['login']=True
                return func(*args,**kwargs)
        return wrapper
    
    @outter
    def index():
        time.sleep(1)
        print('welcome to index')
        return 1234
    
    @outter
    def home(name):
        time.sleep(2)
        print('welcome %s to home page' %name)
    
    index()   # 等价于 index = outter(index)
    home('tom')

    装饰器带参数

    带有参数的装饰器,能够起到在运行时,有不同的功能

    #如果arg=ok,则执行调用两次,否则调用一次
    def fun_arg(arg):
        def func(fun):
            def func_in(*args,**kwargs):
                print("-----记录日志-arg=%s----"%arg)
                if arg=="ok":
                    fun(args)
                    return fun(args)
                else:
                    return fun(args)
            return func_in
        return func
    
    
    #1. 先执行func_arg("ok")函数,这个函数return 的结果是func这个函数的引用
    #2. @func
    #3. 使用@func对test1和test2进行装饰
    
    @fun_arg("ok")
    def test1(a):
        print("-----test1----%d----"%a)
        return "test1"
    
    @fun_arg("haha")
    def test2(b):
        print("-----test2----%d--"%b)
        return "test2"
    
    #调用并返回
    ret1 = test1(10)
    ret2 = test2(20)
    print(ret1,ret2)
    '''
    -----记录日志-arg=ok----
    -----test1----10----
    -----test1----10----
    -----记录日志-arg=haha----
    -----test2----20--
    test1 test2
    '''

    多个装饰器

    def makeb(f1):
        print("--------mb----------")
        def makeb_in():
            print("------1------")
            return "<b>"+ f1()+"</b>"
        return makeb_in
    
    def makei(f2):
        print("--------mi----------")
        def makei_in():
            print("------2------")
            return "<i>"+ f2()+"</i>"
        return makei_in
    #f1----->f2----->test   test----->makeb_in
    #语法糖
    @makeb
    @makei
    def test():
        print("------3------")
        return "hello world!"
    
    """
    执行流程:   1.f2指向test,test指向makei_in
                2.f1指向test,即指向makei_in,test指向了makeb_in
    """
    
    # test = makeb(makei(test))
    re = test()
    print(re)
    ''' 
    结果:
    --------mi----------
    --------mb----------
    ------1------
    ------2------
    ------3------
    <b><i>hello world</i></b>

    类装饰器

    #__call__方法使类变成可调用的对象
    class Test(object):
        def __init__(self, func):
            print("__init__初始化---")
            print("func name is %s" % func.__name__)
            #保存func变量
            self.__func = func
    
        def __call__(self):
            print("__call__执行装饰器---")
            self.__func()
    
    
    @Test       #  test = Test(test)
    def test():
        print("----test---")
    
    test()
    
    '''
    结果:
    __init__初始化---
    func name is test
    __call__执行装饰器---
    ----test---
    
    '''
  • 相关阅读:
    P85 实战练习
    Java语句及控制台输入
    P62 实战练习
    运算符、数据类型转换和注释
    Java变量与常量
    Java语法初步实际应用
    JQ 练习题
    JQ 特效下拉列表 写出与css一样的效果
    JQ 全选设定与设置选中
    JQ JSON数据类型
  • 原文地址:https://www.cnblogs.com/liulyuan/p/9885858.html
Copyright © 2011-2022 走看看