1. 交换两个数字
In [66]: x, y = 1, 2
In [67]: x
Out[67]: 1
In [68]: y
Out[68]: 2
赋值的右侧形成了一个新的元组,左侧立即解析(unpack)那个(未被引用的)元组到变量 x 和 y。
2. 链式比较
In [71]: y = 5
In [72]: 1 < y < 10
Out[72]: True
In [73]: 10 < y < 20
Out[73]: False
3. 使用三元操作符进行条件赋值
三元操作符是 if-else 语句也就是条件操作符的一个快捷方式:
[表达式为真的返回值] if [表达式] else [表达式为假的返回值]
x = 1 if x < 10 else 0
在列表推导式中使用三元运算符
In [70]: [x**2 if x > 5 else x**3 for x in range(10)]
Out[70]: [0, 1, 8, 27, 64, 125, 36, 49, 64, 81]
4. 多行字符串
-
使用反斜杠
-
使用三引号
-
使用括号(将长字符串包含在括号中)
5. 解包操作
In [74]: aa = [1, 2, 3]
In [75]: x, y, z = aa
In [76]: x, y, z
Out[76]: (1, 2, 3)
6. 打印引入模块的文件路径
如果你想知道引用到代码中模块的绝对路径,可以使用下面的技巧:
import threading
import socket
print(threading)
print(socket)
#1- <module 'threading' from '/usr/lib/python2.7/threading.py'>
#2- <module 'socket' from '/usr/lib/python2.7/socket.py'>
7. 字典、集合、列表推导
In [77]: [i for i in range(10)]
Out[77]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
In [78]: {i:i*i for i in range(10)}
Out[78]: {0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81}
In [79]: (i*2 for i in range(10))
Out[79]: <generator object <genexpr> at 0x0000000003BEA3A8>
In[57]: dic = {"name": "Tom", "age": 30, "country": "USA"}
In[58]: {k:v for k, v in dic.iteritems()}
Out[58]: {'age': 30, 'country': 'USA', 'name': 'Tom'}
# 翻转字典的 key value 值
In[59]: {v:k for k, v in dic.iteritems()}
Out[59]: {30: 'age', 'Tom': 'name', 'USA': 'country'}
8. 文件共享
Python 允许运行一个 HTTP 服务器来从根路径共享文件,下面是开启服务器的命令:
# Python 2
python -m SimpleHTTPServer
# Python 3
python3 -m http.server
上面的命令会在默认端口也就是 8000 开启一个服务器,你可以将一个自定义的端口号以最后一个参数的方式传递到上面的命令中。
9. 查看对象的内置方法
In [81]: dir(aa)
Out[81]:
['__add__',
'__class__',
...
'append',
'count',
'extend',
'index',
'insert',
'pop',
'remove',
'reverse',
'sort']
10. in 语句简化操作
if x == 1 or x == 2 or x == 3 or x ==4
## 替换为
if x in [1, 2, 3, 4]
11. 连接字符串
In [82]: cc = ['I', 'love', 'you']
In [83]: ' '.join(cc)
Out[83]: 'I love you'
12. 翻转字符串/列表
* 使用 reverse() 翻转列表本身
* 使用 reversed() 翻转产生新列表
* 使用切片翻转
In [82]: cc = ['I', 'love', 'you']
In [84]: cc.reverse()
In [85]: cc
Out[85]: ['you', 'love', 'I']
In [86]: for i in reversed(cc):
...: print i
...:
I
love
you
In [87]: cc[::-1]
Out[87]: ['I', 'love', 'you']
13. 同时获取列表索引和值
In [89]: a = ['a', 'b', 'c']
In [90]: for i, v in enumerate(a):
...: print i, v
...:
0 a
1 b
2 c
14. 函数返回多个值
# function returning multiple values.
def x():
return 1, 2, 3, 4
# Calling the above function.
a, b, c, d = x()
print(a, b, c, d)
#-> 1 2 3 4
15. 使用 * 运算符来 unpack 函数参数
def test(x, y, z):
print(x, y, z)
testDict = {'x': 1, 'y': 2, 'z': 3}
testList = [10, 20, 30]
test(*testDict)
test(**testDict)
test(*testList)
#1-> x y z
#2-> 1 2 3
#3-> 10 20 30
16. 如何打开关闭文件
f = open("test.txt")
try:
content = f.read()
finally:
f.close()
## 更好的方法
with open("test.txt") as f:
content = f.read()
17. 使用锁
# 创建锁
lock = threading.Lock()
# 使用锁的老方法
lock.acquire()
try:
print 'Critical section 1'
print 'Critical section 2'
finally:
lock.release()
## 更好的方法
with lock:
print 'Critical section 1'
print 'Critical section 2'
18. 字典的 popitem() 是原子操作,多线程没必要加锁
In [2]: d = {'matthew': 'blue', 'rachel': 'green', 'raymond': 'red'}
In [3]: while d:
...: key, value = d.popitem()
...: print key, '-->', value
matthew --> blue
rachel --> green
raymond --> red
19. 用key-value对构建字典
In [4]: names = ['raymond', 'rachel', 'matthew']
In [5]: colors = ['red', 'green', 'blue']
In [7]: d = dict(zip(names, colors))
In [8]: d
Out[8]: {'matthew': 'blue', 'rachel': 'green', 'raymond': 'red'}
20. 遍历一个序列
colors = ['red', 'green', 'blue', 'yellow']
# 正序
for color in sorted(colors):
print colors
# 倒序
for color in sorted(colors, reverse=True):
print colors
21. 将"hello world"转换为首字母大写"Hello World"
In[2]: "hello, world".title()
Out[2]: 'Hello, World'
22. a =“info:China 960 beijing”,用正则切分字符串输出[‘info’, ‘China’, ‘960’, ‘beijing’]
In[7]: import re
In[8]: a ="info:China 960 beijing"
In[9]: re.split(":| ", a)
Out[9]: ['info', 'China', '960', 'beijing']
23. a = “hello world” 去除多余空格只留一个空格
str.split()
注意:当使用空格作为分隔符时,对于中间为空的项会自动忽略
In[20]: " ".join(a.split())
Out[20]: 'hello world'
24. 如何实现 [“1,2,3”] 变为 [‘1’, ‘2’, ‘3’]
In[21]: a = ["1,2,3"]
In[22]: a[0].split(",")
Out[22]: ['1', '2', '3']
25. 字典操作中 del 和 pop 有什么区别
del 可以根据 key 来删除对应的元素,没有返回值;
pop 可以根据 key 弹出该 key 对应的 value,然后可以接收它的返回值;
In[24]: a = {"a":1, "b":2, "c":3}
In[25]: del a["a"]
In[26]: a
Out[26]: {'b': 2, 'c': 3}
In[27]: re = a.pop("b")
In[28]: re
Out[28]: 2
26. 如何在一个函数内部修改全局变量
num = 5
def func():
global num
num = 4
func()
print(num) # 4
27. 说说死锁、GIL 锁、协程
- 死锁
多个子线程在系统资源竞争时,都在等待对方解除占用状态。比如,线程 A 等待着线程 B 释放锁 b,同时,线程 B 等待着线程 A 释放锁 a.
在这种局面下,线程 A 和线程 B 都相互等待着,无法执行下去,这就是死锁。
- GIL锁
任何Python线程执行前,必须先获得GIL锁,然后,每执行100条字节码,解释器就自动释放GIL锁,让别的线程有机会执行。这个GIL全局锁实际上把所有线程的执行代码都给上了锁,所以,多线程在Python中只能交替执行,即使100个线程跑在100核CPU上,也只能用到1个核。
需要注意的是,GIL并不是Python的特性,它是在实现Python解析器(CPython)时所引入的一个概念。而Python解释器,并不是只有CPython,除它之外,还有PyPy,Psyco,JPython,IronPython等。
在绝大多数情况下,我们通常都认为 Python == CPython,所以也就默许了Python具有GIL锁这个事。
都知道GIL影响性能,那么如何避免受到GIL的影响?
- 使用多进程代替多线程。
- 更换Python解释器,不使用CPython
GIL 是 Python 的全局解释器锁,同一进程中假如有多个线程运行,一个线程在运行 Python 程序的时候会占用 Python 解释器(加了一把锁即 GIL),使该进程内的其他线程无法运行,等该线程运行完后其他线程才能运行。如果线程运行过程中遇到耗时操作,则解释器锁解开,使其他线程运行。所以在多线程中,线程的运行仍是有先后顺序的,并不是同时进行。
为了避免死锁发生,cython 使用 GIL锁,确保同一时刻只有一个线程在执行,所以其实是伪多线程。所以,python 里常常使用协程技术来代替多线程。
多进程中因为每个进程都能被系统分配资源,相当于每个进程有了一个 Python 解释器,所以多进程可以实现多个进程的同时运行,缺点是进程系统资源开销大。
- 协程
多进程、多线程的切换是由系统决定,而协程由我们自己决定。
协程无需使用锁,也就不会发生死锁。同时,利用协程的协作特点,高效的完成了原编程模型只能通过多个线程才能完成的任务。
28. 简述面向对象中 new 和 init 区别?
-
__new__至少要有一个参数 cls,代表当前类,此参数在实例化时由 Python 解释器自动识别。
-
__new__必须要有返回值,返回实例化出来的实例,这点在自己实现__new__时要特别注意,可以 return 父类(通过 super(当前类名, cls))__new__出来的实例,或者直接是 object 的__new__出来的实例。
-
__init__有一个参数 self,就是这个__new__返回的实例,__init__在__new__的基础上可以完成一些其它初始化的动作,__init__不需要返回值。
-
如果__new__创建的是当前类的实例,会自动调用__init__函数,通过 return 语句里面调用的__new__函数的第一个参数是 cls 来保证是当前类实例,如果是其他类的类名;那么实际创建返回的就是其他类的实例,其实就不会调用当前类的__init__函数,也不会调用其他类的__init__函数。
29. s=“ajldjlajfdljfddd”,去重并从小到大排序输出"adfjl"?
In[33]: s = "ajldjlajfdljfddd"
In[35]: ''.join(sorted(set(s)))
Out[35]: 'adfjl'
30. 用 lambda 函数实现两个数相乘?
In[36]: ret = lambda x, y: x * y
In[37]: ret(4, 5)
Out[37]: 20
部分内容来自: www.lightxue.com/transforming-code-into-beautiful-idiomatic-python