• Python高阶用法总结


    前言: 接触python有一段时间了,从开始的看菜鸟的python教程,看了一些视频,一些书。很多人感觉python很简单,确实相比其他语言,python可能稍微简单一点,但是不能说只学了python基础语法就说自己python水平可以了。最近在阅读YOLOv3的pytorch版本源码,就遇到很多瓶颈,很多是与python相关的。所以这篇进行总结一下,收集一下所有的问题,更深入理解python高阶用法,并且尽量每个都附上例子,做一个认真的coder,bloger。

    1. lambda匿名函数

    lambda匿名函数在一些工程项目中经常出现,理解该用法是读懂项目的前提。如:

    lf = lambda x: 1 - 10 ** (hyp['lrf'] * (1 - x / epochs)) 
    

    匿名函数就是没有定义函数的名称,用来实现简单的功能。

    语法结构:lambda param_list: expression

    param_list 就是参数列表,相当于函数的参数

    expression 就是表达式,相当于函数体,用一行进行表示

    举个简单的例子:

    >>> func=lambda x, y: x+y
    >>> func(3,4)
    7
    

    应用场景:

    1.1 函数式编程

    python提供了很多函数式编程特性,如map, reduce, filter, sorted等内置函数,都支持函数作为参数。

    • map会根据提供的函数对指定序列做映射。

      • map(function, iterable, ...)

      •   >>> func2=lambda x: x**x
          >>> L=[1,2,3]
          >>> map(func2, L)
          <map object at 0x00000218C07F0080>
          >>> list(map(func2, L)) # 注意要显示内容需要转为list类型,因为py3中返回的是迭代器对象
          [1, 4, 27]
          >>>
        
      • 其中function可以使lambda函数对象,也可以是str等类型

      •   >>> L=[1,2,3,4]
          >>> list(map(str, L))
          ['1', '2', '3', '4']
          >>> list(map(float, L))
          [1.0, 2.0, 3.0, 4.0]
        
    • reduce 函数会对参数序列中元素进行累积。

      • 语法:reduce(function, iterable[, initializer])

      •   >>> reduce(lambda x, y: x+y, [1,2,3,4,5])  # 使用 lambda 匿名函数
          15
        
      • 注意python3使用前要加上:from functools import reduce , reduce函数在python3中被移除,放入了functools模块。

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

      •   filter(function, iterable)
        
      •   >>> filter(lambda x: x % 2 == 0, [1,2,3,4,5,6,7,8,9,10])
          <filter object at 0x00000218C07F0080>
          >>> list(filter(lambda x: x % 2 == 0, [1,2,3,4,5,6,7,8,9,10]))
          [2, 4, 6, 8, 10]
          >>>
        
      • 这里function智能返回true or false, 将满足true的放入最终列表。

    • sorted函数对所有可迭代的对象进行排序操作。

      • sorted(iterable, key=None, reverse=False)

      •   >>> sorted([[3,4],[2,1],[5,3],[7,4],[9,0]], key=lambda x:x[0])
          [[2, 1], [3, 4], [5, 3], [7, 4], [9, 0]]
        

    1.2 应用在闭包

    def get_y(a,b):
         return lambda x:ax+b
    y1 = get_y(1,1)
    y1(1) # 结果为2
    

    用常规函数实现闭包,如下:

    def get_y(a,b):
        def func(x):
            return ax+b
        return func
    y1 = get_y(1,1)
    y1(1) # 结果为2
    

    例子转载自:https://www.cnblogs.com/hf8051/p/8085424.html

    2. 列表解析式

    列表解析式是Python内置的非常简单强大的可以用来创建list的生成式。在深度学习项目中也可以经常看到这种用法。

    (1) 语法1:[表达式 for 变量 in 列表],表示把得到的每一个变量值都放到 for 前面的表达式中计算 ,然后生成一个列表
    (2) 语法2:[表达式 for 变量 in 列表 if 条件],如果加上 if 判断,则表示把每一个变量值进行判断,如果判断正确再交给表达式进行计算,然后生成一个列表

    举例:

    >>> items=[1,2,3,4,5,6,7]
    >>> [item*2 for item in items]
    [2, 4, 6, 8, 10, 12, 14]
    >>> [item*2 for item in items if item % 2 == 0]
    [4, 8, 12]
    

    使用列表解析式的写法更加简短,除此之外,因为是Python内置的用法,底层使用C语言实现,相较于编写Python代码而言,运行速度更快。

    3. enumerate内建函数

    对于一个列表,既要遍历索引又要遍历元素。

    >>> days=['mon','tus','wed','ths','fri','sat','sun']
    >>> for i,day in enumerate(days):
    ...     print(i,day)
    ...
    0 mon
    1 tus
    2 wed
    3 ths
    4 fri
    5 sat
    6 sun
    >>> for i,day in enumerate(days, start=1):
    ...     print(i,day)
    ...
    1 mon
    2 tus
    3 wed
    4 ths
    5 fri
    6 sat
    7 sun
    >>>
    

    4. 迭代器与生成器

    有时候项目会使用到这种语法,如果不了解这两种用法,可能很难读懂代码,可能会直接懵B o((⊙﹏⊙))o。下面分别看看这两个的用法:

    4.1 迭代器

    迭代器指的是可以使用next()方法来回调的对象,可以对可迭代对象使用iter()方法,将其转换为迭代器。

    >>> L=[1,2,3,4,5]
    >>> lst = iter(L)
    >>> type(lst)
    <class 'list_iterator'>
    >>> L1=(1,2,3,4,5)
    >>> lst1 = iter(L1)
    >>> type(lst1)
    <class 'tuple_iterator'>
    >>> next(lst)
    1
    >>> next(lst1)
    1
    >>>
    

    迭代器优势: 所有的元素不是一次性加载的,在调用next方法才会返回,不需要考虑内存问题。next()只能往后进行访问。

    迭代器应用场景:

    1. list规模过大,出于对内存的考虑使用迭代器。
    2. 有规律,但是不能使用列表推导式描述

    迭代器的创建:

    1. __iter__() 方法返回一个特殊的迭代器对象, 这个迭代器对象实现了 next() 方法并通过 StopIteration 异常标识迭代的完成。
    2. __next__() 方法(Python 2 里是 next())会返回下一个迭代器对象。
    class MyNumbers:
      def __iter__(self):
        self.a = 1
        return self
     
      def __next__(self):
        x = self.a
        self.a += 1
        return x
     
    myclass = MyNumbers()
    myiter = iter(myclass)
     
    print(next(myiter))
    print(next(myiter))
    

    例子来自菜鸟教程:https://www.runoob.com/python3/python3-iterator-generator.html

    4.3 生成器

    生成器是一个返回迭代器的函数,只能用于迭代操作,更简单点理解生成器就是一个迭代器。

    使用了yield的函数被称为生成器。

    在调用生成器运行的过程中,每次遇到 yield 时函数会暂停并保存当前所有的运行信息,返回 yield 的值, 并在下一次执行 next() 方法时从当前位置继续运行。(之前也遇见过yolo的代码中使用了这种用法,需要仔细理解并掌握)

    #!/usr/bin/python3
     
    import sys
     
    def fibonacci(n): # 生成器函数 - 斐波那契
        a, b, counter = 0, 1, 0
        while True:
            if (counter > n): 
                return
            yield a
            a, b = b, a + b
            counter += 1
    f = fibonacci(10) # f 是一个迭代器,由生成器返回生成
     
    while True:
        try:
            print (next(f), end=" ")
        except StopIteration:
            sys.exit()
    

    例子来自菜鸟教程:https://www.runoob.com/python3/python3-iterator-generator.html

    生成器的优点是延迟计算,一次返回一个结果,这样非常适用于大数据量的计算。但是,使用生成器必须要注意的一点是:生成器只能遍历一次。

    5. 装饰器

    装饰器本质是一个python函数,如果学过flask就知道,里边装饰器是必须的,经常用到。

    装饰器的作用:抽离大量和函数功能本身无关的代码进行重用

    一个简单的装饰器,用于计数,由于对不同的函数运行时间进行计数的需要,所以要对时间计数这部分进行处理。

    def get_time(func):
    	def wrapper():
            startTime = time.time()
            func()
            endTime = time.time()
            print("spend %f" % (endTime-startTime))
        return wrapper
    myFunction = get_time(myFunction)
    	
    

    精简一下,使用@语法来进行精简:

    import time
    def get_time(func):
        startTime = time.time()
        func()
        endTime = time.time()
        processTime = (endTime - startTime) * 1000
        print ("The function timing is %f ms" %processTime)
        
    @get_time
    def myfunc():
    	print("start")
    	time.sleep(0.8)
    	print("end")
    
    if __name__ == "__main__":
        myfunc
    

    output:

    start
    end
    The function timing is 800.058126 ms

    理解为:get_time(myfun()) ,将myfunc()函数包裹

    装饰器可以叠加使用,若多个装饰器同时装饰一个函数,那么装饰器的调用顺序和@语法糖的声明顺序相反,也就是:

    @decorator1
    @decorator2
    def func():
        pass
    

    等效于:

    func = decorator1(decorator2(func()))

    内置装饰器

    Python中,常见的类装饰器包括:@staticmathod、@classmethod和@property

    • @staticmethod:类的静态方法,跟成员方法的区别是没有self参数,并且可以在类不进行实例化的情况下调用。
    • @classmethod:跟成员方法的区别是接收的第一个参数不是self,而是cls(当前类的具体类型)
    • @property:表示可以直接通过类实例直接访问的信息。

    了解更多请看:https://www.jianshu.com/p/ee82b941772a

  • 相关阅读:
    【贪心】CodeForces-545C:Woodcutters
    【贪心】雷达问题
    【贪心】poj1328:雷达设置
    【最短路】HDU2680:Choose the best route
    2018年第四阶段组队训练赛第九场
    第四阶段组队训练赛第八场
    2018年第四阶段组队训练赛第七场
    第四阶段组队训练赛第六场( 题源:UKIEPC2017)
    Coins I
    2018年第四阶段组队训练赛第五场
  • 原文地址:https://www.cnblogs.com/pprp/p/11722730.html
Copyright © 2020-2023  润新知