Mastering Python 01
1.准备
1.说明:《Mastering Python》读书笔记
2.要求:首先,希望你是处在
python3
版本,然后拥有一个干净的虚拟环境更是必要。3.virtualenv或者anaconda都是不错的选择
2.Pythonic Syntax, Common Pitfalls, and Style Guide
2.1.Pythonic code
对于python开发者,无不希望写出pythonic风格的代码,请谨记以下几点:
- Clean
- Simple
- Beautiful
- Explicit
- Readable
具体的话请打开你的python解释器:
import this
细细感受吧。
2.1.2.Differences between value and identity comparisons
对于下面这个例子:
|
|
256 == 256: True
256 is 256: True
-5 == -5: True
-5 is -5: True
257 == 257: True
257 is 257: False
-6 == -6: True
-6 is -6: False
可以看到,在值相同的情况下,使用==
比较都返回True
自不必说,为何有的id
相同有的id
却不同?
这是因为,在pyhton
中,会提前为一小部分整数提前分配空间,这个整数的范围是[-5,256],当整数范围大于256或者小于-5时,python
便会为该整数创建对象,于是造成id不同。如果想深入了解,可阅读深入 Python 整数对象的实现
2.1.3.Loops
对于一个列表,比如:
|
|
想将其输出为[index:value]
这种列表格式,请看以下几种实现方法:
|
|
不得不说,实在很繁琐,我们可以利用python
提供的enumerate
类:
|
|
第二种方法确实精简了不少,但是,优雅的pythonic
不是浪得虚名,请看这种:
|
|
['0:1', '1:2', '2:3', '3:4']
2.2.Common pitfalls
虽说python
自诩是一种清晰易读无歧义的优雅语言,但是这个伟大的目标并不是那么容易实现。
2.2.1.Function arguments
需要知道的是,千万不要使用可变参数作为函数默认参数,看下面这样一个例子:
|
|
List: ['value 1']
Dict: {'key 1': 'value 1'}
List: ['value 1', 'value 2']
Dict: {'key 2': 'value 2', 'key 1': 'value 1'}
按照代码的思路,输出的结果应该是下面这样才对:
|
|
实际上并非如此,首先,list
以及dict
都是可变对象,当spam
函数被定义,list_
和dict_
就会被创建(但是它们只被创建一次),随后调用函数的时候,list_
和dict_
并没有被重新创建,于是,这个陷阱便出现了。
正确的做法:
|
|
List: ['value 1']
Dict: {'key 1': 'value 1'}
List: ['value 2']
Dict: {'key 2': 'value 2'}
2.2.2.Class properties
在类的定义中,也存在这样的问题。
|
|
output:
List: ['value 1']
Dict: {'key 1': 'value 1'}
List: ['value 1', 'value 2']
Dict: {'key 1': 'value 1', 'key 2': 'value 2'}
替代方案:
|
|
List: ['key 1']
Dict: {'key 1': 'value 1'}
List: ['key 2']
Dict: {'key 2': 'value 2'}
<__main__.Spam at 0x10498a2b0>
2.2.3.Modifying variables in the global scope
在函数内对变量进行操作也有需要注意的地方。
|
|
---------------------------------------------------------------------------
UnboundLocalError Traceback (most recent call last)
<ipython-input-8-52c0d52ad689> in <module>()
7
8
----> 9 eggs()
<ipython-input-8-52c0d52ad689> in eggs()
3
4 def eggs():
----> 5 spam += 1
6 print(spam)
7
UnboundLocalError: local variable 'spam' referenced before assignment
在eggs
函数内,如果某个变量有被赋值,那么该变量就是局部变量,如果没有赋值,那么便会被解释为全局变量,所以对局部变量spam
进行操作的时候,在函数内并没有进行赋值,spam
被解释成全局变量,自然会出现错误。
2.2.4.Modifying while iterating
当对某个字典进行迭代的时候:
|
|
---------------------------------------------------------------------------
RuntimeError Traceback (most recent call last)
<ipython-input-9-b88de85f5f0b> in <module>()
1 dict_ = {'spam': 'eggs'}
2
----> 3 for key in dict_:
4 del dict_[key]
RuntimeError: dictionary changed size during iteration
改正方法如下:
dict_ = {'spam': 'eggs'}
for key in list(dict_):
del dict_[key]
2.2.5.Late binding
这个问题就是所谓的后期绑定,什么是后期绑定?请看下面的例子:
|
|
10
10
10
果然现实和理想是有差别的,为什么会造成这样的结果呢,是因为在匿名函数中i
的值是2,可是明明分别循环了0、1、2
。
你需要知道,定义一个函数后,函数内的变量并不是立刻就把值绑定了,而是在被调用的时候才会去查找变量,所以等egg(5)
去查找i这个变量的时候,i=5
,于是就造成了后期绑定这个陷阱。
要解决这个问题很简单,只需要在出现后期绑定前提前对变量进行赋值操作即可
|
|
0
5
10
|
|
0
5
10
|
|
0
5
10
总之,以上作为参考,能解决就好。
3.总结
本节笔记主要记录python
一些优雅的写法以及陷阱。
- 原文作者:howie.hu
- 原文链接:https://www.howie6879.com/post/2017/02_16/
- 版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可,非商业转载请注明出处(作者,原文链接),商业转载请联系作者获得授权。