大部分编程语言都有共性,也有个性。下手害怕个性,视为异端,抵触之;上手善用个性,欣欣然,妙用之。
别抱怨python没有三元表达式,请看:
intro = None
introduction = "haha" if intro == None or len(intro) == 0 else intro
含义隽永,妙味无穷。千言万语,尽在一行中。
定义:一个星号和两个星号分别对list和dict进行packing和unpacking,
请听题:
v, *end = [10, 20, 30]
# gives v= 1, end = [2, 3]
v, *middle, z= [1, 2, 3, 4]
# gives v= 1, middle = [2, 3], z= 4
v, *middle, z= [1, 2, 3, 4]
# gives v= 1, middle = [2, 3]
传可变参数也是用它们:
def add(*args):
sum = 0
for arg in args:
sum += arg
return sum
def say(**kwargs):
for k,v in kwargs.items():
print(f"{k} = {v}")
有了这两个函数,我们可以这样用:
add(1, 2)
add(1, 2, 3)
say(username='user1', passwd='123')
say(username='user1', passwd='123', age=10)
多方便,多神奇啊。
列表能运算,能带表达式,能lambda,请听题:
listOfNones = [None] * 6
# gives [None, None, None, None, None, None]
listOfFives = [[5]] *5
# gives [[5], [5], [5], [5], [5]]
filtered_list = [item for item in sequence if item != x]
## to avoid generating a new object, use generators
filtered_list = (item for item in sequence if item != x)
result = list(map(lambda x:x**2, [i for i in range(3)]))
用yield而不是return语句,能改善程序结构,提高执行效率。yield把数据含在嘴里,迭代一次,就往外吐一次数据。
生成器的定义:
def calculate(size):
result = []
for i in range(size):
result.append(i**2)
return result
for val in calculate(1_000_000):
print(val)
改为:
def calculate(size):
for i in range(size):
yield i**2
for val in calculate(1_000_000):
print(val)
这样更节省内存。
典型的使用案例:scrapy中做网页抓取时,每遇到一个url链接,就yield一把,不断往外"吐"链接,如此循环下去,就形成了深度优先遍历。
Python中,我们通常在两类代码块中分配资源:
with open("data.txt", "r") as f:
text = f.read()
采用context manager能帮我们管理资源申请和释放:
import contextlib
@contextlib.contextmanager
def db_handler():
try:
stop_db()
yield
finally:
start_db()
with db_handler():
db_backup()
这样等价于:
try:
stop_db()
db_backup()
finally:
start_db()
集合的性能优于函数。如果你不需要许多函数,集合比其他数据结构好。
data = {'find_this', 'among', 'all_the', 'other', 'data'}
if 'find_this' in data:
print('this exists!')
long_stuff = ['this', 'list', 'list', 'is',
'enormous', 'oh', 'my', 'god',
'god', 'what', 'is', 'unique', 'unique']
unique_values = set(long_stuff)
##不推荐
if x == True:
# ....
if len(items) != 0:
# ...
if items != []:
# ...
##推荐
if x:
# ....
if items:
# ...
使用 in 更加简洁:
# 字符串包含
if 'hello' in 'helloworld':
# ... do something
# 多次判断
##不推荐
if fruit == "apple" or fruit == "orange" or fruit == "berry":
##推荐
if fruit in ["apple", "orange", "berry"]:
# 字典键值判断
##不推荐
if my_dict.has_key(key):
# ...do something with d[key]
##推荐
if key in my_dict:
# ...do something with d[key]
##不推荐
import threading
lock = threading.Lock()
lock.acquire()
try:
# 互斥操作...
finally:
lock.release()
##推荐
import threading
lock = threading.Lock()
with lock:
# 互斥操作...
##不推荐
f = open("some_file.txt")
try:
data = f.read()
# 其他文件操作..
finally:
f.close()
##推荐
with open("some_file.txt") as f:
data = f.read()
# 其他文件操作...
##不推荐
try:
os.remove("somefile.txt")
except OSError:
pass
##推荐
from contextlib import ignored # Python 3 only
with ignored(OSError):
os.remove("somefile.txt")
不推荐:
my_name = 'firstname' + ' ' + 'lastname'
推荐:
my_name = " ".join(['firstname', 'lastname'])
students = ['tom', 'dick', 'harry', 'larry', 'tim', 'benny']
scores = [100, 20, 40, 60, 30, 40]
不推荐:
for i in range(len(students)):
print(student[i], scores[i])
推荐:
for student, score in zip(students, scores):
print(student,score)