zoukankan      html  css  js  c++  java
  • 编写高效且优雅的 PYTHON 代码

    1,列表推到式:

      对于简单的函数方法,尽量使用表推导式来代替map和filter函数,因为这样往往可以少些很多函数。

      例如,

        nums= [1, 2, 3]

        squares = map(lambda x: x**2, nums) #使用map

        squares = [x**2 for x in test_num] #使用列表推导式

      并且,在列表推导式中能加入很多判断

        squares = [x**2 for x in test_num if x == 2] #使用列表推导式,相当于也使用了filter

      但是,如果方法过于复杂,还是建议使用map函数

      如果数据量过多,可以使用生成器表达式来代替列表推导式,这样可以节约很多内存

        squares = (x**2 for x in test_num if x == 2) #使用生成器表达式来代替列表式,这样在使用时才会占用内存

    2,使用zip函数来同时迭代长度不同的两个list

      zip函数的主要功能是,将一个或多个迭代器的内容打包生成l元祖,并且可以同时传入多个迭代器。如果各个迭代器的元素个数不一致,则返回列表长度与最短的对象相同。

      test_num = [1, 2, 3]

      test_num2 = ['a', 'b', 'c', 'd']

      for i in zip(test_num, test_num2):

          print i


    3,使用装饰器:
      装饰器用于在不改变原函数代码的情况下修改已存在的函数。常见场景是增加一句调试,或者为已有的函数增加log监控,具体使用方式可以参照我之前的博客

    4,使用生成式来代替返回列表
      带有yield的函数是可以将值的值推入一个生成式中,在该生成式真正被调用时才会被计算。而yield字段必须要在函数中使用,之后,调用这个函数的返回值就会是一个生成式,只有在调用的时候
      才会开始计算数列,从而大大减少了内存
      但是!生成器只能被迭代一次,循环了一次以后,这个迭代器就失效了,只能重新获得以后才能使用
      如果不想造成以上结果,可以将生成器的结果传入一个可重复迭代的类中:例如:
      
    class LoopIter(object):
    
        def __init__(self, data):
            self.data=data
    
        # 必须在 __iter__ 中 yield 结果
        def __iter__(self):
            for index,letter in enumerate(self.data):
                if letter == 'a':
                    yield index#记录下标

    5,这边再记录几个没用过的内置参数:
      __slots__
      这个内置参数记录了这个类中所有用到的参数,默认下可以动态添加类的参数,但是,如果将这个参数以列表的形式固定了,那么就无法动态的增加参数
      
      __call __
      这个内置方法可以使得一个实例对象可以像调用方法一样调用这个实例的方法
      Python 的 __call__ 方法可以让类的实例具有类似于函数的行为,通常用于定义和初始化一些带有上下文的函数
      
      class A(object):
      def __call__(self, *args, **kwargs):
      print args

      a = A()
      a("123")
      暂时不太理解这样做的好处,这样实际上模糊了函数和实例对象之间的关系。网络上可以借鉴的使用场景是: 可以把一个类写成一个装饰器进行调用。
      
    class Pipe(object):
        def __init__(self, fn):
            self.fn = fn
    
        def __ror__(self, other):
            return self.fn(other)
    
        def __call__(self, *args, **kwargs):
            op = Pipe(lambda x: self.fn(x, *args, **kwargs))
            return op
    @Pipe
    def sort(data, cmp=None, key=None, reverse=False):
        return sorted(data, cmp=cmp, key=None, reverse=reverse)
        
    [{'score': 1}, {'score': 3}, {'score': 2}] | sort(key=lambda x: x['score'])

    __init__函数与__new__函数

    __init__函数是当一个类被加载以后第一个执行的函数,通常被用于进行类的初始化设定
    __new__函数才是用于创建一个实例的函数,经常,可以利用这个函数实现单例模式:
      
    class Singleton(object):
    _instance = None
    def __new__(cls, *args, **kw):
    if not cls._instance:
    cls._instance = super(Singleton, cls).__new__(cls, *args, **kw)
    return cls._instance
    class MyClass(Singleton):
    a = 1

    @classmethod 和 @staticmethod
    @staticmethod 类似与定义了一个静态方法,这个方法并不会传入这个类的相关数据作为参数
    而@classmethod标注的方法,将会把这个类自身作为一个参数传入,这样的好处在于,我可以不侵入原有的代码进行函数操作

    上下文管理函数__enter__和__exit__函数,可以用来定义在使用在进入函数时执行的方法和退出函数时执行的方法,其中,使用with关键字来进行函数的调用。
    经典的场景就是进行文件的读取的时候,利用with函数来确保文件的正确打开和关闭

    参考链接:
        https://gnu4cn.gitbooks.io/python-advance-coding/content/01-effective-and-fine-python-code.html



     




      
      
  • 相关阅读:
    C++快速排序
    C++冒泡排序
    为什么Excel创建一个新的工作簿就会初始化三个worksheet
    为什么游戏需要英雄
    2015.11.18——Lua中文教程
    [国家集训队2012]JZPFAR
    后缀数组小结?
    [BZOJ 2738]矩阵乘法
    [BZOJ 3221][Codechef FEB13] Obserbing the tree树上询问
    [BZOJ 4999]This Problem Is Too Simple!
  • 原文地址:https://www.cnblogs.com/Rubick7/p/7760924.html
Copyright © 2011-2022 走看看