文章大纲
回到 print 和 import
print
是一个内置函数,提供了多种参数:
print(*args, sep=' ', end='\n', file=None, flush=False)
Prints the values to a stream, or to sys.stdout by default.
sep
string inserted between values, default a space.
end
string appended after the last value, default a newline.
file
a file-like object (stream); defaults to the current sys.stdout.
flush
whether to forcibly flush the stream.
*args
表明 print
支持打印多个参数:
print('Hello', 'World')
Hello World
sep
代表多个参数之间的间隔符,默认为空格:
print('Hello', 'World', sep='--')
Hello--World
end
代表打印参数后在最后添加的内容,默认是换行:
print('Hello', 'World', sep='--', end='#This is end.')
Hello--World#This is end.
导入时重命名
导入模块时使用 import somemodule
时,会将该模块中的所有方法导入,使用时通过 modulename.functionname
方式使用。
使用 from somemodule import somefunction, anotherfunction ..
方式导入时,可直接使用 functionname
使用。
如果确定要导入模块中的一切式,使用 from somemodule import *
方式导入。
如果不同模块中的函数名称冲突,可以使用 as
来指定别名:
from math import pi as p
p
3.141592653589793
赋值魔法
赋值语句也存在一些有趣高效的方法。
序列解包
序列解包:将一个序列(或任何可迭代对象)解包,并将得到的值存储到一系列变量中。
data = [1,2,3]
x, y, z = data
print(x, y, z, sep='-')
1-2-3
使用返回元组(或其它序列或可迭代对象)的函数和方法时很有用:
data = {'name': 'imxcai', 'blog': 'www.imxcai.com'}
x, y = data.popitem()
print(x, y, sep='/')
blog/www.imxcai.com
要解包序列包含的的元素个数应与等号一侧的目标个数相同,否则将引发异常:
a,b,c = [1,2,3,4]
Traceback (most recent call last):
File "<pyshell#103>", line 1, in <module>
a,b,c = [1,2,3,4]
ValueError: too many values to unpack (expected 3)
可以使用 *
来收集多余的值:
a,b,*c = [1,2,3,4]
c
[3, 4]
*a,b,c = [1,2,3,4]
a
[1, 2]
带星号的变量可以放在任意位置,且最终返回的始终是一个列表:
a, b, *c = [1,2,3]
c
[3]
链式赋值
链式赋值是一种快捷方式,用于将多个变量关联到同一个值:
x = y = somefunction()
等效于:
y = somefouncation()
x = y
不等效于:
x = somefouncation()
y = somefouncation()
增强赋值
x = x + 1
可以将右边表达式中的运算符号移到赋值运算符(=) 的前面,变成 x += 1
这称为增强赋值,适用于所有标准运算符。
增强赋值也可以用于其它数据类型:
str = 'foo'
str += 'bar'
str
'foobar'
str *= 2
str
'foobarfoobar'
条件和条件语句
条件语句是让程序是否指定特定的语句块。
布尔值
标准值 False 和 None、各种类型(包括浮点数、复数)的数值 0 、空序列(空字符串、空元组和空列表)和空映射(空字典)都被视为假,而其它各种值都被视为真,包括特殊值 True。任何值都可以用 bool()
进行转换:
bool('abc')
True
bool(1)
True
bool([])
False
有条件的执行和 if 语句
if
语句能够有条件的执行代码,如果条件为真,就执行后续的代码,如果为假则不执行:
name = 'Bob Gumby'
if name.endswith('Gumby'):
print('Hello Gumby')
Hello Gumby
else 子句
else
子句为 if
条件为假时指定了要执行的语句:
name = 'Bob Gumby'
if name.endswith('bob'):
print('Hello bob')
else:
print('Welcome!')
Welcome!
elif 语句
elif
是 else if 的缩写,可用于检查多个条件:
num = int(input('Enter a number: '))
if num > 0:
print('The number is positive')
elif num < 0:
print('The number is negative')
else:
print('The number is zero')
更复杂的条件
在 if
语句中,条件本身很重要。
比较运算符
条件表达式中,最基本的运算符是比较运算符,用于执行比较。
表达式 | 描述 |
---|---|
x == y | x 等于 y |
x < y | x 小于 y |
x > y | x 大于 y |
x >= y | x 大于等于 y |
x <= y | x 小于等于 y |
x != y | x 不等于 y |
x is y | x 和 y 是同一对象 |
x is not y | x 和 y 不是同一对象 |
x in y | x 是容器 y 的成员 |
x not in y | x 不是容器 y 的成员 |
与赋值一样,也支持链式比较,如 0 < age < 100
。
布尔运算符
and
是一个布尔运算符,它接受两个真值,并在两个都为真时才返回真,否则返回假。
另外还有 or
和 not
这两个布尔运算符。
if ((cash > price) or customer_has_good_credit) and not out_of_stock:
give_goods()
断言
让程序在错误条件出现后立即崩溃胜过以后再崩溃。
如果知道必须满足特定条件,程序才能正确的运行,可在程序里面添加 assert
语句充当检查点。assert
可在条件后面添加一个字符串,用于说明:
age = -1
assert 0 < age < 100 , 'The age must be realistic!'
Traceback (most recent call last):
File "<pyshell#154>", line 1, in <module>
assert 0 < age < 100 , 'The age must be realistic!'
AssertionError: The age must be realistic!
循环
循环用于重复操作多次,执行周期性的任务。
while 循环
while
循环的格式如下:
x = 1
while x <= 100:
print(x)
x += 1
如果条件为 True
则一直循环。
for 循环
为序列(或其它可迭代对象)中的每个元素执行代码块可使用 for
循环:
data = [1,2,3,4,5]
for d in data:
print(d)
遍历是特定范围内的数,这是一种常见的任务,Python 提供了创建范围的内置函数 range
:
range(0,10)
range(0, 10)
type(range(0,10))
<class 'range'>
返回的是一个可迭代的对象,可直接进行迭代循环:
for i in range(0,3):
print(i)
0
1
2
也可以通过 list
转换为列表:
data = list(range(0,3))
data
[0, 1, 2]
迭代字典
迭代字典有两种方式,一种方式是迭代出 key
然后根据 key
获取 value
:
d = {'a': 'alice', 'b': 'bob', 'c': 'caer'}
for k in d:
print(k, '---', d[k])
a --- alice
b --- bob
c --- caer
另一种是通过 items
返回元组,然后通过序列解包的方式:
d = {'a': 'alice', 'b': 'bob', 'c': 'caer'}
for k, v in d.items():
print(k, '----', v)
a ---- alice
b ---- bob
c ---- caer
迭代工具
Python 提供了多个可帮助进行迭代序列的函数。
并行迭代
同时迭代两个序列,可用的方式有:
a = [1,2,3]
b = ['a','b','c']
for i in range(len(a)):
print(a[i], '---', b[i])
1 --- a
2 --- b
3 --- c
此外还可使用 zip
函数,该函数可以缝合任意数量的序列,当序列长度不同时,将在最短的序列用完后停止缝合:
a = [1,2,3]
b = ['a','b','c']
zip(a,b)
<zip object at 0x7f5ec92f95c0>
for x,y in zip(a,b):
print(x, y,sep='---')
1---a
2---b
3---c
list(zip(range(3),range(10000)))
[(0, 0), (1, 1), (2, 2)]
迭代时获取索引
内置函数 enumerate
能够迭代索引-值对,索引是自动提供的:
enumerate('abc')
<enumerate object at 0x7f5ec75c3380>
list(enumerate('abc'))
[(0, 'a'), (1, 'b'), (2, 'c')]
迭代循环时可以很容易的获取到索引:
strings = 'helloworld'
for index, string in enumerate(strings):
if string == 'w':
print('index is:', index, 'string is: ', string)
index is: 5 string is: w
反向迭代和排序后迭代
内置的函数 reversed
和 sorted
类似于列表方法中的 reverse
和 sort
,但这两个函数可以用于任何序列或可迭代的对象,且不就地修改对象,而是返回反转和排序后的版本。
sorted([2,5,1,8,4])
[1, 2, 4, 5, 8]
reversed('hello')
<reversed object at 0x7f5ec86f12a0>
list(reversed('hello'))
['o', 'l', 'l', 'e', 'h']
跳出循环
通常循环会不断的执行代码块,直到条件为假或使用完序列中的所有元素,但在有些情况下可以控制中断循环或进入新的一个循环。
break
要结束循环,可使用 break
,但执行到 break
语句时,将结束整个的循环:
for i in range(10000):
print(i)
if i == 1:
break
0
1
continue
continue
用于结束当前的迭代,并跳到下一个迭代的开头:
for i in range(0,10):
if i % 2 == 0:
continue
print(i)
1
3
5
7
9
while True/break 成例
while True
会导致循环永不结束,但可以在满足条件中的 if
语句中放置 break
:
while True:
word = input('Pls input some words: ')
if not word: break
print('The word was: ', word)
循环中的 else 子句
如何判断循环是提前结束还是正在结束呢?简单的方法是在循环外添加一条 else
子句,仅在没有调用 break
时才执行:
from math import sqrt
for n in range(99, 81, -1):
root = sqrt(n)
if root == int(root):
print(n)
break
else:
print("Didn't find it!")
简单推导
列表推导是一种从其它列表创建列表的方式,列表推导的工作原理类似于 for
循环:
[ x * x for x in range(10) ]
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
推导中还可以使用 if
语句来生成满足条件的元素:
[ x * x for x in range(10) if x % 3 == 0]
[0, 9, 36, 81]
添加更多的 for
结构:
[ (x, y) for x in range(3) for y in range(3) ]
[(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)]
同样,也可使用 if
语句:
[ (x, y) for x in range(3) for y in range(3) if x == y ]
[(0, 0), (1, 1), (2, 2)]
使用圆括号不能实现元组的推导,而是创建生成器。
但是可以使用花括号来执行字典的推导:
sqrts = { i: "{} squartd is {}".format(i, i**2) for i in range(10)}
sqrts[6]
'6 squartd is 36'
在列表推导中,for
前面只有一个表达式,在字典推导中,for
前面有两个用冒号分隔的表达式,两个表达式分别为键和对应的值。
三人行
pass
、del
和 exec
语句的使用。
什么都不做
pass
语句代表什么都不做,通常用于占位符。
if True:
pass
如果 if
中没有任何可执行的代码,程序将报错,此时可以使用 pass
语句。
使用 del 删除
对于没有任何变量或数据结构指向的对象,Python 通常会将其删除。del
语句会删除对象的引用,还会删除名称本身:
x = 1
del x
x
Traceback (most recent call last):
File "<pyshell#90>", line 1, in <module>
x
NameError: name 'x' is not defined
但是 del
不会删除对象本身,只会删除名称和引用:
y = x = 1
del x
x
Traceback (most recent call last):
File "<pyshell#93>", line 1, in <module>
x
NameError: name 'x' is not defined
y
1
Python 中没有办法删除值,也不需要删除,但一个值没有任何引用时(不再使用),会被 Python 自动回收,立即删除。
使用 exec 和 eval 执行字符串
exec
和 eval
是内置函数,可以动态的执行 Python 代码,能够将其作为语句进行或作为表达式进行计算。
exec
函数 exec
将字符串作为代码执行:
exec("print('hi')")
hi
大多数情况下,还应向它传递一个命名空间,命名空间是存放变量的地方,防止输入的代码污染命名空间,如修改之前定义的变量。
没有命名空间的情况:
from math import sqrt
type(sqrt)
<class 'builtin_function_or_method'>
exec("sqrt=1")
type(sqrt)
<class 'int'>
sqrt(4)
Traceback (most recent call last):
File "<pyshell#113>", line 1, in <module>
sqrt(4)
TypeError: 'int' object is not callable
动态执行的 exec
函数,将 sqrt
内置函数覆盖成了一个变量,导致后续使用函数报错。
为 exec
传递第二个字典类型的参数,用作代码字符串的命名空间:
from math import sqrt
scope = {}
exec('sqrt = 1', scope)
sqrt(4)
2.0
scope['sqrt']
1
scope
中还包含一个自动添加了所有内置函数和值的字典 __builtins__
。
scope.keys()
dict_keys(['__builtins__', 'sqrt'])
eval
exec
是执行一系列 Python 语句,eval
计算用字符串表示的 Python 表达式的值,并返回结果(exec
不返回结果,其本身就是条语句)。
eval(input(" Enter an artihmetic expression: "))
Enter an artihmetic expression: 10*5 + 20
70
与 exec
一样, eval
也可以添加命名空间,命名空间中可以提前放置一些值:
scope = {}
scope['x'] = 2
scope['y'] = 3
eval('x * y', scope)
6