美文网首页Python
Python学习(四)

Python学习(四)

作者: BlainPeng | 来源:发表于2017-02-05 11:34 被阅读20次

    高阶函数

    把函数作为参数传入,这样的函数称为高阶函数

    from math import sqrt
    
    def test(x, *func):
        ret = list(f(x) for f in func)
        return ret
    
    print(test(4, abs, sqrt))       # [4, 2.0]
    

    map函数

    map函数接收两个参数,第一个是一个函数,第二个是Iterable,map将传入的函数依次作用到Iterable中的每个元素,并把结果作为新的Iterator返回

    # 将名字变为首字母大写,其他小写
    def test(elem):
    return elem.capitalize()
    
    print(list(map(test, ['adam', 'LISA', 'barT'])))        # ['Adam', 'Lisa', 'Bart']
    

    reduce函数

    reduce函数接收两个参数,第一个是一个函数,第二个是一个序列,reduce将传入的函数依次作用到Iterable中的每个元素,并把每一个元素的结果与下一个元素作累积计算

    from functools import reduce
    
    def str2int(s):
        def char2num(c):
            # 根据dict中的key来获取value
            return {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}[c]
    
        def f(x, y):
            return x * 10 + y
    
        return reduce(f, map(char2num, s))
    
    
    print(str2int("13579"))             # 13579
    print(type(str2int("13579")))       # <class 'int'>
    

    上面是我们自己写的一个str转int的函数,虽然系统给我们提供了。我们还可以写一个str转float的函数来加强reduce与map的理解

    def str2float(s):
        # 获取小数点的位置
        point = s.index(".")
        # 整数部分
        num1 = map(int, s[:point])
        # 小数部分
        num2 = map(int, s[point + 1:])
        # 算出小数有多少位
        num3 = 1 / 10 ** len(s[point + 1:])
    
        def f(x, y):
            return x * 10 + y
    
        return reduce(f, num1) + reduce(f, num2) * num3
    
    
    print(str2float("126.789"))                 # 126.789
    print(type(str2float("126.789")))           # <class 'float'>
    

    filter函数

    filter()也接收一个函数和一个序列,把传入的函数依次作用于每一个序列的元素,然后根据返回值是True还是False来决定保留还是丢弃该元素。filter()函数返回的是一个Iterator

    def func(elem):
    return elem % 2 == 0
    
    
    print(list(filter(func, list(range(1, 11)))))       # [2, 4, 6, 8, 10]
    

    sorted函数

    sorted()可以对一个序列进行排序,也可以接收一个key来实现自定义的排序

    l = [36, 5, -12, 9, -21]
    print(sorted(l))                            # [-21, -12, 5, 9, 36]  从小到大
    print(sorted(l, reverse=True))            # [36, 9, 5, -12, -21]    从大到小
    print(sorted(l, key=abs))                  # [5, 9, -12, -21, 36]   按绝对值的大小排序
    

    对字符串进行排序。对字符串排序是按照ASCII大小比较的,由于'Z'<'a',大写字母Z会排在小写字母a的前面,所以可以过字符串的lower方法将先把字符串都变成小写(也可以都变成大写),再比较

    L = [('Bob', 75), ('Adam', 92), ('Bart', 66), ('Lisa', 88), ('Zoo', 40)]
    def by_name(item):
        return item[0].lower()
    print(sorted(L, key=by_name))       # [('adam', 92), ('Bart', 66), ('Bob', 75), ('Lisa', 88), ('Zoo', 40)]
    

    返回函数

    上面学习了将函数作为参数的高阶函数,也可以把函数作为结果值返回

    def test(*args):
        def f():
            ret = 0
            for item in args:
                ret += item
            return ret
        return f
    result = test(1, 3, 5, 7, 9)
    # 返回回来的是一个函数,必须调用才能获取到返回值
    print(result())         # 25
    print(result)           # <function test.<locals>.f at 0x101a7ac80>
    

    我们在函数test中定义了函数f,内部函数f可以引用外部函数test的的参数和局部变量;当函数test返回函数f时,相关参数和变量都保存在返回的函数中,这种称为闭包(Closure)。但这里有一个问题需要注意:

    def test2():
        fs = []
        for i in range(1, 4):
            def f():
                return i * i
    
            fs.append(f)
        return fs
    f1, f2, f3 = test2()
    print(f1())     # 9
    print(f2())     # 9
    print(f3())     # 9
    

    这里的结果为什么都是9?

    原因在于返回的函数引用了变量i,但它并非立即执行,等到3个函数都返回时,它们所引用的变量i已经变成了3,因此最终结果都是9。

    所以,返回闭包时牢记一点:返回函数不要引用任何循环变量,或者后续会发生变化的变量

    若一定要引用循环变量怎么办呢?可以这样做:

    def test3():
        fs = []
    
        def f(x):
            def g():
                return x * x
    
            return g
    
        for i in range(1, 4):
            fs.append(f(i))         # f(i)立即被执行,因此当前i的值被传入到f()函数中
        return fs
    f4, f5, f6 = test3()
    print(f4())         # 1
    print(f5())         # 4
    print(f6())         # 9
    

    重新创建了一个函数,用该函数的参数与循环变量当前的值进行绑定,无论后绪循环变量如何变,已绑定的函数参数的值不变

    匿名函数

    结构:

    lambda 参数名 : 表达式    或者  lambda : 表达式
    

    如:

    print(list(map(lambda x: x * x, [1, 2, 3])))        # [1, 4, 9]
    def test(x, y):
        return lambda: x + y
    print(test(1, 2)())                              # 3
    

    装饰器

    在代码运行期间动态增加功能的方式称之为装饰器(Decorator)

    # 调用函数time时,输出log日志
    
    import functools
    
    def log(func):
        # 把原始函数的__name__等属性复制到wrapper()函数中,否则返回出去的__name__属性值为wrapper
        @functools.wraps(func)      
        def wrapper(*args, **kw):
            print("call %s():" % func.__name__)
            return func(*args, **kw)
    
        return wrapper
        
    # 这里相当于执行:time = log(time)    
    @log 
    def time():
        print("2017-2-5")
           
    time()                  # call time():  2017-2-5
    print(time.__name__)      # time
    

    自定义一个输出log文本的装饰器

    def log2(text):
        def decorator(func):
            @functools.wraps(func)
            def wrapper(*args, **kw):
                print("%s ,%s():" % (text, func.__name__))
                return func(*args, **kw)
    
            return wrapper
    
        return decorator
    
    # 这里相当于执行:time2 = log("execute")(time2)
    @log2("execute")   
    def time2():
        print("2017-1-5")
        
    time2()                 # execute ,time2(): 2017-1-5
    print(time2.__name__)     # time2
    

    首先执行的是log("execute"),返回decorator,再调用返回的函数,参数就是time2,返回值最终是wrapper函数

    偏函数

    在学习函数参数类型的时候,为了降低函数的调用难度,我们可以设置默认参数。而偏函数也可以做到。
    偏函数的作用就是:把一个函数的某些参数给固定住(也就是设置默认值),返回一个新的函数,调用这个新函数会更简单

    def test(x, sqrt=2):
    return x ** sqrt
    
    test2 = functools.partial(test, sqrt=3)
    print(test2(3))         # 27
    

    相关文章

      网友评论

        本文标题:Python学习(四)

        本文链接:https://www.haomeiwen.com/subject/iiteittx.html