2.1 Python解释器
Python是解释性语言。Python解释器同一时间只能运行一个程序的一条语句。标准的交互Python解释器可以在命令行中通过键入python命令打开:
C:\Users\Sherlock>python
Python 3.11.4 (tags/v3.11.4:d2340ef, Jun 7 2023, 05:45:37) [MSC v.1934 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>>
>>>
提示输入代码。
要退出Python解释器返回终端,可以输入exit()
或按Ctrl-D
。
假设创建了一个hello_world.py
文件,可以用下面的命令运行它(.py
文件必须位于终端的工作目录):python hello_world.py
。
使用%run
命令,IPython会同样执行指定文件中的代码,结束之后,还可以与结果交互:
D:\Tool\Python>ipython
Python 3.11.4 (tags/v3.11.4:d2340ef, Jun 7 2023, 05:45:37) [MSC v.1934 64 bit (AMD64)]
Type 'copyright', 'credits' or 'license' for more information
IPython 8.14.0 -- An enhanced Interactive Python. Type '?' for help.
In [1]: %run hello_world.py
Hello world
In [2]:
IPython默认采用序号的格式In [2]:
,与标准的>>>
提示符不同。
2.2 IPython基础
1、运行IPython Shell
用ipython
在命令行打开IPython Shell,就像打开普通的Python解释器。可以通过输入代码并按Return(或Enter),运行任意Python语句。当你只输入一个变量,它会显示代表的对象。
D:\Tool\Python>ipython
Python 3.11.4 (tags/v3.11.4:d2340ef, Jun 7 2023, 05:45:37) [MSC v.1934 64 bit (AMD64)]
Type 'copyright', 'credits' or 'license' for more information
IPython 8.14.0 -- An enhanced Interactive Python. Type '?' for help.
In [1]: a = 5
In [2]: a
Out[2]: 5
In [5]: import numpy as np
In [6]: data = {i : np.random.randn() for i in range(7)}
In [7]: data
Out[7]:
{0: -0.20470765948471295,
1: 0.47894333805754824,
2: -0.5194387150567381,
3: -0.55573030434749,
4: 1.9657805725027142,
5: 1.3934058329729904,
6: 0.09290787674371767}
前两行是Python代码语句;第二条语句创建一个名为data
的变量,它引用一个新创建的Python字典。最后一行打印data
的值。
许多Python对象被格式化为更易读的形式,或称作pretty-printed
,它与普通的print
不同。如果在标准Python解释器中打印上述data
变量,则可读性要降低:
>>> from numpy.random import randn
>>> data = {i : randn() for i in range(7)}
>>> print(data)
{0: -1.5948255432744511, 1: 0.10569006472787983, 2: 1.972367135977295,
3: 0.15455217573074576, 4: -0.24058577449429575, 5: -1.2904897053651216,
6: 0.3308507317325902}
IPython还支持执行任意代码块(通过一个华丽的复制-粘贴方法)和整段Python脚本的功能。
2、运行Jupyter Notebook
notebook是Jupyter项目的重要组件之一,它是一个代码、文本(有标记或无标记)、数据可视化或其它输出的交互式文档。
Python的Jupyter内核是使用IPython。要启动Jupyter,在命令行中输入jupyter notebook
:
要新建一个notebook,点击按钮New,选择“Python3”。如果是第一次,点击空格,输入一行Python代码。然后按Shift-Enter执行。
当保存notebook时(File目录下的Save and Checkpoint),会创建一个后缀名为.ipynb
的文件。这是一个自包含文件格式,包含当前笔记本中的所有内容(包括所有已评估的代码输出)。可以被其它Jupyter用户加载和编辑。
要加载存在的notebook,把它放到启动notebook进程的相同目录内。
3、Tab补全
IPython shell的进步之一是具备其它IDE和交互计算分析环境都有的tab补全功能。在shell中输入表达式,按下Tab
,会搜索已输入变量(对象、函数等等)的命名空间。(输入an
后按下tab
键)
IPython呈现出了之前两个定义的变量和Python内建的函数any
。
也可以补全任何对象的方法和属性。例如,列表list。
同样适用于模块。
注意,默认情况下,IPython会隐藏下划线开头的方法和属性,比如魔术方法和内部的“私有”方法和属性,以避免混乱的显示(和让新手迷惑!)这些也可以tab补全,但是你必须首先键入一个下划线才能看到它们。如果你喜欢总是在tab补全中看到这样的方法,你可以IPython配置中进行设置。可以在IPython文档中查找方法。
输入看似文件路径时(即使是Python字符串),按下Tab也可以补全电脑上对应的文件信息。
结合%run
,tab
补全可以节省许多键盘操作。
tab补全可以补全函数的关键词参数(包括等于号=)。
4、自省
在变量前后使用问号?
,可以显示对象的信息:
这可以作为对象的自省。如果对象是一个函数或实例方法,定义过的文档字符串,也会显示出信息。假设我们写了一个如下的函数:
然后使用?
符号,就可以显示如下的文档字符串:
使用??
会显示函数的源码:
?
还有一个用途,就是像Windows命令行一样搜索IPython的命名空间。字符与通配符结合可以匹配所有的名字。例如,我们可以获得所有包含load的顶级NumPy命名空间:
5、%run命令
可以用%run
命令运行所有的Python程序。
In [14]: %run ipython_script_test.py
文件中所有定义的变量(import、函数和全局变量,除非抛出异常),都可以在IPython shell中随后访问。
如果一个Python脚本需要命令行参数(在sys.argv
中查找),可以在文件路径之后传递,就像在命令行上运行一样。
如果想让一个脚本访问IPython已经定义过的变量,可以使用%run -i
。
可以使用%load
,它将脚本导入到一个代码格中。
>>> %load ipython_script_test.py
def f(x, y, z):
return (x + y) / z
a = 5
b = 6
c = 7.5
result = f(a, b, c)
6、中断运行的代码
代码运行时按Ctrl-C
,无论是%run
或长时间运行命令,都会导致KeyboardInterrupt
。
但是, 当Python代码调用了一些编译的扩展模块,按Ctrl-C不一定将执行的程序立即停止。在这种情况下,你必须等待,直到控制返回Python解释器,或者在更糟糕的情况下强制终止Python进程。
7、从剪贴板执行程序
Jupyter notebook,你可以将代码复制粘贴到任意代码格执行。
IPython shell中也可以从剪贴板执行。方法是使用%paste
和%cpaste
函数。
比如复制了如下代码:
x = 5
y = 7
if x > 5:
x += 1
y = 8
%paste
可以直接运行剪贴板中的代码。
In [17]: %paste
x = 5
y = 7
if x > 5:
x += 1
y = 8
## -- End pasted text --
%cpaste
功能类似,但会给出一条提示:
In [18]: %cpaste
Pasting code; enter '--' alone on the line to stop or use Ctrl-D.
:x = 5
:y = 7
:if x > 5:
: x += 1
:
: y = 8
:--
使用%cpaste
,你可以粘贴任意多的代码再运行。你可能想在运行前,先看看代码。如果粘贴了错误的代码,可以用Ctrl-C
中断。
8、键盘快捷键
9、魔术命令
IPython中特殊的命令(Python中没有)被称作 “魔术”命令。魔术命令是在指令前添加百分号%
前缀。例如,可以用%timeit
测量任何Python语句,例如矩阵乘法,的执行时间:
In [20]: a = np.random.randn(100, 100)
In [20]: %timeit np.dot(a, a)
10000 loops, best of 3: 20.9 µs per loop
魔术命令可以被看做IPython中运行的命令行。许多魔术命令有“命令行”选项,可以通过?
查看:
In [21]: %debug?
魔术函数默认可以不用百分号,只要没有变量和函数名相同。这个特点被称为 “自动魔术”,可以用%automagic
打开或关闭。
交互计算和Python开发的IPython指令:
10、集成Matplotlib
IPython在分析计算领域能够流行的原因之一是它非常好的集成了数据可视化和其它用户界面库,比如matplotlib。%matplotlib
魔术函数配置了IPython shell和Jupyter notebook中的matplotlib。它创建的图不会出现(notebook)或获取session的控制,直到结束(shell)。
在IPython shell中,运行%matplotlib
可以进行设置,可以创建多个绘图窗口,而不会干扰控制台session:
In [26]: %matplotlib
Using matplotlib backend: Qt4Agg
在Jupyter中,命令有所不同。%matplotlib inline
2.3 Python语法基础
1、使用缩进,而不是括号
Python使用空白字符(tab和空格)来组织代码。冒号标志着缩进代码块的开始,冒号之后的所有代码的缩进量必须相同,直到代码块结束。强烈建议你使用四个空格作为默认的缩进,可以使用 tab 代替四个空格。例如:
for x in array:
if x < pivot:
less.append(x)
else:
greater.append(x)
2、万物皆对象
每个数字、字符串、数据结构、函数、类、模块等等,都是在Python解释器的自有“盒子”内,它被认为是Python对象。每个对象都有类型(例如,字符串或函数)和内部数据。
3、注释
前面带#
的文本。也可以在代码后面添加注释。
4、函数和对象方法调用
用圆括号调用函数,传递零个或几个参数,或者将返回值给一个变量:
result = f(x, y, z) # 调用函数并传递3个参数,并将结果返回给result
g() # 调用函数
几乎Python中的每个对象都有附加的函数,称作方法,可以用来访问对象的内容。可以用.
调用方法:
obj.some_method(x, y, z)
函数可以使用位置和关键词参数:
result = f(a, b, c, d=5, e='foo')
5、变量和参数传递
在Python中创建变量(或名字),你就在等号右边创建了一个对这个变量的引用。
注意:b = a
和 b = a[:]
的区别。
赋值也被称作绑定,我们是把一个名字绑定给一个对象。变量名有时可能被称为绑定变量。将对象作为参数传递给函数时,新的局域变量创建了对原始对象的引用,而不是复制。
引用 就是将两个变量指向了同一个地址,改变引用的变量的值,原变量的值也会发生改变。
6、动态引用,强类型
与许多编译语言(如JAVA和C++)对比,Python中的对象引用不包含附属的类型。在下面的代码中,变量a
的类型由int
转换为str
。
In [12]: a = 5
In [13]: type(a)
Out[13]: int
In [14]: a = 'foo'
In [15]: type(a)
Out[15]: str
变量是在特殊命名空间中的对象的名字,类型信息保存在对象自身中。
Python被认为是强类型化语言。在Python中,每个对象都有自己明确的类型,一般不会发生默许转换。例如:
In [16]: '5' + 5
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-16-f9dbf5f0b234> in <module>()
----> 1 '5' + 5
TypeError: must be str, not int
但在某些语言中,例如Visual Basic,字符串‘5’可能被默许转换(或投射)为整数。
在Python中,默许转换只会发生在特定情况下,例如:
In [17]: a = 4.5
In [18]: b = 2
# String formatting, to be visited later(字符串格式,稍后访问)
In [19]: print('a is {0}, b is {1}'.format(type(a), type(b)))
a is <class 'float'>, b is <class 'int'>
In [20]: a / b
Out[20]: 2.25
可以用isinstance
函数检查对象是某个类型。isinstance
函数还可以用类型元组,检查对象的类型是否在元组中。
In [22]: isinstance(a, int)
In [24]: isinstance(a, (int, float))
7、属性和方法
Python的对象通常都有属性(其它存储在对象内部的Python对象)和方法(对象的附属函数可以访问对象的内部数据)。
- 可以用
obj.attribute_name
访问属性和方法:
In [1]: a = 'foo'
In [2]: a.<Press Tab> # 以下就是对象a的所有属性和方法
a.capitalize a.format a.isupper a.rindex a.strip
a.center a.index a.join a.rjust a.swapcase
a.count a.isalnum a.ljust a.rpartition a.title
a.decode a.isalpha a.lower a.rsplit a.translate
a.encode a.isdigit a.lstrip a.rstrip a.upper
a.endswith a.islower a.partition a.split a.zfill
a.expandtabs a.isspace a.replace a.splitlines
a.find a.istitle a.rfind a.startswith
可以用 .
调用这些方法。
- 也可以用
getattr
函数,通过名字访问属性和方法:
In [27]: getattr(a, 'split')
Out[27]: <function str.split>
8、鸭子类型
不关心对象的类型,只关心对象是否有某些方法或用途,这通常被称为“鸭子类型”。
可以通过验证一个对象是否遵循迭代协议,判断它是可迭代的。对于许多对象,这意味着它有一个__iter__
魔术方法(左右分别是两个下划线_
),其它更好的判断方法是使用iter
函数:
def isiterable(obj):
try:
iter(obj)
return True
except TypeError: # not iterable
return False
这个函数会返回字符串以及大多数Python集合类型为True
,例如:
In [29]: isiterable('a string')
Out[29]: True
In [30]: isiterable([1, 2, 3])
Out[30]: True
In [31]: isiterable(5)
Out[31]: False
9、引入
在Python中,模块就是一个有.py
扩展名、包含Python代码的文件。假设有以下模块:
# some_module.py
PI = 3.14159
def f(x):
return x + 2
def g(a, b):
return a + b
如果想从同目录下的另一个文件访问some_module.py
中定义的变量和函数,可以使用关键字import
引入该模块:
import some_module
result = some_module.f(5)
pi = some_module.PI
或者:
from some_module import f, g, PI
result = g(5, PI)
使用as
关键词,你可以给引入起不同的变量名:
import some_module as sm
from some_module import PI as pi, g as gf
r1 = sm.f(pi)
r2 = gf(6, pi)
10、二元运算和比较运算符
判断两个引用是否指向同一个对象,可以使用is
或者is not
方法。
In [35]: a = [1, 2, 3]
In [36]: b = a
In [37]: c = list(a)
In [38]: a is b
Out[38]: True
In [39]: a is not c
Out[39]: True
In [40]: a == c
Out[40]: True
注意! 使用is
比较与==
运算符不同。is
是判断是否指向同一地址,而==
则是判断内容是否相同。
is
和is not
常用来判断一个变量是否为None
,因为只有一个None
的实例:
In [41]: a = None
In [42]: a is None
Out[42]: True
11、可变与不可变对象
Python中的大多数对象,比如列表、字典、NumPy数组,和用户定义的类型(类),都是可变的,意味着这些对象或包含的值可以被修改。
In [43]: a_list = ['foo', 2, [4, 5]]
In [44]: a_list[2] = (3, 4)
In [45]: a_list
Out[45]: ['foo', 2, (3, 4)]
其它的,例如字符串和元组,是不可变的。
In [46]: a_tuple = (3, 5, (4, 5))
In [47]: a_tuple[1] = 'four'
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-47-b7966a9ae0f1> in <module>()
----> 1 a_tuple[1] = 'four'
TypeError: 'tuple' object does not support item assignment
可以修改一个对象并不意味就要修改它。这被称为副作用。任何副作用都要在文档或注释中写明。推荐避免副作用,采用不可变的方式,即使要用到可变对象。
12、标量类型
Python的标准库中有一些内建的类型,用于处理数值数据、字符串、布尔值,和日期时间。这些单值类型被称为标量类型,本书中称其为标量。主要的标量有:
日期和时间处理会另外讨论,因为它们是标准库的datetime
模块提供的。
13、数值类型
Python的主要数值类型是int
和float
。int
可以存储任意大的数:
In [48]: ival = 17239871
In [49]: ival ** 6
Out[49]: 26254519291092456596965462913230729701102721
浮点数使用Python的float
类型。每个数都是双精度(64位)的值。也可以用科学计数法表示:
In [50]: fval = 7.243
In [51]: fval2 = 6.78e-5
不能得到整数的除法会得到浮点数:
In [52]: 3 / 2
Out[52]: 1.5
要获得C-风格的整除(去掉小数部分),可以使用底除运算符//
(地板除):
In [53]: 3 // 2
Out[53]: 1
14、字符串
用单引号''
或双引号""
来写字符串。对于有换行符的字符串,可以使用三引号,'''
或"""
都行。
c = """
This is a longer string that
spans multiple lines
"""
字符串c
实际包含四行文本,"""
后面和lines后面的换行符。可以用count
方法计算c
中的新的行:
In [55]: c.count('\n') # 有3个换行符,所以有4行文本
Out[55]: 3
Python的字符串是不可变的,不能修改字符串。
许多Python对象使用str
函数可以被转化为字符串:
In [61]: a = 5.6
In [62]: s = str(a)
In [63]: print(s)
5.6
字符串是一个序列的Unicode字符,因此可以像其它序列,比如列表和元组(下一章会详细介绍两者)一样处理:
In [64]: s = 'python'
In [65]: list(s)
Out[65]: ['p', 'y', 't', 'h', 'o', 'n']
In [66]: s[:3]
Out[66]: 'pyt'
语法s[:3]
被称作切片,适用于许多Python序列。
反斜杠\
是转义字符,意思是它准备用来表示特殊字符,比如换行符\n
等。
要写一个包含反斜杠的字符串,需要进行转义:
In [67]: s = '12\\34'
In [68]: print(s)
12\34
声明字符串非转义,可以在字符串前面加一个r
,表明字符就是它自身。r
表示raw。
In [69]: s = r'this\has\no\special\characters'
In [70]: s
Out[70]: 'this\\has\\no\\special\\characters'
#实际上输出的就是'this\has\no\special\characters',字符串中多加一个反斜杠进行转义,就可以得到原本想得到的有一个反斜杠的字符串。
两种输出实际结果都是12\13
,只是表现的形式不一样。
将两个字符串合并,可以直接使用+
。
In [71]: a = 'this is the first half '
In [72]: b = 'and this is the second half'
In [73]: a + b
Out[73]: 'this is the first half and this is the second half'
字符串的模板化或格式化,是另一个重要的主题。比如,字符串对象有format
方法,可以替换格式化的参数为字符串,产生一个新的字符串:
In [74]: template = '{0:.2f} {1:s} are worth US${2:d}'
在这个字符串中,
{0:.2f}
表示格式化第一个参数为带有两位小数的浮点数。{1:s}
表示格式化第二个参数为字符串。{2:d}
表示格式化第三个参数为一个整数。
要替换参数为这些格式化的参数,我们传递format
方法一个序列:
In [75]: template.format(4.5560, 'Argentine Pesos', 1)
Out[75]: '4.56 Argentine Pesos are worth US$1'
15、字节和Unicode
在Python 3及以上版本中,Unicode是一级的字符串类型,可以更一致的处理ASCII和Non-ASCII文本。知道字符编码,可以将其转化为Unicode。看一个例子:
In [76]: val = "español"
In [77]: val
Out[77]: 'español'
可以用encode
将这个Unicode字符串编码为UTF-8:
In [78]: val_utf8 = val.encode('utf-8') #将Unicode转为utf-8编码
In [79]: val_utf8
Out[79]: b'espa\xc3\xb1ol'
In [80]: type(val_utf8) # utf-8编码的是字节对象,而Unicode则是str对象,即字符串对象
Out[80]: bytes
知道一个字节对象的Unicode编码,用decode
方法可以解码:
In [81]: val_utf8.decode('utf-8') #将utf-8转为Unicode编码
Out[81]: 'español'
在字节文本的前面加上一个b
,使得该文本使用utf-8编码:
In [85]: bytes_val = b'this is bytes'
In [86]: bytes_val
Out[86]: b'this is bytes'
In [87]: decoded = bytes_val.decode('utf8') #解码,utf-8转为Unicode编码
In [88]: decoded # this is str (Unicode) now #当前是Unicode编码
Out[88]: 'this is bytes'
16、布尔值
Python中的布尔值有两个,True
和False
。可以与and
、or
和not
结合使用。
17、类型转换
str、bool、int和float也是函数,可以用来转换类型:
In [91]: s = '3.14159'
In [92]: fval = float(s)
In [93]: type(fval)
Out[93]: float
In [94]: int(fval)
Out[94]: 3
In [95]: bool(fval)
Out[95]: True
In [96]: bool(0)
Out[96]: False
18、None
None
是Python的空值类型。
如果一个函数没有明确的返回值,就会默认返回None
。
None
也常常作为函数的默认参数:
def add_and_maybe_multiply(a, b, c=None):
pass
None
不仅是一个保留字,还是唯一的NoneType
的实例。
In [101]: type(None)
Out[101]: NoneType
19、日期和时间
Python内建的datetime
模块提供了datetime
、date
和time
类型。
datetime
类型结合了date
和time
,是最常使用的:
In [102]: from datetime import datetime, date, time
In [103]: dt = datetime(2011, 10, 29, 20, 30, 21)
In [104]: dt.day
Out[104]: 29
根据datetime
实例,你可以用date
和time
提取出各自的对象:
In [106]: dt.date()
Out[106]: datetime.date(2011, 10, 29)
In [107]: dt.time()
Out[107]: datetime.time(20, 30, 21)
strftime
方法可以将datetime
格式化为字符串:f指format(格式化)
In [108]: dt.strftime('%m/%d/%Y %H:%M')
Out[108]: '10/29/2011 20:30'
strptime
可以将字符串转换成datetime
对象:p指parse(解析)
In [109]: datetime.strptime('20091031', '%Y%m%d')
Out[109]: datetime.datetime(2009, 10, 31, 0, 0)
所有的格式化命令:
替换datetimes的 time字段 要使用replace
方法。例如,用0替换分和秒:
In [110]: dt.replace(minute=0, second=0)
Out[110]: datetime.datetime(2011, 10, 29, 20, 0)
因为datetime.datetime
是不可变类型,上面的方法会产生新的对象。
两个datetime对象的差会产生一个datetime.timedelta
类型:
In [111]: dt2 = datetime(2011, 11, 15, 22, 30)
In [112]: delta = dt2 - dt # dt2和dt都是datetime对象
In [113]: delta
Out[113]: datetime.timedelta(17, 7179)
In [114]: type(delta)
Out[114]: datetime.timedelta
结果timedelta(17, 7179)
指明了timedelta
将17天、7179秒的编码方式。
将timedelta
添加到datetime
,会产生一个新的偏移datetime
:
In [115]: dt
Out[115]: datetime.datetime(2011, 10, 29, 20, 30, 21)
In [116]: dt + delta
Out[116]: datetime.datetime(2011, 11, 15, 22, 30)
20、控制流
Python有若干内建的关键字进行条件逻辑、循环和其它控制流操作。
21、if、elif 和 else
if
后面可以跟一个或多个elif
,所有条件都是False
时,还可以添加一个else
:
if x < 0:
print('It's negative')
elif x == 0:
print('Equal to zero')
elif 0 < x < 5:
print('Positive but smaller than 5')
else:
print('Positive and larger than or equal to 5')
如果某个条件为True
,后面的elif
就不会被执行。当使用and
和or
时,复合条件语句是从左到右执行:
In [117]: a = 5; b = 7
In [118]: c = 8; d = 4
In [119]: if a < b or c > d:
print('Made it')
Made it
在这个例子中,c > d
不会被执行,因为第一个比较是True
。
也可以把比较式串在一起:
In [120]: 4 > 3 > 2 > 1
Out[120]: True
22、for循环
for
循环是在一个集合(列表或元组)中进行迭代,或者就是一个迭代器。for
循环的标准语法是:
for value in collection:
# do something with value
- 可以用
continue
使for
循环提前,跳过当前循环,直接开始下一次循环。 - 可以用
break
跳出整个for
循环,循环提前结束。
如果循环有多层,break
只会跳出最内层的循环,其他层的循环仍会继续运行:
In [121]: for i in range(4):
.....: for j in range(4):
.....: if j > i:
.....: break
.....: print((i, j))
.....:
(0, 0)
(1, 0)
(1, 1)
(2, 0)
(2, 1)
(2, 2)
(3, 0)
(3, 1)
(3, 2)
(3, 3)
如果集合或迭代器中的元素序列(元组或列表),可以用for
循环将其方便地拆分成变量:
for a, b, c in iterator:
# do something
23、While循环
while
循环指定了条件和代码,当条件为False
或用break
退出循环,代码才会退出:
x = 256
total = 0
while x > 0:
if total > 500:
break
total += x
x = x // 2
24、pass
pass是Python中的非操作语句。代码块不需要任何动作时可以使用(作为未执行代码的占位符);因为Python需要使用空白字符划定代码块,所以需要pass:
if x < 0:
print('negative!')
elif x == 0:
# TODO: put something smart here
pass
else:
print('positive!')
25、range
range
函数返回一个迭代器,它产生一个均匀分布的整数序列,range
的三个参数是(起点,终点,步进)。默认起点为0,步进为1。
In [122]: range(10)
Out[122]: range(0, 10)
In [123]: list(range(10))
Out[123]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
In [125]: list(range(5, 0, -1))
Out[125]: [5, 4, 3, 2, 1]
range
产生的整数不包括终点。
range
的常见用法是用序号迭代序列:
seq = [1, 2, 3, 4]
for i in range(len(seq)):
val = seq[i]
可以使用list
来存储range
在其他数据结构中生成的所有整数。
虽然range
可以产生任意大的数,但任意时刻耗用的内存却很小。
26、三元表达式
Python中的三元表达式可以将if-else
语句放到一行里。语法如下:
value = true-expr if condition else false-expr
true-expr
或false-expr
可以是任何Python代码。它和下面的代码效果相同:
if condition:
value = true-expr
else:
value = false-expr
更具体的例子:
In [126]: x = 5
In [127]: 'Non-negative' if x >= 0 else 'Negative'
Out[127]: 'Non-negative'
和if-else
一样,只有一个表达式会被执行。因此,三元表达式中的if
和else
可以包含大量的计算,但只有True
的分支会被执行。
虽然使用三元表达式可以压缩代码,但会降低代码可读性。