pythonic之路—-编写简洁清晰python代码(一)
一、if中不要直接将语句与True、False、None做比较
python中隐含为False的对象:
None
False数值
0(不是字符"0")空容器,比如空list
x=[]、空tuplex=()、空dictx={}、空strx=""
其余的则隐含为True。
尽量避免用如下语法if foo == True,if x == 0,if len(bar) == 0,应替换为if foo,if not x,if not bar。
但是,如果一个程序的关键字参数默认值为None,代码需要判断输入是否为None,则必须显式的与None比较,即
def foo(x=None):
if x is not None:
pass
假如写为
def foo(x=None):
if x:
pass
那么x=0也被排除在外,如果参数x是一个序列的指标(index)则0显然是其中一个而不应该被排除。
同时,要记住,与None作比较时用is和is not,不要用==。
所以,None是个例外,对于其他的条件判断,直接用python隐含的True和False来做比较,而不是==。
二、尽量不要用可变对象(比如list、dict)作为函数的默认参数
因为可变对象会将实参累积起来,导致随后的调用出现问题。可用None作为默认值。
问题代码:
def foo_(foo, bar=["bar"]):
bar.append(foo)
return bar
print(foo_(1))#输出['bar', 1]
print(foo_(1))#输出['bar', 1, 1]
print(foo_(1))#输出['bar', 1, 1, 1]
改进代码:
def foo_1(foo, bar=None):
if bar is None:
bar = ["bar"]
bar.append(foo)
return bar
print(foo_1(1))#输出['bar', 1]
print(foo_1(1))#输出['bar', 1]
print(foo_1(1))#输出['bar', 1]
总的来说,要在函数里重新初始化形参,这样每次调用时都是以初始化的形参来接收实参,从而避免了累加。这对初学者来说可能是个陷阱,但老司机一般不会犯这样的错。
三、用*表示list的剩余元素
>>>x = ["a", "b", "c", "d", "e"]
>>>(f, s, *r) = x
f = "a"
s = "b"
r = ["c", "d", "e"]
>>>(f, *m, l) = x
f = "a"
s = "e"
m = ["b", "c", "d"]
四、通过字典dict.get给变量提供默认值
字典方法mydict.get(k,d)实现了一个条件判断功能。return mydict[k] if k in mydict, else return d。
一个原理验证例子。
>>>x = ["a", "b", "c", "d", "e"]
>>>z = dict((k,v) for k,v in zip(x,range(6)))
>>>z1 = z.get("a",10)#z1 = 0
>>>z1 = z.get("x",10)#z1 = 10
一个有点用处但语法啰嗦的例子。
log_severity = None
if 'severity' in configuration:
log_severity = configuration['severity']
else:
log_severity = 'Info'
用dict.get改进版。
log_severity = configuration.get('severity', 'Info')
五、用format函数格式化字符串
格式化字符串一般有三种方法,用“+”、用“%”、用“format函数”。
最糟糕的莫过于用“+”,语句冗长晦涩难懂(尤其当有一串字符需要格式化时);
用“%”稍微好一些,缺点是用变量格式作为占位符,完全与格式化的内容脱节,也难懂;
format直接使用命名的占位符,一看一目了然,清晰简洁。
def get_formatted_user_info(user):
#最糟的方式
return 'Name: ' + user.name + ', Age: ' + str(user.age) + ', Sex: ' + user.sex
def get_formatted_user_info(user):
#不太好的方式
return 'Name: %s, Age: %i, Sex: %c' % (user.name, user.age, user.sex)
def get_formatted_user_info(user):
#良好方式
output = 'Name: {user.name}, Age: {user.age}, Sex: {user.sex}'.format(user=user)
return output
六、如果有一个list,可用"".join(mylist)创建一个string
七、class受保护变量和私有变量
受保护变量以单下划线开始,比如self._id = id,受保护的意思是提示客户(client)不要直接使用它。
私有变量以双下划线开始,比如self.__id = id,私有的意思是提示子类没法直接调用该属性。
一定要记住,这只是程序员所遵循的一个传统而已,如果client真想一窥究竟,谁也没法阻止,实际上没有真正的隐私。但是要尊重开发人员的意图。
八、在class里定义一个魔法方法__str__,用于友好的打印instance信息。
class Point():
def __init__(self, x, y, name):
self.x = x
self.y = y
self._name = name
def __str__(self):
return "{}({})".format(self.__class__.__name__, self._name)
if __name__ == "__main__":
p = Point(1,2,"two point")
print(p)#显示Point(two point)
九、用set消除重复元素
集合的一个特性是唯一性,即没有重复的元素。相当于字典的键。
set是Iterable和Container的子类。所以可用于for循环,也可当做in语句的迭代对象。
y = ['bar', 1, 1, 2, 1, 1, 1, 1]
for s in set(y):
print(s)#输出1,2,bar
集合可以很方便的用集合表达式(类似于列表表达式)来生成。
users_first_names = {user.first_name for user in users}
set包含了所有数学意义上集合的运算,比如并(A|B)、交(A&B)、差(A-B)、对称差(并集-交集A^B)。
可以通过交集求出经常上线的且正在活跃的用户。
啰嗦写法:
def get_both_popular_and_active_users():
most_popular_users = get_list_of_most_popular_users()#存储用户名的list
most_active_users = get_list_of_most_active_users()#存储用户名的list
opular_and_active_users = []
for user in most_active_users:
if user in most_popular_users:
popular_and_active_users.append(user)
return popular_and_active_users
简洁写法:
def get_both_popular_and_active_users():
return(set(get_list_of_most_active_users()) & set(get_list_of_most_popular_users()))
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
(内容同步更新到微信公众号python数学物理,微信号python_math_physics)
1125

被折叠的 条评论
为什么被折叠?



