使用逗号输出
print 的参数并不能像我们预期的那样构成一个元组
print 1, 2, 3
输出结果:
预想 (1, 2, 3)
实际 1, 2, 3
如果在结尾处加个逗号,那么接下来的语句会与前一条语句在同一行打印,例如:
print 'Hello,',
print 'world!'
输出结果:
Hello,world!
赋值魔法
- 序列解包
a, b, c = 1, 2, 3
print a
print b
print c
输出结果:
1
2
3
解包序列中的元素数量必须和放置在赋值符号=号左边的变量数量完全一致,否则Python在赋值时引发异常
a, b, c = 1, 2
输出结果:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: need more than 2 values to unpack
a, b = 1, 2, 3
输出结果:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: too many values to unpack
注意:
Python 3.0中有另一个解包的特性:可以想在函数的参数列表中一样使用星号运算符。例如:a, b, *reset = [1, 2, 3, 4]最终会在a和b都被赋值之后将所有其他的参数都收集到reset中。本例中,reset的结果将会是[3, 4]。使用星号的变量也可以放在第一个未知,这样它就总会包含一个列表。右侧的赋值语句可以是可迭代对象。
- 链式赋值
链式赋值是将同一个值赋给多个变量的捷径。
x = y = 'abc'
# 和下面语句的效果是一样的:
x = 'abc'
x = y
# 但不一定等价于下面语句
x = 'abc'
y = 'abc'
- 增量赋值,对于*、/、%等标准运算符都使用
x = 2
x += 1
x *= 2
print x
输出结果:
6
布尔值
下面的值在作为布尔值表达式的时候,会被解释器看作假(False):
False None 0 "" () [] {}
换句话说,也就是标准值False和None、所有类型的数字0(包括浮点型、长整型和其他类型)、空序列(比如空字符串、元组和列表)已经空的字典都为假。其它的一切都被解释为真,包括特殊值True。
布尔值True和False属于布尔类型,bool函数可以用来(和list、str以及tuple一样)转换其他值。
print bool("I'm bool")
print bool(520)
print bool("")
print bool(0)
输出结果:
True
True
False
False
因为所有值都可以用作布尔值,所以几乎不需要对它显示转换(可以说Python会自动转换这些值)
注意:尽管[]和""都是假值(也就是说bool([]) == bool("") == False),它们本身却并不相等(也就是说[] != "")。对于其他不同类型的假值对象也是如此(例如() != False)
断言 assert
一般来说,你可以要求某些条件必须为真(例如,在检查函数参数的属性时或者作为初期测试和调试过程中的辅助条件)。语句中使用的关键字是assert
age = 10
assert 0 < age < 100
age = -1
assert 0 < age < 100
输出结果:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AssertionError
条件后可以添加字符串,用来解释断言:
age = -1
assert 0 < age < 100, 'age 必须大于0小于100'
输出结果:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AssertionError: age 必须大于0小于100
一些迭代工具
- 并行迭代
程序可以同时迭代两个序列。比如有下面两个列表
names = ['Daniel', 'zhuqipeng']
ages = [23, 22]
如果想要打印名字和对应的年龄,可以像下面这样做:
for i in range(len(names)):
print names[i], 'is', ages[i], 'years old'
而内建的zip
函数可以用来进行并行迭代,可以把两个序列压缩
在一起,然后返回一个元组列表:
zip(names, ages)
# [('Daniel', 23), ('zhuqipeng', 22)]
现在我可以在循环中解包元组:
for name, age in zip(names, ages):
print name, 'is', age, 'years old'
输出结果:
Daniel is 23 years old
zhuqipeng is 22 years old
zip
函数也可以作用于任意多的序列。关于它很重要的一点是zip
可以应付不等长的序列,最短的序列 “用完” 的时候就会停止:
zip(range(5), xrange(10000))
输出结果:
[(0, 0), (1, 1), (2, 2), (3, 3), (4, 4)]
- 翻转和排序迭代
另外两个函数:reversed和sorted,它们同列表的reverse和sort(sorted和sort使用同样的参数)方法类似,但作用于任何序列或可迭代对象上,不是原地修改对象,而是翻转或排序后的版本:
sorted([5, 4, 3, 2, 1])
sorted('Daniel')
list(reversed('Daniel'))
''.join(reversed('Daniel'))
输出结果:
[1, 2, 3, 4, 5]
['D', 'a', 'e', 'i', 'l', 'n']
['l', 'e', 'i', 'n', 'a', 'D']
leinaD
注意:sorted方法返回列表,reversed方法却返回一个不可思议的可迭代对象。在for循环以及join方法中使用不会有任何问题。不过却不能直接对它使用索引、分片已经调用list方法。
使用exec和eval执行和求值字符串
- exec 执行一个字符串的语句
很多情况下可以给它提供命名空间-可以放置变量的地方。这样做使代码不会干扰命名空间(也就是改变你的变量),比如下面的代码中干扰到了sqrt
from math import sqrt
exec 'sqrt = 1'
sqrt(4)
输出结果:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'int' object is not callable
所以为了安全起见,可以增加一个字典,起到命名空间的作用。可以通过增加 in <scope>
来实现,其中的<scope>
就是起到放置代码字符串命名空间作用的字典。
from math import sqrt
scope = {}
exec 'sqrt = 1' in scope
sqrt(4)
scope['sqrt']
输出结果:
2.0
1
- eval 用于求值,是类似于内建函数。exec语句会执行一系列Python语句,而eval会计算Python表达式(以字符串形式书写),并且返回结果值,(exec 语句并不返回任何对象,因为它本身就是语句)
跟exec一样,eval也可以使用命名空间。
初探作用域
# 给exec或者eval语句提供命名空间时,还可以在真正使用命名空间前放置一些值进去:
scope = {}
scope['x'] = 2
scope['y'] = 3
eval('x * y', scope)
# 同理,exec或者eval调用的作用域也能在另外一个上面使用:
scope = {}
exec 'x = 2' in scope
eval('x * x', scope)
输出结果:
6
4