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
1 and 2 and 3 返回3
1 and 2 and '' 返回''
'' and 2 and 0 返回''
PS:若是都为真则返回最后一个值,若是其中某些值为假,则返回第一个为假的值复制代码
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循环快好多服务器
代码参考:app
```
def func(a, b, c):
print vars()
执行func(1, 2, 3)
输出:{"a":1,"b":2,"c":3}
PS: vars()的值为字典,其键值对来源于当前做用域的全部变量。
```复制代码
使用场景:在调用他人接口或方法时,须要将传入的参数打印以记录日志,此刻vars()便派上用场了。
代码示例:
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 -m smtpd -n -c DebuggingServer localhost:1025
Python搭建简易web服务器:
python -m SimpleHTTPServer port
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:iteritems
和items
的区别在于iteritems
采用了生成器的原理,只有在须要的时候才会把值生成,其之间的区别相似于range
和 xrange
;readline
和 xreadline
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的深度还须要继续探索
以上就是平时工做中所总结出来的经常使用的知识点
但愿对你们之后的工做会有所帮助