Python经常使用知识点一二

写在前面

Python是一门解释型的、动态型的OOP语言,结识Python的这几年来,其语法的简洁、结构的条理性深入的吸引了我。下面是我总结出来的一些Python经常使用知识点。html

列表碾平式

需求: 将[[1,2],[3,4]] 转换为[1,2,3,4],具体实现有如下几种方法python

test_list = [[1,2],[3,4]]

1. from itertools import chain
   list(chain.from_iterable(test_list))
   结果:[1, 2, 3, 4]

2. from itertools import chain
   list(chain(*test_list))
   结果:[1, 2, 3, 4]

3. sum(test_list, [])
   结果:[1, 2, 3, 4]

4. [x for y in test_list for x in y]
   结果:[1, 2, 3, 4]

5. 万能方法(递归)
   func = lambda x: [y for t in x for y in func(t)] if type(x) is list else [x]
   func(test_list)
   结果:[1, 2, 3, 4]复制代码

PS: 项目中,不免会有相似的需求,对于结构嵌套一致的状况,上述的1,2,3,4方法均可以很好的解决(不建议用for循环嵌套的方式,那是最low的方法,没有之一);对于结构嵌套不一致的状况,第5种方法就派上了用场,其采用了递归的思想,堪称万能的方法,屡试不爽。项目中,你们能够根据实际应用场景来挑选最适合本身的方法。肚中有粮,心中不慌;你们能够把上述方法都记下来,以作到有的放矢。web

三目操做符

对于Python的三元表达式,想必你们对if else都不会感到陌生,可是对and or操做想必是另外一种感受了,不过你们对其余语言的? :应该不会陌生,没错,此次的主角and or就和? :有着殊途同归之妙。ajax

代码参考:django

1 == 1 and 2 or 3   返回2
1 == 2 and 2 or 3   返回3复制代码

PS:习惯于if else的同窗偶尔用下and or是否是会给人耳目一新的感受。json

and or 分开来用

  • [x] and 用法以下:
1 and 2 and 3   返回3
1 and 2 and ''   返回''
'' and 2 and 0  返回''
PS:若是都为真则返回最后一个值,若是其中某些值为假,则返回第一个为假的值复制代码
  • [x] or 用法以下
1 or '' or 0    返回1
'' or 0 or []    返回[]
PS:若是都为假返回最后一个值,若是其中某些值为真,则返回第一个为真的值复制代码

使用场景:在项目中咱们常常会有这样的需求,在将一个字典更新以后还想要返回更新后的字典,这是咱们就能够这样写:dic = dic1.update(dic2) or dic1缓存

列表推导式

需求:将[1,2,3]中的每一项都加1bash

good: [x+1 for x in [1,2,3]]
bad:  def add_list(goal_list):
          tmp_list = []
          for x in goal_list:
              tmp_list.append(x+1)复制代码

PS: 列表推导式底层是用C实现的,其执行速度要比for循环快好多服务器

vars() 用法

代码参考:app

```
def func(a, b, c):
    print vars()
执行func(1, 2, 3)
输出:{"a":1,"b":2,"c":3}
PS: vars()的值为字典,其键值对来源于当前做用域的全部变量。
```复制代码

使用场景:在调用他人接口或方法时,须要将传入的参数打印以记录日志,此刻vars()便派上用场了。

偏函数之partial

代码示例:

import functools
def add(a, b):
    return a + b
add(4, 2)
    6
plus3 = functools.partial(add, 3)
plus5 = functools.partial(add, 5)
plus3(4)
    7
plus3(7)
    10
plus5(10)
    15复制代码

实际使用心得:

以前作对象存储的项目中,我须要同时去调用三个同样的接口(大部分参数同样)下面是个人部分代码,供你们参考

my_thread = functools.partial(myThread, dic, zone_id, start, end, customer_id)
my_thread1 = my_thread("day", "gets", "2")
my_thread1 = my_thread("day", "original_traffic", "3")复制代码

使用场景:
当咱们须要同时去调用一个函数,而且发现大部分参数一致的时候,即可以采起上述方法,一来代码简洁,二来可读性高。

Python搭建简易服务

  • Python搭建简易邮件服务器:python -m smtpd -n -c DebuggingServer localhost:1025
  • Python搭建简易web服务器:

    • Python2: python -m SimpleHTTPServer port
    • Python3: python -m http.server port
  • Python搭建简易ftp服务

    pip install pyftpdlib
      python -m pyftpdlib -p 21
      ftp://localhost:21复制代码

遍历字典

在项目中遍历字典是很常见的需求,下面介绍下经常使用的方法并作下比较:

dic = {'name': 'peter', 'age': 27}
1. for key, value in dic.items():
       print key, value
2. for key, value in dic.iteritems():
       print key, value复制代码

PS:
iteritemsitems的区别在于iteritems采用了生成器的原理,只有在须要的时候才会把值生成,其之间的区别相似于rangexrangereadlinexreadline

内存管理

Python的内存管理主要分为引用计数和垃圾回收机制两大部分,且看下面代码:

  • [ ] 内存分配:

    a = 1
      b = 1
      a is b      True
      ---------------------
      a = 1000
      b = 1000
      a is b      False复制代码

    PS: 在Python中,整数和短小的字符,Python都会缓存这些对象,以便重复使用。当咱们建立多个等于1的引用时,其实是让这些引用指向了同一个对象。

  • [ ] 引用计数:

    在Python中,所谓引用计数(reference count)是指全部指向该对象的引用的总数;

    咱们可使用sys包中的getrefcount(),来查看某个对象的引用计数。须要注意的是,当使用该函数查看某个对象的引用计数时,其实是临时建立了该对象的一个新的引用,全部使用getrefcount()所获得的结果,会比指望的值多1。

    from sys import getrefcount
      aa = 'test refcount'
      print(getrefcount(a))
      bb = aa
      print(getrefcount(a))复制代码

    PS: 因为上述缘由,两个getrefcount()将返回2和3,并非指望的1和2.

  • [ ] 引用减小

    引用减小大体分为两类:

    • 指向该对象的引用指向了其余对象

      from sys import getrefcount
      
         aa = 'test refcount'
         bb = aa
         print(getrefcount(aa))      3
      
         bb = 1
         print(getrefcount(aa))      2复制代码
    • 使用del关键字显示的删除某个引用

      from sys import getrefcount
      
         aa = 'test refcount'
         bb = aa
         print(getrefcount(aa))      3
      
         del bb
         print(getrefcount(aa))      2复制代码
  • [ ] 垃圾回收

    不断的建立对象,若是不及时销毁的话,那Python的体积会愈来愈大,再大的内存也会有耗完的时候;不用像C语言那样,须要手动的去管理内存、Python已经帮咱们作好了(Python的垃圾回收机制),你只须要去关心你的业务逻辑便可,其余的都交给Python来处理。

    从原理上讲,当Python中某个对象的引用计数降为0时,该对象就应该被回收。可是频繁的启动垃圾回收机制毕竟是个很耗时的问题;所以Python只有在特定条件下(当Python中被分配对象和取消分配对象的次数之间的差值达到某个阈值时),Python会自动启动垃圾回收机制。

    咱们能够经过gc模块的get_threshold()方法,查看该阈值:

    import gc
      print(gc.get_threshold())复制代码

    该方法会返回(700, 10, 10),后面的俩10是与分代回收相关的,稍后讲解。700即是垃圾回收机制启动的阈值。能够经过gc模块中的set_threshold()方法从新设定该值。

    固然了,咱们也能够手动启动垃圾回收机制,使用gc.collect()便可。

  • [ ] 分代回收

    Python同时采用了分代回收的机制,设想一下:存活越久的对象、越不多是垃圾对象。程序在运行时,每每会产生大量的临时对象,程序结束以后,这些临时对象的生命周期也就随之告一段落。但有一些对象会被长期占用,垃圾回收机制在启动的时候会减小扫描到他们的频率。

    Python将全部对象分为0,1,2三代。全部新建立的对象都是0代,当垃圾回收机制在启动屡次0代机制并扫描到他们的时候,这些对象若是依然存活在内存的话,他们就会被纳入下一代对象,以此类推。

    刚才上面所提到的(700, 10, 10)三个参数后面的俩10所表明的意思是:每10次0代垃圾回收,会配合1次1代的垃圾回收;而每10次1代的垃圾回收会配合1次的2代垃圾回收。

    固然咱们一样可使用set_threshold()来调整此策略的比例,好比对1代对象进行更频繁的扫描。

    import gc
      gc.set_threshold(700, 5, 10)复制代码

新式类、经典类

  • [ ] 新式类: 显示的继承了object的类

    class A(object):
          attr = 1
    
      class B(A):
          pass
    
      class C(A):
          attr = 3
    
      class D(B, C):
          pass
    
      if __name__ == '__main__':
          d = D()
          print 'attr = ', d.attr     # attr = 3复制代码
  • [ ] 经典类:没有继承自object的类

    class A():
          attr = 1
    
      class B(A):
          pass
    
      class C(A):
          attr = 3
    
      class D(B, C):
          pass
    
      if __name__ == '__main__':
          d = D()
          print 'attr = ', d.attr     # attr = 1复制代码

    PS: 经过以上代码的输出结果能够看出,新式类会广度搜索,也就是一层层的向上搜索;经典类是深度优先,即遇到一个超类点就向上搜索。

装饰器

Python的装饰器被称为Python的语法糖,哪里须要粘哪里。

代码示例:

@makeh1
@makeeitalic
def say():
    return 'Peter'

咱们但愿输出结果为:<h1><i>Peter</i></h1>复制代码

去看看官方文档,答案就看下面:

def makeh1(func):
    def wrp():
        return "<h1>" + func() + "</h1>"
    return wrp

def makeeitalic(func):
    def wrp():
        return "<i>" + func() + "</i>"
    return wrp

@makeh1
@makeeitalic
def say():
    return 'Hello Peter'

print say()
输出:<h1><i>Hello Peter</i></h1>复制代码

实际应用场景:

使用过django的小伙伴想必都用过login_required装饰器,可是若是用户没登陆的话login_required会重定向到登陆页面;在作web开发的过程当中,咱们会常常用
ajax异步提交数据到后台,这时若是再继续使用原有的login_required装饰器确定是不行了(该装饰器不会重定向到登陆页面,ajax也没有任何返回结果),下面咱们改变下原有代码:

from django.shortcuts import HttpResponse
import json

def is_authenticat(func):
    def wrp(req, **kwargs):
        if req.user.is_authenticated():
            return func(req, **kwargs)
        else:
            json_str = {'status': 0, 'msg': u'请登陆'}
            return HttpResponse(json.dumps(json_str), content_type='application/json')
    return wrp复制代码

上述代码便很好的解决了问题,也算是对Python装饰器的一个很好的使用场景。

写在结语

Python的奥妙远不止于此

Python的深度还须要继续探索

以上就是平时工做中所总结出来的经常使用的知识点

但愿对你们之后的工做会有所帮助

相关文章
相关标签/搜索