zoukankan      html  css  js  c++  java
  • python函数和lambda表达式学习笔记

    1. python函数

    不同于其他语言,python支持函数返回多个值
    为函数提供说明文档:help(函数名)或者函数名.doc

    def str_max(str1, str2):
        '''
        比较两个字符串的大小
        '''
        str = str1 if str1 > str2 else str2
        return str
    help(str_max)
    print(str_max.__doc__)
    
    Help on built-in function len in module builtins:
    len(obj, /)
        Return the number of items in a container.
    
    out[2]:'Return the number of items in a container.'
    

    2. python函数值传递和引用(地址)传递

    1. 值传递:适用于实参类型为不可变类型(字符串、数字、元组);
    2. 引用传递:适用于实参类型不可变类型(列表、字典);
    3. 值传递和引用传递的区别:函数参数进行值传递后,若形参的值发生改变,不会影响实参的值;而函数参数进行引用传递后,改变形参的值,实参的值一会一同改变。
    def demo(obj)
        obj += obj
        print("形参值为:",obj)
    print("---值传递---")
    a = "孙悟空"
    print("a的值为:",a)
    demo(a)
    print("实参值为:",a)
    print("---引用传递---")
    a = [1, 2, 3]
    print("a的值为:",a)
    demo(a)
    print("实参值为:",a)
    
    运行结果为:
    -------值传递-----
    a的值为: 孙悟空
    形参值为: 孙悟空孙悟空
    实参值为: 孙悟空
    -----引用传递-----
    a的值为: [1, 2, 3]
    形参值为: [1, 2, 3, 1, 2, 3]
    实参值为: [1, 2, 3, 1, 2, 3]
    

    3. python函数参数传递机制

    1. 值传递
      所谓值传递,实际上就是将实际参数值的副本(复制品)传入函数,而参数本身不会受到任何影响。
    2. 引用传递
      如果实参的数据类型是可变对象(列表、字典),则函数参数的传递方式将采用引用传递方式。引用传递的底层实现,采用的依然是值传递的方式。

    4. python函数关键字参数

    def dis_str(str1, str2):
        print("str1:", str1)
        print("str2:", str2)
    #位置参数
    dis_str("python", "c++")
    #关键字参数
    dis_str(str2 = "c++", str1 = "python")
    #混合参数
    dis_str("c++", str2 = "python")
    #混合传参,关键字参数必须位于所有的位置参数之后
    

    5. python函数默认参数

    注意:指定有默认值的形式参数必须在所有没默认参数的最后。

    def dis_str(str1, str2 = "python"):
        print("str1:", str1)
        print("str2:", str2)
    dis_str("c++")
    dis_str("c++", "python")
    

    python中可以使用"函数名.defaults"查看函数的默认值参数的当前值,其返回值是一个元组。

    print(dis_str.__defaults__)
    #执行结果为
    ('python',)
    

    6. python可变参数*args和**kwargs

    *args和**kwargs主要用于函数定义。你可以将不定数量的参数传递给一个函数。
    1.*args用来传递一个非键值对的可变数量的参数列表给一个函数

    def test(f_arg, *args):
        print("first normal arg:", f_arg)
        for arg in args:
            print("another arg through *args:", arg)
    test("python", "c++", "java", "c")
    #执行结果为
    first normal arg: python
    another arg through *args: c++
    another arg through *args: java
    another arg through *args: c
    

    2.**kwargs允许将不定长度的键值对,作为参数传递给一个函数。如果想在一个函数里处理带名字的参数,应该使用**kwargs

    def names(**kwargs):
        for key, value in kwargs.items():
            print("{0} == {1}".format(key, value))
    names(name = "xiaobai")
    #执行结果为
    name == xiaobai
    

    7. python逆向参数收集

    所谓逆向参数收集,指的是在程序已有列表、元组、字典等对象的前提下,把它们的元素"拆开"后传给函数的形参。
    逆向参数收集需要在传入的列表、元组参数之前添加一个星号,在字典参数之前添加两个星号。

    def test(name, message):
        print("用户是:", name)
        print("欢迎信息:", message)
    my_list = ["小白", "欢迎来到上海"]
    test(*my_list)
    #执行结果为
    用户是: 小白
    欢迎信息: 欢迎来到上海
    

    实际上,即使是可变参数,如果程序需要将一个元组传给该函数,那么同样需要使用逆向收集。

    def test(name, *nums):
        print("name参数:", name)
        print("nums参数:", nums)
    my_tuple = (1, 2, 3)
    test("小白", *my_tuple)
    test(*my_tuple)
    #执行结果为
    name参数: 小白
    nums参数: (1, 2, 3)
    #执行结果为
    name参数: 1
    nums参数: (2, 3)
    
    def test(book, price, des):
        print(book, "价格是:", price)
        print("描述信息:", des)
    my_dict = {'price':159, 'book':'西游记', 'des':'师徒四人西天取经'}
    test(**my_dict)
    #执行结果为
    西游记 价格是: 159
    描述信息: 师徒四人西天取经
    

    8. python partial偏函数

    偏函数是对原始函数的二次封装,是将现有函数的部分参数设置默认值,从而得到一个新的函数,相比原函数,偏函数具有较少的可变参数,从而降低了函数调用的难度。

    from functools import partial
    def display(name, age):
        print("name:", name, "age:", age)
    #定义偏函数
    xiaobai = partial(display, name = 'xiaobai')
    #由于name已经有默认值,因此调用偏函数时,可以不指定
    xiaobai(age = 10000)
    #执行结果为
    name: xiaobai age: 10000
    

    偏函数通过将任意数量的参数,转化为另一个带有剩余参数的函数对象,从而实现了截取函数功能的效果。

    9. python局部变量和全局变量

    1.定义全局变量的两种方式

    name = "xiaobai"
    def print_name(name):
        global age
        age = 10
        print("函数体内访问:", name, age)
    print_name(name)
    print("函数体外访问:", name, age)
    #执行结果为
    函数体内访问: xiaobai 10
    函数体外访问: xiaobai 10
    #注意:在使用global关键字修饰变量名时,不能直接给变量赋值,否则会引发语法错误。
    

    2.获取指定作用域(scope)范围中的变量

    # 1.globals()函数返回一个包含全局范围内所有变量的字典
    #全局变量
    name = "xiaobai"
    age = 10
    def test():
        #局部变量
        name1 = "xiaohei"
        age1 = 20
    print(globals())
    #执行结果为
    {..., 'name':'xiaobai', 'age':10, ...}
    
    # 2.locals()函数得到一个包含当前作用域内所有变量的字典。即在函数内部调用locals()得到包含所有局部变量的字典,在全局范围内调用locals()函数和globals()函数相同。
    # 3.vars()函数返回一个指定object对象范围内所有变量组成的字典,如果不传入object对象,vars()和locals()的作用完全相同。
    

    10. python函数的高级用法(赋值、作为其他函数的参数、作为其他函数的返回值)

    1.将函数赋值给其他变量,这样,程序中可以使用其他变量来调用该函数。

    def my_fun():
        print("正在执行my_fun函数")
    #将函数赋值给其他变量
    other = my_fun
    #间接调用my_fun()函数
    other()
    #执行结果
    正在执行my_fun函数
    

    2.将函数以参数的形式传入其他函数中。

    def add(a, b):
        return a + b
    def my_fun(a, b, dis):
        return dis(a, b)
    print(my_fun(3, 4, add))
    #执行结果
    7
    

    3.将函数作为其他函数的返回值。

    def my_fun():
        #局部函数
        def infun():
            print("调用局部函数")
        #调用局部函数
        return infun
    other_fun = my_fun()
    #调用局部的infun()函数
    other_fun()
    #执行结果
    调用局部函数
    

    11. python闭包(闭包函数或闭合函数)

    闭包函数和嵌套函数类似,不同之处在于,闭包中外部函数返回的不是一个具体的值,而是一个函数。一般情况下,返回的函数会赋值给一个变量,这个变量可以在后面被继续执行调用。

    #闭包函数,其中exponent称为自由变量
    def nth_power(exponent):
        def exponent_of(base):
            return base ** exponent
        return exponent_of #返回值是exponent_of函数
    square = nth_power(2)
    cube = nth_power(3)
    
    print(square(2))
    print(cube(2))
    

    闭包函数比普通函数多了一个__closure__属性,该属性记录着自由变量的地址。当闭包被调用时,系统就会根据该地址找到对应的自由变量,完成整体的函数调用。

    def nth_power(exponent):
        def exponent_of(base):
            return base ** exponent
        return exponent_of
    square = nth_power(2)
    print(square.__closure__)
    #执行结果
    (<cell at 0x0000019F2EA25828: int object at 0x00007FFCDBFAEF20>,)
    

    可以看到,显示的内容是一个int整数类型,这就是square中自由变量exponent的初始值。还可以看到,__closure__属性的类型是一个元组,这表明闭包可以支持多个自由变量的形式。

    12. python lambda表达式(匿名函数)

    res = lambda x, y : x + y
    

    1.对于单行函数,使用lambda表达式可以省去定义函数的过程,让代码更加简洁
    2.对于不需要多次使用的函数,使用lambda表达式可以在用完之后立即释放,提高程序执行的性能

    13. python eval()和exec()函数

    这两个函数都可以执行一个字符串形式的python代码,相当于一个python的解释器。二者不同之处在于,eval()执行完要返回结果,而exec()执行完不返回结果。

    dic={} #定义一个字
    dic['b'] = 3 #在 dic 中加一条元素,key 为 b
    print (dic.keys()) #先将 dic 的 key 打印出来,有一个元素 b
    exec("a = 4", dic) #在 exec 执行的语句后面跟一个作用域 dic
    print(dic.keys()) #exec 后,dic 的 key 多了一个
    #执行结果
    dict_keys(['b'])
    dict_keys(['b', '__builtins__', 'a'])
    

    13. python函数式编程(map(), filter(), reduce())

    1.map()函数
    map()函数对可迭代对象中的每个元素,都调用指定的函数,并返回一个map对象。
    注意:该函数返回的是一个map对象,不能直接输出,可以通过for循环或者list()函数来显式。

    nums = [1, 2, 3, 4]
    res = map(lambda x : x ** 3, nums)
    print(res)
    print(list(res))
    #执行结果
    <map object at 0x0000013B6A2A24A8>
    [1, 8, 27, 64]
    

    2.filter()函数
    filter()函数对每个可迭代对象,都使用function函数判断,并返回True或者False,最后将返回True的元素组成一个新的可遍历的集合。

    nums = [1, 2, 3, 4]
    res = filter(lambda x : x % 2 == 0, nums)
    print(res)
    print(list(res))
    #执行结果
    <filter object at 0x0000013B6A2A24E0>
    [2, 4]
    

    3.reduce()函数
    reduce()函数用来对一个集合做累积操作。
    注意:reduce()函数已经被移除,放入了functools模块。

    import functools
    nums = [1, 2, 3, 4, 5]
    res = functools.reduce(lambda x, y : x * y, res)
    print(res)
    #执行结果
    24
    

    14. 提高代码可读性和颜值的几点建议

    1. 不写重复性代码
    2. 刻意减少代码的迭代层数,尽可能让python代码扁平化
    3. 函数的粒度应该尽可能细,不要让一个函数做太多的事情
  • 相关阅读:
    Linux安装Oralce 11g问题
    Hadoop 2.X 集群安装
    Centos图形界面关闭与开启
    SecureCRT乱码
    Hadoop 1.X 集群安装
    ThinkPad E430c 开机启动
    Node.js运行端口修改
    Node.js代理设置
    Github安装过后删除右键菜单选项
    吴恩达深度学习笔记 第四章作业1
  • 原文地址:https://www.cnblogs.com/xiaobaizzz/p/12210094.html
Copyright © 2011-2022 走看看