介绍
Python 3.8发布于2019年10月14日,在很多方面都进行了提升,特别是加入了海象运算符,用习惯了还是挺方便的,大家快来尝鲜吧。
知识点
- 海象运算符
- 字典反转
- f-string
- 仅限位置形参
Python3.8安装
官方网址:
Python Release Python 3.8.1 | Python.org

根据自己系统选择所需下载版本,我是Windows x86系统选的是这个图形化的安装自动安装,绝大多数情况下,特别是学习阶段,32位还是64位没有区别。今后我们编写的所有Python代码,也不会区分是多少位。
大家现在所用的Python是C语言实现的CPython,它可以直接使用C语言编写的模块。这些C语言模块针对不同位数的Python编译出来的结果只能用在特定的版本上。
大多数情况下,这些模块会同时提供针对不同位数的版本,直接使用pip install的时候会自动匹配。只是有些时候手动下载安装包的时候,需要注意版本要匹配一致。
开始安装

可以选择Install Now(立即安装),也可以选择Customize installation(自定义安装),想偷懒的可以直接选择Install Now
自定义安装有2个对话框选择,
第一个默认都是勾选上的,每个选项是啥意思介绍如下:

- Documentation离线的.chm格式文档,必须保留。英文还OK的小伙伴可以直接看这份文档,比所有书都靠谱。看英文有压力的,平时随时查查标准库模块用法什么的是极好的。
- pip Python包下载工具,必须保留。(想找虐的随意)
- tcl/tk and IDLE,说来话长,保留就对了。
- Python test suite,这个可以没有,当然留下来也没关系。
- py launcher,前面介绍过了。这里额外注意的是for all user选项,可以选择是否对所有用户安装。如果对所有用户安装,则需要administrator的权限。
第2个对话框是高级选项:

- Install for all user,是否对所有人安装,如果是,需要 administrator 的权限,并且安装路径会有所不同。
- 关联文件到Python,这个保持原样即可。它就是把 .py 文件和 python 程序关联起来,这样双击 .py 文件的时候,自动就用 python 去执行了。
- 创建快捷方式,保持原样即可。
- 添加Python到环境变量,第2次修改的机会
- 预编译标准库,一次性的把标准库的 .py 都预编译成 .pyc,没什么必要,会多花费安装时间,不选
- 两个download debug xxx,不知道哪里会用到,都不选
最下面是指定安装路径,个人意见,保持默认即可。如果取消勾选为所有人安装,则默认安装的路径会比较深,这个看上去有点不舒服,但是绝大多数情况下我们都不会直接造访该目录,所以不会有什么影响。
“ 我个人的推荐操作是 不选择对所有用户安装,这样如果想使用多个用户,每个用户有自己选择的自由。“
安装后的基本测试
安装完成后,新打开一个命令行窗口,win + r,然后输入cmd(ps:“ 注意,必须重新打开,在安装Python前已打开的命令行不会自动更新环境变量。”)
依次执行下面的命令:
#注意,-0后面是数字0,不是字母o
py -0
或者
py --list
这就是调用Python启动器,它显示出系统中已安装的Python版本。
python --version这是直接调用Python解释器,打印出它的版本。
pip --version
为什么要测试这3个命令,因为它们分别安装在了不同的位置,都工作正常了,就证明安装没有问题了。
想要了解更多细节,我们来查看 PATH 环境变量。
安装后的 PATH 变化
因为没有选择为所有用户安装,所以环境变量看当前用户的:
“ 安装时的选择不同,这里环境变量出现的位置也会有所不同”

上面3条就是安装后自动添加的。
“ 注意,如果 launcher 没有取消勾选 for all user,则会默认安装在系统目录下,就不需要添加到 PATH,这里就只有2条新增。
安装目录详情
先来看 C:\Users\Davy\AppData\Local\Programs\Python\Python38,也就是Python的安装路径,它是包含 python.exe 的目录。
其它目录的作用:
- DLLs,静态链接库,里面是一些 .dll 和 .pyd 文件,一般不会直接和这个目录打交道
- Doc,文档,里面就是一个 python381.chm,快捷方式里包含了该文档路径,所以平常不会直接访问
- include,头文件,基本上不会用到
- Lib,这个目录最最重要,几乎所有的标准库源码都在这里面了,大部分平常都不会去动它们,除了其中一个子目录:
- site-packages 后续安装的第三方模块和包都会出现在这里,所以偶尔出现问题,我们会造访这里。
- libs,几乎不会直接用到,注意和 Lib 区分开。(因为Windows系统路径不区分大小写,所以Lib实际会展示成lib)
- Scripts,后续安装的第三方包如果提供了命令,可执行文件就会出现在这里。例如 pip.exe 就是在此目录下,而Lib目录下保存的是pip的源码。
- tcl,仍然是说来话长,略过
- Tools,自带的一些Python脚本,包括一些 demo,其中有些可以作为学习参考。
最后看 launcher 的目录,它要管理所有的Python版本,所以它是超脱在外的,安装在了Python38的上级目录中。
启动菜单详情

安装Python后在开始菜单会多出来4个快捷方式,一般很少用,做一个简单的介绍:
- IDLE (Python 3.8 64-bit),用来启动IDLE,以后再详细介绍它。
- Python 3.8 Module Docs (64-bit),点击会自动启动一个本地web服务,然后自动打开包含模块文档的网页,样式非常古老,而且其中的内容都包含在下面的文档文件中了,所以基本没人会用这个。
- Python 3.8 Manuals (64-bit),点击打开文档
- Python 3.8 (64-bit),点击用来启动Python解释器。用这种方法启动解释器,退出后就整个黑窗口都消失了,打印的信息也都看不到了,所以我们一般是先启动命令行,再从命令行内启动Python,这样即使解释器退出了,也能看到刚才程序执行的结果。
海象运算符(赋值表达式)
海象运算符 := 可在表达式内部为变量赋值,虽然官方名称叫赋值表达式,可它的昵称海象运算符更为人熟知,至于昵称的由来其实仔细观察就会发现,它很像海象的眼睛和长牙。
先举个例子:
a='abcdefg'
if len(a)>3:
print(f'字符串{a}的长度是{len(a)}')
运行结果为:

可以看到,例子中的 len 函数用了两次,这种重复的运算肯定会对性能产生影响。原本我们是可以提前先把len函数的值算出来的,可那样又多写了一行,让代码不那么简洁。
那么我们再用海象运算符重新写一下:
a='abcdefg'
if (b:=len(a))>3:
print(f'字符串{a}的长度是{b}')
运行结果如下:

可以看到, (b:=len(a)) 部分其实就是把 len(a) 算出来的值赋值到 b 了,后面我们就能直接使用 b 的值了。
需要注意的是,这里一定要用括号括起来,因为大于号 > 比海象运算符 := 优先级高,不括起来相当于先计算后面部分,然后赋值给b也就是 b:=(len(a)>3) 得到的b的值就变成布尔值了。其他一些场合不括起来还可能报错,需要注意。大家可以多多尝试,仔细体会。
下面再来一个有趣的例子,见识一下海象运算符的威力。
相信很多人都用Python写过斐波那契数列,使用海象运算符,你甚至可以一行代码实现。
[(f:=(f[1], sum(f)) if i else (0,1))[1] for i in range(10)]
运行结果如下:

海象运算符虽然可以在很多场合使用,但官方也建议尽量将海象运算符的使用限制在清晰的场合中,以降低复杂性并提升可读性。
仅限位置形参
新增了一个函数形参语法 / 用来指明某些函数形参必须使用仅限位置而非关键字参数的形式。/ 左侧的参数必须使用位置形参。
另外, * 的右边为仅限关键字形参。
下面的例子中,形参a和b为仅限位置形参,c或d可以是位置形参或关键字形参,也就是默认形式,而e或f要求为仅限关键字形参:
def f(a, b, /, c, d, *, e, f):
print(a, b, c, d, e, f)
我们尝试用关键字方式给a和b赋值,运行结果如下:

可以看到,错误提醒很明确,我们在仅限位置参数的地方放了关键字参数。
如果你把e和f的关键字去掉,当作位置参数使用,它也会报错。
我们按照正确的要求写入参数,运行结果如下:

另外,在 / 左侧的形参不会被公开为可用关键字,其形参名仍可在**kwargs中使用。
举个例子:
def f(a, b, /, **kwargs):
print(a, b, kwargs)
然后我们给后面的参数赋值给a , b
f(10, 20, a=1, b=2, c=3)
运行结果如下:

可以看到,/ 左侧仅限位置形参的参数名并不影响后面我们后来的操作。
字典可使用 reversed 进行反转
普通字典自Python 3.7起已保证具有确定的元素顺序,在Python 3.8中可以利用reversed按插入顺序反向迭代。Python字典(Dictionary) items()函数以列表返回可遍历的(键,值)元组数组
s={'a':23,'b':24,'c':66}
list(reversed(s.items()))
运行结果如下:

f-string增加 = 说明符
在f-string的早期版本,我们要想实现 a = x 的形式,往往比较麻烦。增加 = 说明符用于 f-string。形式为 f'{expr=}' 的f字符串将扩展表示为表达式文本,加一个等于号,再加表达式的求值结果。
name = 'Galaxy'
print(f'name = {name}')
运行结果如下:

Python3.8更新了新的更加简洁的写法,也就是 = 说明符
name = 'Galaxy'
print(f'{name = }')
运行结果如下:

另外,新版本还给f-string增加了转换符!s、!a、!r
转换符'!s'是对结果调用str(),'!r'是调用repr(),而'!a'是调用ascii()。
我们来举个例子
import datetime
today = datetime.date.today()
print(f'今天是{today!s}')
运行结果如下:

repr()函数将对象转化为供解释器读取的形式。
转换符'!r'的结果如下:

ascii()函数类似repr()函数,返回一个表示对象的字符串,但是对于字符串中的非ASCII字符则返回通过repr()函数使用\x, \u或\U编码的字符。 生成字符串类似Python2版本中repr()函数的返回值。
转换符'!a'的结果如下:

可从进程直接访问的共享内存
该模块提供了一个 SharedMemory 类,用于分配和管理多核或对称多处理器(SMP)机器上进程间的共享内存。
介绍一个有趣的新功能,它可以从进程直接访问的共享内存。
我们先打开运行下面代码,获得一个name值
from multiprocessing import shared_memory
a = shared_memory.ShareableList([2021, 'abc', 2022])
a

然后打开一个新终端
from multiprocessing import shared_memory b = shared_memory.ShareableList(name=) #这里要把获得的name值写入b
运行结果如下:

以下示例展示了一个现实中的例子,使用 SharedMemory 类和 NumPy arrays 结合,从两个Python shell中访问同一个 numpy.ndarray :
>>> # In the first Python interactive shell>>> import numpy as np>>> a = np.array([1, 1, 2, 3, 5, 8]) # Start with an existing NumPy array>>> from multiprocessing import shared_memory>>> shm = shared_memory.SharedMemory(create=True, size=a.nbytes)>>> # Now create a NumPy array backed by shared memory>>> b = np.ndarray(a.shape, dtype=a.dtype, buffer=shm.buf)>>> b[:] = a[:] # Copy the original data into shared memory>>> barray([1, 1, 2, 3, 5, 8])>>> type(b)<class 'numpy.ndarray'>>>> type(a)<class 'numpy.ndarray'>>>> shm.name # We did not specify a name so one was chosen for us'psm_21467_46075'>>> # In either the same shell or a new Python shell on the same machine>>> import numpy as np>>> from multiprocessing import shared_memory>>> # Attach to the existing shared memory block>>> existing_shm = shared_memory.SharedMemory(name='psm_21467_46075')>>> # Note that a.shape is (6,) and a.dtype is np.int64 in this example>>> c = np.ndarray((6,), dtype=np.int64, buffer=existing_shm.buf)>>> carray([1, 1, 2, 3, 5, 8])>>> c[-1] = 888>>> carray([ 1, 1, 2, 3, 5, 888])>>> # Back in the first Python interactive shell, b reflects this change>>> barray([ 1, 1, 2, 3, 5, 888])>>> # Clean up from within the second Python shell>>> del c # Unnecessary; merely emphasizing the array is no longer used>>> existing_shm.close()>>> # Clean up from within the first Python shell>>> del b # Unnecessary; merely emphasizing the array is no longer used>>> shm.close()>>> shm.unlink() # Free and release the shared memory block at the very end总结
Python 3.8最让大家期待的就是海象运算符,其他方面还增加仅限位置形参、字典反转、f-string的=用法,另外,很多内置方法的性能都提高了20% - 50%,类型提示方面也有一些更新,还是很值得更新使用的。