python】【Python基础】python3.7和3.8的区别

2020-11-12 11:25发布

6条回答
小优
2楼 · 2020-11-12 12:03

Python 3.8 是Python语言的最新版本,它适合用于编写脚本、自动化以及机器学习和Web开发等各种任务。

现在Python 3.8已经进入官方的beta阶段,这个版本带来了许多语法改变、内存共享、更有效的序列化和反序列化、改进的字典和更多新功能。

Python 3.8还引入了许多性能改进。总的来说,我们即将拥有一个更快、更精确、更一致和更现代的Python。


浅浅77
3楼 · 2020-11-12 15:22

Python 3.8 是Python语言的最新版本,它适合用于编写脚本、自动化以及机器学习和Web开发等各种任务。

现在Python 3.8已经进入官方的beta阶段,这个版本带来了许多语法改变、内存共享、更有效的序列化和反序列化、改进的字典和更多新功能。

Python 3.8还引入了许多性能改进。总的来说,我们即将拥有一个更快、更精确、更一致和更现代的Python。

下面是Python 3.8的新功能和最重要的改变,我总结了一些开发中用得到的,常用的特性。

1.赋值表达式

Python 3.8最明显的变化就是赋值表达式,即:=操作符。赋值表达式可以将一个值赋给一个变量,即使变量不存在也可以。它可以用在表达式中,无需作为单独的语句出现。

2020311103117412.jpg?2020211103132

上例中,如果变量line不存在则会被创建,然后将file.readline()的返回值赋给它。然后检查line是否为"end"。如果不是,则读取下一行,保存在line中,然后继续测试。

赋值表达式遵循了Python一贯简洁的传统,就像列表解析式一样。其目的在于避免在特定的Python编程模式中出现一些枯燥的样板代码。例如,上述代码用一般写法需要多写两行代码。

2.仅通过位置指定的参数

仅通过位置指定的参数是函数定义中的一个新语法,可以让程序员强迫某个参数只能通过位置来指定。这样可以解决Python函数定义中哪个参数是位置参数、哪个参数是关键字参数的模糊性。

仅通过位置指定的参数可以用于如下情况:某个函数接受任意关键字参数,但也能接受一个或多个未知参数。Python的内置函数通常都是这种情况,所以允许程序员这样做,能增强Python语言的一致性。

Python文档中给出的例子如下:

2020311103209180.png?2020211103226

符号 / 分隔了位置参数和关键字参数。在这个例子中,所有参数都是未知参数。在以前版本的Python中,z会被认为是关键字参数。但采用上述函数定义,pow(2, 10)和pow(2, 10, 5)都是正确的调用方式,而pow(2, 10, z=5)是不正确的。

3.支持f字符串调试

f字符串格式可以更方便地在同一个表达式内进行输出文本和值或变量的计算,而且效率更高。

2020311103256833.jpg?2020211103312

输出4。

在f字符串表达式末未添加=可以输出f表达式本身的值,后面是计算后的值

2020311103335096.jpg?2020211103346

输出为x+1=4。

4.多进程共享内存

在Python 3.8中,multiprocessing模块提供了SharedMemory类,可以在不同的Python进城之间创建共享的内存区域。

在旧版本的Python中,进程间共享数据只能通过写入文件、通过网络套接字发送,或采用Python的pickle模块进行序列化等方式。共享内存提供了进程间传递数据的更快的方式,从而使得Python的多处理器和多内核编程更有效率。

共享内存片段可以作为单纯的字节区域来分配,也可以作为不可修改的类似于列表的对象来分配,其中能保存数字类型、字符串、字节对象、None对象等一小部分Python对象。

5.Typing模块的改进

Python是动态类型语言,但可以通过typing模块添加类型提示,以便第三方工具验证Python代码。Python 3.8给typing添加了一些新元素,因此它能够支持更健壮的检查:

final修饰器和Final类型标注表明,被修饰或被标注的对象在任何时候都不应该被重写、继承,也不能被重新赋值。

Literal类型将表达式限定为特定的值或值的列表(不一定是同一个类型的值)。

TypedDict可以用来创建字典,其特定键的值被限制在一个或多个类型上。注意这些限制仅用于编译时确定值的合法性,而不能在运行时进行限制。

6.新版本的pickle协议

Python的pickle模块提供了一种序列化和反序列化Python数据结构或实例的方法,可以将字典原样保存下来供以后读取。不同版本的Python支持的pickle协议不同,而最新版本的支持范围更广、更强大、更有效的序列化。

Python 3.8引入的第5版pickle协议可以用一种新方法pickle对象,它能支持Python的缓冲区协议,如bytes、memoryviews或Numpy array等。新的pickle避免了许多在pickle这些对象时的内存复制操作。

NumPy、Apache Arrow等外部库在各自的Python绑定中支持新的pickle协议。新的pickle也可以作为Python 3.6和3.7的插件使用,可以从PyPI上安装。

7.可反转字典

Python3.6中重写了字典,其使用了PyPy项目贡献的一个新实现。除了更快、更紧凑之外,现在的字典还会继承元素的顺序――元素会按照添加的顺序排列,就像列表一样。Python 3.8还允许在字典上使用reversed()。

8.性能改进

许多内置方法和函数的速度都提高了20%~50%,因为之前许多函数都需要进行不必要的参数转换。

一个新的opcode缓存可以提高解释器中特定指令的速度。但是,目前实现了速度改进的只有LOAD_GLOBAL opcode,其速度提高了40%。以后的版本中也会进行类似的优化。

文件复制操作如shutil.copyfile()和shutil.copytree()现在使用平台特定的调用和其他优化措施,来提高操作速度。

新创建的列表现在平均比以前小了12%,这要归功于列表构造函数如果能提前知道列表长度的情况下进行的优化。

Python 3.8中向新型类(如class A(object))的类变量中的写入操作变得更快。operator.itemgetter()和collections.namedtuple()也得到了速度优化。

9.Python C API和CPython实现

Python最近的版本在CPython(C语言编写的Python的参考实现)中使用的C API重构方面下了很大功夫。到目前为止这些工作还在不断添加,现有的成果包括:

Python初始化配置(Python Initialization Configuration)有了个新的C API,可以实现对Python初始化例程更紧密的控制和更详细的反馈。如此一来,将Python运行时嵌入到其他应用程序中就会更容易,也可以以编程方式给Python程序传递启动参数。新的API还确保了所有Python配置控制都有一个单一的、一致的位置,因此以后的改变(如Python的新的UTF-8模式)也更为容易。

CPython的另一个新的C API――"vectorcall"调用协议――可以实现针对Python内部方法更快的调用,而无需创建临时对象。该API依然不稳定,但已有了明显的改善。该API计划在Python 3.9中成熟。

Python运行时的审计钩子为Python运行时提供了两个API,可以用来勾住事件,从而保证测试框架、日志和审计系统等外部工具能够监视到它们。


freediandianer
4楼 · 2020-11-12 17:23

最新版本,功能方面还有语法啥的都变了一些。

无需指教
5楼 · 2020-11-13 08:37

一、Python3.6新特性

1、新的格式化字符串方式

新的格式化字符串方式,即在普通字符串前添加 f 或 F 前缀,其效果类似于str.format()。比如

name = "red"print(f"He said his name is {name}.") 
# 'He said his name is red.'

相当于:

print("He said his name is {name}.".format(**locals()))

此外,此特性还支持嵌套字段,比如:

import decimal
width = 10precision = 4value = decimal.Decimal("12.34567")
print(f"result: {value:{width}.{precision}}") 
#'result:  12.35'

2、变量声明语法

可以像下面一样声明一个变量并指定类型:

from typing import List, Dict
 
primes: List[int] = []
captain: str  # 此时没有初始值
 class Starship:
  stats: Dict[str, int] = {}

3、数字的下划线写法

允许在数字中使用下划线,以提高多位数字的可读性。

a = 1_000_000_000_000_000    # 1000000000000000b = 0x_FF_FF_FF_FF       # 4294967295

除此之外,字符串格式化也支持_选项,以打印出更易读的数字字符串:

'{:_}'.format(1000000)     # '1_000_000''{:_x}'.format(0xFFFFFFFF)   # 'ffff_ffff'

4、异步生成器

在Python3.5中,引入了新的语法 async 和 await 来实现协同程序。但是有个限制,不能在同一个函数体内同时使用 yield 和 await。Python3.6中,这个限制被放开了,允许定义异步生成器:

async def ticker(delay, to):"""Yield numbers from 0 to *to* every *delay* seconds."""
  for i in range(to):    yield i    await asyncio.sleep(delay)

5、异步解析器

允许在列表list、集合set 和字典dict 解析器中使用 async 或 await 语法。

result = [i async for i in aiter() if i % 2]
result = [await fun() for fun in funcs if await condition()]

6、新增加模块

标准库(The Standard Library)中增加了一个新的模块:secrets。该模块用来生成一些安全性更高的随机数,用于管理passwords, account authentication, security tokens, 以及related secrets等数据。

7、其他新特性

  • 新的 PYTHONMALLOC 环境变量允许开发者设置内存分配器,以及注册debug钩子等。

  • asyncio模块更加稳定、高效,并且不再是临时模块,其中的API也都是稳定版的了。

  • typing模块也有了一定改进,并且不再是临时模块。

  • datetime.strftime 和 date.strftime 开始支持ISO 8601的时间标识符%G, %u, %V。

  • hashlib 和 ssl 模块开始支持OpenSSL1.1.0。

  • hashlib模块开始支持新的hash算法,比如BLAKE2, SHA-3 和 SHAKE。

  • Windows上的 filesystem 和 console 默认编码改为UTF-8。

  • json模块中的 json.load() 和 json.loads() 函数开始支持 binary 类型输入。

更多内容参考官方文档:What's New In Python 3.6

二、Python3.7新特性

Python 3.7于2018年6月27日发布, 包含许多新特性和优化,增添了众多新的类,可用于数据处理、针对脚本编译和垃圾收集的优化以及更快的异步I/O,主要如下:

  • 用类处理数据时减少样板代码的数据类。

  • 一处可能无法向后兼容的变更涉及处理生成器中的异常。

  • 面向解释器的“开发模式”。

  • 具有纳秒分辨率的时间对象。

  • 环境中默认使用UTF-8编码的UTF-8模式。

  • 触发调试器的一个新的内置函数。

1、新增内置函数breakpoint()

使用该内置函数,相当于通过代码的方式设置了断点,会自动进入Pbd调试模式。

如果在环境变量中设置PYTHONBREAKPOINT=0会忽略此函数。并且,pdb 只是众多可用调试器之一,你可以通过设置新的 PYTHONBREAKPOINT 环境变量来配置想要使用的调试器。

下面有一个简单例子,用户需要输入一个数字,判断它是否和目标数字一样:

"""猜数字游戏"""def guess(target):
    user_guess = input("请输入你猜的数 >>> ")    if user_guess == target:        return "你猜对了!"
    else:        return "猜错了"if __name__ == '__main__':
    a = 100
    print(guess(a))

不幸的是,即使猜的数和目标数一样,打印的结果也是‘猜错了’,并且没有任何异常或错误信息。

为了弄清楚发生了什么,我们可以插入一个断点,来调试一下。以往一般通过print大法或者IDE的调试工具,但现在我们可以使用 breakpoint()

"""猜数字游戏"""def guess(target):
    user_guess = input("请输入你猜的数 >>> ")    breakpoint()   //加入这一行    if user_guess == target:        return "你猜对了!"
    else:        return "猜错了"if __name__ == '__main__':
    a = 100
    print(guess(a))

在 pdb 提示符下,我们可以调用 locals() 来查看当前的本地作用域的所有变量。(pdb 有大量的命令,你也可以在其中运行正常的Python 语句)

请输入你猜的数 >>> 100
> d:\work\for_test\py3_test\test.py(7)guess()
-> if user_guess == target:
(Pdb) locals()
{'target': 100, 'user_guess': '100'}
(Pdb) type(user_guess)

搞明白了,target是一个整数,而user_guess 是一个字符串,这里发生了类型对比错误。

2、类型和注解

从 Python 3.5 开始,类型注解就越来越受欢迎。对于那些不熟悉类型提示的人来说,这是一种完全可选的注释代码的方式,以指定变量的类型。

什么是注解?它们是关联元数据与变量的语法支持,可以是任意表达式,在运行时被 Python 计算但被忽略。注解可以是任何有效的 Python 表达式。

下面是个对比的例子:

# 不带类型注解def foo(bar, baz):# 带类型注解def foo(bar: 'Describe the bar', baz: print('random')) -> 'return thingy':

上面的做法,其实是Python对自身弱类型语言的强化,希望获得一定的类型可靠和健壮度,向Java等语言靠拢。

在 Python 3.5 中,注解的语法获得标准化,此后,Python 社区广泛使用了注解类型提示。

但是,注解仅仅是一种开发工具,可以使用 PyCharm 等 IDE 或 Mypy 等第三方工具进行检查,并不是语法层面的限制。

我们前面的猜数程序如果添加类型注解,它应该是这样的:

"""猜数字游戏"""def guess(target:str):
    user_guess:str = input("请输入你猜的数 >>> ")    breakpoint()    if user_guess == target:        return "你猜对了!"
    else:        return "猜错了"if __name__ == '__main__':
    a:int = 100
    print(guess(a))

PyCharm会给我们灰色的规范错误提醒,但不会给红色的语法错误提示。

用注解作为类型提示时,有两个主要问题:启动性能和前向引用

  • 在定义时计算大量任意表达式相当影响启动性能,而且 typing 模块非常慢

  • 你不能用尚未声明的类型来注解

typing 模块如此缓慢的部分原因是,最初的设计目标是在不修改核心 CPython 解释器的情况下实现 typing 模块。随着类型提示变得越来越流行,这一限制已经被移除,这意味着现在有了对 typing 的核心支持。

而对于向前引用,看下面的例子:

class User:
    def __init__(self, name: str, prev_user: User) -> None:
        pass

错误在于 User类型还没有被声明,此时的 prev_user 不能定义为 User 类型。

为了解决这个问题,Python3.7 将注解的评估进行了推迟。并且,这项改动向后不兼容,需要先导入annotations,只有到Python 4.0后才会成为默认行为。

from __future__ import annotationsclass User: 
    def __init__(self, name: str, prev_user: User) -> None:
        pass

或者如下面的例子:

class C:
    def validate_b(self, obj: B) -> bool:
        ...class B:
    ...

3、新增dataclasses模块

这个特性可能是 Python3.7以后比较常用的,它有什么作用呢?

假如我们需要编写一个下面的类:

from datetime import datetimeimport dateutilclass Article(object):
    def __init__(self, _id, author_id, title, text, tags=None, 
                 created=datetime.now(), edited=datetime.now()):
    self._id = _id
    self.author_id = author_id
    self.title = title
    self.text = text
    self.tags = list() if tags is None else tags
    self.created = created
    self.edited = edited    if type(self.created) is str:
       self.created = dateutil.parser.parse(self.created)    if type(self.edited) is str:
       self.edited = dateutil.parser.parse(self.edited)    def __eq__(self, other):
        if not isinstance(other, self.__class__):            return NotImplemented
        return (self._id, self.author_id) == (other._id, other.author_id)    def __lt__(self, other):
        if not isinstance(other, self.__class__):            return NotImplemented
        return (self._id, self.author_id) < (other._id, other.author_id)    def __repr__(self):
        return '{}(id={}, author_id={}, title={})'.format(
                self.__class__.__name__, self._id, self.author_id, self.title)

大量的初始化属性要定义默认值,可能还需要重写一堆魔法方法,来实现类实例的打印、比较、排序和去重等功能。

如果使用dataclasses进行改造,可以写成这个样子:

from dataclasses import dataclass, fieldfrom typing import Listfrom datetime import datetimeimport dateutil@dataclass(order=True)   //注意这里class Article(object):
    _id: int
    author_id: int
    title: str = field(compare=False)
    text: str = field(repr=False, compare=False)
    tags: List[str] = field(default=list(), repr=False, compare=False)
    created: datetime = field(default=datetime.now(), repr=False, compare=False)
    edited: datetime = field(default=datetime.now(), repr=False, compare=False)    def __post_init__(self):
       if type(self.created) is str:
           self.created = dateutil.parser.parse(self.created)       if type(self.edited) is str:
           self.edited = dateutil.parser.parse(self.edited)

这使得类不仅容易设置,而且当我们创建一个实例并打印出来时,它还可以自动生成优美的字符串。在与其他类实例进行比较时,它也会有适当的行为。这是因为dataclasses除了帮我们自动生成 __init__ 方法外,还生成了一些其他特殊方法,如 repreq 和 hash 等。

Dataclasses 使用字段 field来完提供默认值,手动构造一个 field() 函数能够访问其他选项,从而更改默认值。例如,这里将 field 中的 default_factory 设置为一个 lambda 函数,该函数提示用户输入其名称。

from dataclasses import dataclass, fieldclass User:
    name: str = field(default_factory=lambda: input("enter name"))

4、生成器异常处理

在Python 3.7中,生成器引发StopIteration异常后,StopIteration异常将被转换成RuntimeError异常,那样它不会悄悄一路影响应用程序的堆栈框架。这意味着如何处理生成器的行为方面不太敏锐的一些程序会在Python 3.7中抛出RuntimeError。在Python 3.6中,这种行为生成一个弃用警告;在Python 3.7中,它将生成一个完整的错误。

一个简易的方法是使用try/except代码段,在StopIteration传播到生成器的外面捕获它。更好的解决方案是重新考虑如何构建生成器――比如说,使用return语句来终止生成器,而不是手动引发StopIteration。

5、开发模式

Python解释器添加了一个新的命令行开关:-X,让开发人员可以为解释器设置许多低级选项。

这种运行时的检查机制通常对性能有重大影响,但在调试过程中对开发人员很有用。

-X 激活的选项包括:

  • asyncio模块的调试模式。这为异步操作提供了更详细的日志记录和异常处理,而异常操作可能很难调试或推理。

  • 面向内存分配器的调试钩子。这对于编写CPython扩展件的那些人很有用。它能够实现更明确的运行时检查,了解CPython如何在内部分配内存和释放内存。

  • 启用faulthandler模块,那样发生崩溃后,traceback始终转储出去。

6、 高精度时间函数

Python 3.7中一类新的时间函数返回纳秒精度的时间值。尽管Python是一种解释型语言,但是Python的核心开发人员维克多•斯廷纳(Victor Stinner)主张报告纳秒精度的时间。最主要的原因是,在处理转换其他程序(比如数据库)记录的时间值时,可以避免丢失精度。

新的时间函数使用后缀_ns比如说,time.process_time()的纳秒版本是time.process_time_ns()。请注意,并非所有的时间函数都有对应的纳秒版本。

7、其他新特性

  • 字典现在保持插入顺序。这在 3.6 中是非正式的,但现在成为了官方语言规范。在大多数情况下,普通的 dict 能够替换 collections.OrderedDict

  • .pyc 文件具有确定性,支持可重复构建 —— 也就是说,总是为相同的输入文件生成相同的 byte-for-byte 输出。

  • 新增contextvars模块,针对异步任务提供上下文变量。

  • __main__中的代码会显示弃用警告(DeprecationWarning)。

  • 新增UTF-8模式。在Linux/Unix系统,将忽略系统的locale,使用UTF-8作为默认编码。在非Linux/Unix系统,需要使用-X utf8选项启用UTF-8模式。

  • 允许模块定义__getattr__、__dir__函数,为弃用警告、延迟import子模块等提供便利。

  • 新的线程本地存储C语言API。

  • 更新Unicode数据到11.0。

三、Python3.8新特性

Python3.8版本于2019年10月14日发布,以下是 Python 3.8 相比 3.7 的新增特性。

1、海象赋值表达式

新的语法 :=,将值赋给一个更大的表达式中的变量。它被亲切地称为 “海象运算符”(walrus operator),因为它长得像海象的眼睛和象牙。

“海象运算符” 在某些时候可以让你的代码更整洁,比如:

在下面的示例中,赋值表达式可以避免调用 len () 两次:

if (n := len(a)) > 10: 
    print(f"List is too long ({n} elements, expected <= 10)")

类似的好处还可体现在正则表达式匹配中需要使用两次匹配对象的情况中,一次检测用于匹配是否发生,另一次用于提取子分组:

discount = 0.0 if (mo := re.search(r'(\d+)% discount', advertisement)): 
    discount = float(mo.group(1)) / 100.0

此运算符也可用于配合 while 循环计算一个值,来检测循环是否终止,而同一个值又在循环体中再次被使用的情况:

# Loop over fixed length blocks while (block := f.read(256)) != '': 
    process(block)

或者出现于列表推导式中,在筛选条件中计算一个值,而同一个值又在表达式中需要被使用:

[clean_name.title() for name in names 

 if (clean_name := normalize('NFC', name)) in allowed_names]

请尽量将海象运算符的使用限制在清晰的场合中,以降低复杂性并提升可读性。

2、仅限位置形参

新增一个函数形参语法 / 用来指明某些函数形参必须使用仅限位置而非关键字参数的形式。

这种标记语法与通过 help () 所显示的使用 Larry Hastings 的 Argument Clinic 工具标记的 C 函数相同。

在下面的例子中,形参 a 和 b 为仅限位置形参,c 或 d 可以是位置形参或关键字形参,而 e 或 f 要求为关键字形参:

def f(a, b, /, c, d, *, e, f): 

    print(a, b, c, d, e, f)

以下是合法的调用:

f(10, 20, 30, d=40, e=50, f=60)

但是,以下均为不合法的调用:

f(10, b=20, c=30, d=40, e=50, f=60)   # b 不可以是一个关键字参数f(10, 20, 30, 40, 50, f=60)           # e 必须是一个关键字参数

这种标记形式的一个用例是它允许纯 Python 函数完整模拟现有的用 C 代码编写的函数的行为。例如,内置的 pow () 函数不接受关键字参数:

def pow(x, y, z=None, /): 

    "Emulate the built in pow() function" 

    r = x ** y 

    return r if z is None else r%z

另一个用例是在不需要形参名称时排除关键字参数。例如,内置的 len () 函数的签名为 len (obj, /)。这可以排除如下这种笨拙的调用形式:

len(obj='hello')  # The "obj" keyword argument impairs readability

另一个益处是将形参标记为仅限位置形参将允许在未来修改形参名而不会破坏客户的代码。例如,在 statistics 模块中,形参名 dist 在未来可能被修改。这使得以下函数描述成为可能:

def quantiles(dist, /, *, n=4, method='exclusive') 
    ...

由于在 / 左侧的形参不会被公开为可用关键字,其他形参名仍可在 **kwargs 中使用:

>>> def f(a, b, /, **kwargs): ...     print(a, b, kwargs) 
... 
>>> f(10, 20, a=1, b=2, c=3)         # a and b are used in two ways 10 20 {'a': 1, 'b': 2, 'c': 3}

这极大地简化了需要接受任意关键字参数的函数和方法的实现。例如,下面是 collections 模块中的代码摘录:

class Counter(dict): 

    def __init__(self, iterable=None, /, **kwds): 

        # Note "iterable" is a possible keyword argument

3、f 字符串支持 =

增加 = 说明符用于 f-string。形式为 f'{expr=}' 的 f 字符串将扩展表示为表达式文本,加一个等于号,再加表达式的求值结果。例如:

>>> user = 'eric_idle' >>> member_since = date(1975, 7, 31) 
>>> f'{user=} {member_since=}' "user='eric_idle' member_since=datetime.date(1975, 7, 31)"

f 字符串格式说明符允许更细致地控制所要显示的表达式结果:

>>> delta = date.today() - member_since 

>>> f'{user=!s}  {delta.days=:,d}' 'user=eric_idle  delta.days=16,075'

= 说明符将输出整个表达式,以便详细演示计算过程:

>>> print(f'{theta=}  {cos(radians(theta))=:.3f}') 
theta=30  cos(radians(theta))=0.866

4、 typing模块的改进

Python是动态类型语言,但可以通过typing模块添加类型提示,以便第三方工具验证Python代码。Python 3.8给typing添加了一些新元素,因此它能够支持更健壮的检查:

  • final修饰器和Final类型标注表明,被修饰或被标注的对象在任何时候都不应该被重写、继承,也不能被重新赋值。

  • Literal类型将表达式限定为特定的值或值的列表(不一定是同一个类型的值)。

  • TypedDict可以用来创建字典,其特定键的值被限制在一个或多个类型上。注意这些限制仅用于编译时确定值的合法性,而不能在运行时进行限制。

5、多进程共享内存

multiprocessing模块新增SharedMemory类,可以在不同的Python进城之间创建共享的内存区域。

在旧版本的Python中,进程间共享数据只能通过写入文件、通过网络套接字发送,或采用Python的pickle模块进行序列化等方式。共享内存提供了进程间传递数据的更快的方式,从而使得Python的多处理器和多内核编程更有效率。

共享内存片段可以作为单纯的字节区域来分配,也可以作为不可修改的类似于列表的对象来分配,其中能保存数字类型、字符串、字节对象、None对象等一小部分Python对象。

6、 新版本的pickle协议

Python的pickle模块提供了一种序列化和反序列化Python数据结构或实例的方法,可以将字典原样保存下来供以后读取。不同版本的Python支持的pickle协议不同,而3.8版本的支持范围更广、更强大、更有效的序列化。

Python 3.8引入的第5版pickle协议可以用一种新方法pickle对象,它能支持Python的缓冲区协议,如bytes、memoryviews或Numpy array等。新的pickle避免了许多在pickle这些对象时的内存复制操作。

NumPy、Apache Arrow等外部库在各自的Python绑定中支持新的pickle协议。新的pickle也可以作为Python 3.6和3.7的插件使用,可以从PyPI上安装。

7、性能改进

  • 许多内置方法和函数的速度都提高了20%~50%,因为之前许多函数都需要进行不必要的参数转换。

  • 一个新的opcode缓存可以提高解释器中特定指令的速度。但是,目前实现了速度改进的只有LOAD_GLOBAL opcode,其速度提高了40%。以后的版本中也会进行类似的优化。

  • 文件复制操作如shutil.copyfile()shutil.copytree()现在使用平台特定的调用和其他优化措施,来提高操作速度。

  • 新创建的列表现在平均比以前小了12%,这要归功于列表构造函数如果能提前知道列表长度的情况下,可以进行优化。

  • Python 3.8中向新型类(如class A(object))的类变量中的写入操作变得更快。operator.itemgetter()和collections.namedtuple()也得到了速度优化。


小杨小杨
6楼 · 2020-11-13 11:56

变化还挺多的,应用范围更广了

我是大脸猫
7楼 · 2020-11-13 14:00

一、Python3.6新特性

1、新的格式化字符串方式

新的格式化字符串方式,即在普通字符串前添加 f 或 F 前缀,其效果类似于str.format()。比如

name = "red"print(f"He said his name is {name}.") 
# 'He said his name is red.'

相当于:

print("He said his name is {name}.".format(**locals()))

此外,此特性还支持嵌套字段,比如:

import decimal
width = 10precision = 4value = decimal.Decimal("12.34567")
print(f"result: {value:{width}.{precision}}") 
#'result:  12.35'

2、变量声明语法

可以像下面一样声明一个变量并指定类型:

from typing import List, Dict
 
primes: List[int] = []
captain: str  # 此时没有初始值
 class Starship:
  stats: Dict[str, int] = {}

3、数字的下划线写法

允许在数字中使用下划线,以提高多位数字的可读性。

a = 1_000_000_000_000_000    # 1000000000000000b = 0x_FF_FF_FF_FF       # 4294967295

除此之外,字符串格式化也支持_选项,以打印出更易读的数字字符串:

'{:_}'.format(1000000)     # '1_000_000''{:_x}'.format(0xFFFFFFFF)   # 'ffff_ffff'

4、异步生成器

在Python3.5中,引入了新的语法 async 和 await 来实现协同程序。但是有个限制,不能在同一个函数体内同时使用 yield 和 await。Python3.6中,这个限制被放开了,允许定义异步生成器:

async def ticker(delay, to):"""Yield numbers from 0 to *to* every *delay* seconds."""
  for i in range(to):    yield i    await asyncio.sleep(delay)

5、异步解析器

允许在列表list、集合set 和字典dict 解析器中使用 async 或 await 语法。

result = [i async for i in aiter() if i % 2]
result = [await fun() for fun in funcs if await condition()]

6、新增加模块

标准库(The Standard Library)中增加了一个新的模块:secrets。该模块用来生成一些安全性更高的随机数,用于管理passwords, account authentication, security tokens, 以及related secrets等数据。

7、其他新特性

  • 新的 PYTHONMALLOC 环境变量允许开发者设置内存分配器,以及注册debug钩子等。

  • asyncio模块更加稳定、高效,并且不再是临时模块,其中的API也都是稳定版的了。

  • typing模块也有了一定改进,并且不再是临时模块。

  • datetime.strftime 和 date.strftime 开始支持ISO 8601的时间标识符%G, %u, %V。

  • hashlib 和 ssl 模块开始支持OpenSSL1.1.0。

  • hashlib模块开始支持新的hash算法,比如BLAKE2, SHA-3 和 SHAKE。

  • Windows上的 filesystem 和 console 默认编码改为UTF-8。

  • json模块中的 json.load() 和 json.loads() 函数开始支持 binary 类型输入。

更多内容参考官方文档:What's New In Python 3.6

二、Python3.7新特性

Python 3.7于2018年6月27日发布, 包含许多新特性和优化,增添了众多新的类,可用于数据处理、针对脚本编译和垃圾收集的优化以及更快的异步I/O,主要如下:

  • 用类处理数据时减少样板代码的数据类。

  • 一处可能无法向后兼容的变更涉及处理生成器中的异常。

  • 面向解释器的“开发模式”。

  • 具有纳秒分辨率的时间对象。

  • 环境中默认使用UTF-8编码的UTF-8模式。

  • 触发调试器的一个新的内置函数。

1、新增内置函数breakpoint()

使用该内置函数,相当于通过代码的方式设置了断点,会自动进入Pbd调试模式。

如果在环境变量中设置PYTHONBREAKPOINT=0会忽略此函数。并且,pdb 只是众多可用调试器之一,你可以通过设置新的 PYTHONBREAKPOINT 环境变量来配置想要使用的调试器。

下面有一个简单例子,用户需要输入一个数字,判断它是否和目标数字一样:

"""猜数字游戏"""def guess(target):
    user_guess = input("请输入你猜的数 >>> ")    if user_guess == target:        return "你猜对了!"
    else:        return "猜错了"if __name__ == '__main__':
    a = 100
    print(guess(a))

不幸的是,即使猜的数和目标数一样,打印的结果也是‘猜错了’,并且没有任何异常或错误信息。

为了弄清楚发生了什么,我们可以插入一个断点,来调试一下。以往一般通过print大法或者IDE的调试工具,但现在我们可以使用 breakpoint()

"""猜数字游戏"""def guess(target):
    user_guess = input("请输入你猜的数 >>> ")    breakpoint()   //加入这一行    if user_guess == target:        return "你猜对了!"
    else:        return "猜错了"if __name__ == '__main__':
    a = 100
    print(guess(a))

在 pdb 提示符下,我们可以调用 locals() 来查看当前的本地作用域的所有变量。(pdb 有大量的命令,你也可以在其中运行正常的Python 语句)

请输入你猜的数 >>> 100
> d:\work\for_test\py3_test\test.py(7)guess()
-> if user_guess == target:
(Pdb) locals()
{'target': 100, 'user_guess': '100'}
(Pdb) type(user_guess)

搞明白了,target是一个整数,而user_guess 是一个字符串,这里发生了类型对比错误。

2、类型和注解

从 Python 3.5 开始,类型注解就越来越受欢迎。对于那些不熟悉类型提示的人来说,这是一种完全可选的注释代码的方式,以指定变量的类型。

什么是注解?它们是关联元数据与变量的语法支持,可以是任意表达式,在运行时被 Python 计算但被忽略。注解可以是任何有效的 Python 表达式。

下面是个对比的例子:

# 不带类型注解def foo(bar, baz):# 带类型注解def foo(bar: 'Describe the bar', baz: print('random')) -> 'return thingy':

上面的做法,其实是Python对自身弱类型语言的强化,希望获得一定的类型可靠和健壮度,向Java等语言靠拢。

在 Python 3.5 中,注解的语法获得标准化,此后,Python 社区广泛使用了注解类型提示。

但是,注解仅仅是一种开发工具,可以使用 PyCharm 等 IDE 或 Mypy 等第三方工具进行检查,并不是语法层面的限制。

我们前面的猜数程序如果添加类型注解,它应该是这样的:

"""猜数字游戏"""def guess(target:str):
    user_guess:str = input("请输入你猜的数 >>> ")    breakpoint()    if user_guess == target:        return "你猜对了!"
    else:        return "猜错了"if __name__ == '__main__':
    a:int = 100
    print(guess(a))

PyCharm会给我们灰色的规范错误提醒,但不会给红色的语法错误提示。

用注解作为类型提示时,有两个主要问题:启动性能和前向引用

  • 在定义时计算大量任意表达式相当影响启动性能,而且 typing 模块非常慢

  • 你不能用尚未声明的类型来注解

typing 模块如此缓慢的部分原因是,最初的设计目标是在不修改核心 CPython 解释器的情况下实现 typing 模块。随着类型提示变得越来越流行,这一限制已经被移除,这意味着现在有了对 typing 的核心支持。

而对于向前引用,看下面的例子:

class User:
    def __init__(self, name: str, prev_user: User) -> None:
        pass

错误在于 User类型还没有被声明,此时的 prev_user 不能定义为 User 类型。

为了解决这个问题,Python3.7 将注解的评估进行了推迟。并且,这项改动向后不兼容,需要先导入annotations,只有到Python 4.0后才会成为默认行为。

from __future__ import annotationsclass User: 
    def __init__(self, name: str, prev_user: User) -> None:
        pass

或者如下面的例子:

class C:
    def validate_b(self, obj: B) -> bool:
        ...class B:
    ...

3、新增dataclasses模块

这个特性可能是 Python3.7以后比较常用的,它有什么作用呢?

假如我们需要编写一个下面的类:

from datetime import datetimeimport dateutilclass Article(object):
    def __init__(self, _id, author_id, title, text, tags=None, 
                 created=datetime.now(), edited=datetime.now()):
    self._id = _id
    self.author_id = author_id
    self.title = title
    self.text = text
    self.tags = list() if tags is None else tags
    self.created = created
    self.edited = edited    if type(self.created) is str:
       self.created = dateutil.parser.parse(self.created)    if type(self.edited) is str:
       self.edited = dateutil.parser.parse(self.edited)    def __eq__(self, other):
        if not isinstance(other, self.__class__):            return NotImplemented
        return (self._id, self.author_id) == (other._id, other.author_id)    def __lt__(self, other):
        if not isinstance(other, self.__class__):            return NotImplemented
        return (self._id, self.author_id) < (other._id, other.author_id)    def __repr__(self):
        return '{}(id={}, author_id={}, title={})'.format(
                self.__class__.__name__, self._id, self.author_id, self.title)

大量的初始化属性要定义默认值,可能还需要重写一堆魔法方法,来实现类实例的打印、比较、排序和去重等功能。

如果使用dataclasses进行改造,可以写成这个样子:

from dataclasses import dataclass, fieldfrom typing import Listfrom datetime import datetimeimport dateutil@dataclass(order=True)   //注意这里class Article(object):
    _id: int
    author_id: int
    title: str = field(compare=False)
    text: str = field(repr=False, compare=False)
    tags: List[str] = field(default=list(), repr=False, compare=False)
    created: datetime = field(default=datetime.now(), repr=False, compare=False)
    edited: datetime = field(default=datetime.now(), repr=False, compare=False)    def __post_init__(self):
       if type(self.created) is str:
           self.created = dateutil.parser.parse(self.created)       if type(self.edited) is str:
           self.edited = dateutil.parser.parse(self.edited)

这使得类不仅容易设置,而且当我们创建一个实例并打印出来时,它还可以自动生成优美的字符串。在与其他类实例进行比较时,它也会有适当的行为。这是因为dataclasses除了帮我们自动生成 __init__ 方法外,还生成了一些其他特殊方法,如 repreq 和 hash 等。

Dataclasses 使用字段 field来完提供默认值,手动构造一个 field() 函数能够访问其他选项,从而更改默认值。例如,这里将 field 中的 default_factory 设置为一个 lambda 函数,该函数提示用户输入其名称。

from dataclasses import dataclass, fieldclass User:
    name: str = field(default_factory=lambda: input("enter name"))

4、生成器异常处理

在Python 3.7中,生成器引发StopIteration异常后,StopIteration异常将被转换成RuntimeError异常,那样它不会悄悄一路影响应用程序的堆栈框架。这意味着如何处理生成器的行为方面不太敏锐的一些程序会在Python 3.7中抛出RuntimeError。在Python 3.6中,这种行为生成一个弃用警告;在Python 3.7中,它将生成一个完整的错误。

一个简易的方法是使用try/except代码段,在StopIteration传播到生成器的外面捕获它。更好的解决方案是重新考虑如何构建生成器――比如说,使用return语句来终止生成器,而不是手动引发StopIteration。

5、开发模式

Python解释器添加了一个新的命令行开关:-X,让开发人员可以为解释器设置许多低级选项。

这种运行时的检查机制通常对性能有重大影响,但在调试过程中对开发人员很有用。

-X 激活的选项包括:

  • asyncio模块的调试模式。这为异步操作提供了更详细的日志记录和异常处理,而异常操作可能很难调试或推理。

  • 面向内存分配器的调试钩子。这对于编写CPython扩展件的那些人很有用。它能够实现更明确的运行时检查,了解CPython如何在内部分配内存和释放内存。

  • 启用faulthandler模块,那样发生崩溃后,traceback始终转储出去。

6、 高精度时间函数

Python 3.7中一类新的时间函数返回纳秒精度的时间值。尽管Python是一种解释型语言,但是Python的核心开发人员维克多•斯廷纳(Victor Stinner)主张报告纳秒精度的时间。最主要的原因是,在处理转换其他程序(比如数据库)记录的时间值时,可以避免丢失精度。

新的时间函数使用后缀_ns比如说,time.process_time()的纳秒版本是time.process_time_ns()。请注意,并非所有的时间函数都有对应的纳秒版本。

7、其他新特性

  • 字典现在保持插入顺序。这在 3.6 中是非正式的,但现在成为了官方语言规范。在大多数情况下,普通的 dict 能够替换 collections.OrderedDict

  • .pyc 文件具有确定性,支持可重复构建 —— 也就是说,总是为相同的输入文件生成相同的 byte-for-byte 输出。

  • 新增contextvars模块,针对异步任务提供上下文变量。

  • __main__中的代码会显示弃用警告(DeprecationWarning)。

  • 新增UTF-8模式。在Linux/Unix系统,将忽略系统的locale,使用UTF-8作为默认编码。在非Linux/Unix系统,需要使用-X utf8选项启用UTF-8模式。

  • 允许模块定义__getattr__、__dir__函数,为弃用警告、延迟import子模块等提供便利。

  • 新的线程本地存储C语言API。

  • 更新Unicode数据到11.0。

三、Python3.8新特性

Python3.8版本于2019年10月14日发布,以下是 Python 3.8 相比 3.7 的新增特性。

1、海象赋值表达式

新的语法 :=,将值赋给一个更大的表达式中的变量。它被亲切地称为 “海象运算符”(walrus operator),因为它长得像海象的眼睛和象牙。

“海象运算符” 在某些时候可以让你的代码更整洁,比如:

在下面的示例中,赋值表达式可以避免调用 len () 两次:

if (n := len(a)) > 10: 
    print(f"List is too long ({n} elements, expected <= 10)")

类似的好处还可体现在正则表达式匹配中需要使用两次匹配对象的情况中,一次检测用于匹配是否发生,另一次用于提取子分组:

discount = 0.0 if (mo := re.search(r'(\d+)% discount', advertisement)): 
    discount = float(mo.group(1)) / 100.0

此运算符也可用于配合 while 循环计算一个值,来检测循环是否终止,而同一个值又在循环体中再次被使用的情况:

# Loop over fixed length blocks while (block := f.read(256)) != '': 
    process(block)

或者出现于列表推导式中,在筛选条件中计算一个值,而同一个值又在表达式中需要被使用:

[clean_name.title() for name in names 

 if (clean_name := normalize('NFC', name)) in allowed_names]

请尽量将海象运算符的使用限制在清晰的场合中,以降低复杂性并提升可读性。

2、仅限位置形参

新增一个函数形参语法 / 用来指明某些函数形参必须使用仅限位置而非关键字参数的形式。

这种标记语法与通过 help () 所显示的使用 Larry Hastings 的 Argument Clinic 工具标记的 C 函数相同。

在下面的例子中,形参 a 和 b 为仅限位置形参,c 或 d 可以是位置形参或关键字形参,而 e 或 f 要求为关键字形参:

def f(a, b, /, c, d, *, e, f): 

    print(a, b, c, d, e, f)

以下是合法的调用:

f(10, 20, 30, d=40, e=50, f=60)

但是,以下均为不合法的调用:

f(10, b=20, c=30, d=40, e=50, f=60)   # b 不可以是一个关键字参数f(10, 20, 30, 40, 50, f=60)           # e 必须是一个关键字参数

这种标记形式的一个用例是它允许纯 Python 函数完整模拟现有的用 C 代码编写的函数的行为。例如,内置的 pow () 函数不接受关键字参数:

def pow(x, y, z=None, /): 

    "Emulate the built in pow() function" 

    r = x ** y 

    return r if z is None else r%z

另一个用例是在不需要形参名称时排除关键字参数。例如,内置的 len () 函数的签名为 len (obj, /)。这可以排除如下这种笨拙的调用形式:

len(obj='hello')  # The "obj" keyword argument impairs readability

另一个益处是将形参标记为仅限位置形参将允许在未来修改形参名而不会破坏客户的代码。例如,在 statistics 模块中,形参名 dist 在未来可能被修改。这使得以下函数描述成为可能:

def quantiles(dist, /, *, n=4, method='exclusive') 
    ...

由于在 / 左侧的形参不会被公开为可用关键字,其他形参名仍可在 **kwargs 中使用:

>>> def f(a, b, /, **kwargs): ...     print(a, b, kwargs) 
... 
>>> f(10, 20, a=1, b=2, c=3)         # a and b are used in two ways 10 20 {'a': 1, 'b': 2, 'c': 3}

这极大地简化了需要接受任意关键字参数的函数和方法的实现。例如,下面是 collections 模块中的代码摘录:

class Counter(dict): 

    def __init__(self, iterable=None, /, **kwds): 

        # Note "iterable" is a possible keyword argument

3、f 字符串支持 =

增加 = 说明符用于 f-string。形式为 f'{expr=}' 的 f 字符串将扩展表示为表达式文本,加一个等于号,再加表达式的求值结果。例如:

>>> user = 'eric_idle' >>> member_since = date(1975, 7, 31) 
>>> f'{user=} {member_since=}' "user='eric_idle' member_since=datetime.date(1975, 7, 31)"

f 字符串格式说明符允许更细致地控制所要显示的表达式结果:

>>> delta = date.today() - member_since 

>>> f'{user=!s}  {delta.days=:,d}' 'user=eric_idle  delta.days=16,075'

= 说明符将输出整个表达式,以便详细演示计算过程:

>>> print(f'{theta=}  {cos(radians(theta))=:.3f}') 
theta=30  cos(radians(theta))=0.866

4、 typing模块的改进

Python是动态类型语言,但可以通过typing模块添加类型提示,以便第三方工具验证Python代码。Python 3.8给typing添加了一些新元素,因此它能够支持更健壮的检查:

  • final修饰器和Final类型标注表明,被修饰或被标注的对象在任何时候都不应该被重写、继承,也不能被重新赋值。

  • Literal类型将表达式限定为特定的值或值的列表(不一定是同一个类型的值)。

  • TypedDict可以用来创建字典,其特定键的值被限制在一个或多个类型上。注意这些限制仅用于编译时确定值的合法性,而不能在运行时进行限制。

5、多进程共享内存

multiprocessing模块新增SharedMemory类,可以在不同的Python进城之间创建共享的内存区域。

在旧版本的Python中,进程间共享数据只能通过写入文件、通过网络套接字发送,或采用Python的pickle模块进行序列化等方式。共享内存提供了进程间传递数据的更快的方式,从而使得Python的多处理器和多内核编程更有效率。

共享内存片段可以作为单纯的字节区域来分配,也可以作为不可修改的类似于列表的对象来分配,其中能保存数字类型、字符串、字节对象、None对象等一小部分Python对象。

6、 新版本的pickle协议

Python的pickle模块提供了一种序列化和反序列化Python数据结构或实例的方法,可以将字典原样保存下来供以后读取。不同版本的Python支持的pickle协议不同,而3.8版本的支持范围更广、更强大、更有效的序列化。

Python 3.8引入的第5版pickle协议可以用一种新方法pickle对象,它能支持Python的缓冲区协议,如bytes、memoryviews或Numpy array等。新的pickle避免了许多在pickle这些对象时的内存复制操作。

NumPy、Apache Arrow等外部库在各自的Python绑定中支持新的pickle协议。新的pickle也可以作为Python 3.6和3.7的插件使用,可以从PyPI上安装。

7、性能改进

  • 许多内置方法和函数的速度都提高了20%~50%,因为之前许多函数都需要进行不必要的参数转换。

  • 一个新的opcode缓存可以提高解释器中特定指令的速度。但是,目前实现了速度改进的只有LOAD_GLOBAL opcode,其速度提高了40%。以后的版本中也会进行类似的优化。

  • 文件复制操作如shutil.copyfile()shutil.copytree()现在使用平台特定的调用和其他优化措施,来提高操作速度。

  • 新创建的列表现在平均比以前小了12%,这要归功于列表构造函数如果能提前知道列表长度的情况下,可以进行优化。

  • Python 3.8中向新型类(如class A(object))的类变量中的写入操作变得更快。operator.itemgetter()和collections.namedtuple()也得到了速度优化。

更多详细特性,请查阅Python 3.8.0文档:https://docs.python.org/zh-cn/3.8/whatsnew/3.8.html


相关问题推荐

  • 回答 1

    可以试下在cmd命令行执行,编辑器中对turtle的支持度不是很好。

  • 回答 6

    人工智能是一门起步晚却发展快速的科学。20 世纪以来科学工作者们不断寻求着赋予机器人类智慧的方法。现代人工智能这一概念是从英国科学家图灵的寻求智能机发展而来,直到1937年图灵发表的论文《理想自动机》给人工智能下了严格的数学定义,现实世界中实际要...

  • 回答 7

    代理ip网址http://www.goubanjia.com/http://www.ip181.com/https://www.kuaidaili.com/python 环境安装requests库安装bs4库proxies设置代理服务器地址proxies = {&#39;http&#39;:  &#39;http://61.155.164.110:3128&#39;}http://www.goub......

  • 回答 2

    要求:用户正确输入用户名和密码便成功登陆,分别有三次机会输入用户名和密码,超过3次便锁定分析:用两个while循环即可,代码如下:user_name = Brettpassword = 1314i = 0n = 0Is_exit = False  #进入循环标志while not Is_exit:User_name = input(please ...

  • 回答 2

    MacOS设置环境变量path的完全总结  一、MacOS加载bash shell 环境变量的加载顺序   mac 一般使用bash作为默认shell,Mac系统的环境变量,加载顺序为:1、系统级别的/etc/profile                                              ...

  • 回答 4

    当你运行代码的时候,需要你指定闹钟的时间,然后闹钟就会在指定的时间想起来。电脑pytho加载time模块,获取此时此刻的时间:import timet = time.localtime()print(t)时间是以字典的形式出现的。从字典里面提取时间信息:now = time.strftime(%H %M, t).spli...

  • 回答 5

    在几千条数据中有正负数,筛选出同一供应商下正负数相加为零的数据,正负数相加有可能为一正一负相加为零,也有可能是一正多负,也有可能一负多正,总体是将可以所有正负数相加为零的数据标注颜色出来。excel论坛上说计算量太 ...可以用pandas来处理...

  • 回答 2
    已采纳

    import sqlite3p = sqlite3.connect(file:memDB1?mode=memory&cache=shared, uri=True)p.execute('CREATE TABLE tbTest (fld1, fld2)')p.execute(INSERT INTO tbTest VALUES ('fld1', 'fld2'...

  • 回答 13

    Java企业级解决方案较多且成熟,国内搜索网站上对于各种问题的解答较多,相比而言,Python成熟企业级解决方案没Java多,资料多以外文为主。国内web开发大环境一直以Java为主,从业者人口基数众多,小白学习Java无论是书籍还是视频资料一搜一大把,从业者技术...

  • 回答 27

    当然可以了,不只是可以处理表格,而且是非常高效的额处理表格,能大大减轻工作量学会使用Python处理表格的话之前接了一个国企的case,说让我们给出一个解决方案关于数据处理方面的,去了他们天津的公司,一个部门7个人,7个人的工作我看了一下,我和我的同事...

  • 回答 22

    1、兼职处理数据2、兼职查询资料3、兼职P图

  • 回答 26

       Python是一门编程语言。相比于其他编程语言, Python爬取网页文档的接口更简洁;Python的urlib2包提供了完整的访问网页文档的API ;并且python中有优秀的第三方包可以高效实现网页抓取,可用极短的代码完成网页的标签过滤功能。所以Python被很多人称为爬虫。...

  • 回答 17

    可以的,python语法简单。刚开始学习可以试一下

  • 回答 25

    这两个其实现在用的都很普遍,java可能更好用一些吧

  • 回答 19

    1.if 语句1)基本用法:if 要判断的条件:    条件成立的时候,要做的事情else:    条件不成立的时候,要做的事情 if和else语句以及各自的缩进部分都是一个完整的代码块示例:2)if ,elifif 要判断的条件:    条件成立的时候,要做的事情elif 条件2...

  • 回答 26

    首先,从应用领域来看,Python语言涉及范围广,应用路径宽。其中包括:  (1)Web和Internet开发  (2)科学计算和统计  (3)人工智能  (4)桌面界面开发  (5)软件开发  (6)后端开发  (7)网络爬虫...

没有解决我的问题,去提问