python3.5与3.7版本区别,python3.8和3.6
本文列举了Python3.6、3.7和3.8的新特性,学习它们有助于提高我们对Python的理解,跟上最新的趋势。
一、Python3.6的新特性1。格式化字符串的新方法。新的格式化字符串的方式,即在普通字符串前加上f或f前缀,效果类似于str.format()。例如
name=red
他说他的名字是{name}。)
# 他说他的名字是红色相当于:
Print(他说他叫{name} 。format (* * locales()))此外,该功能还支持嵌套字段,例如:
导入小数
宽度=10
精度=4
值=十进制。十进制( 12.34567 )
打印(f 结果:{值:{宽度}。{precision}} )
# 结果:12.352。变量声明语法可以声明变量并指定类型,如下所示:
从输入导入列表,字典
素数:List[int]=[]
船长:str #现在没有初始值
级星际飞船:
Stats: Dict[str,int]={}3。带下划线的数字允许在数字中使用下划线,以提高多位数的可读性。
a=1 _ 000 _ 000 _ 000 _ 000 _ 000 # 10000000000000
B=0x _ FF _ FF _ FF # 4294967295此外,字符串格式化还支持_选项,以打印可读性更好的数字字符串:
{:_}.格式(1000000) # 1_000_000
{:_ x}”。format(0x ffffffff)# ffff _ ffff 4。在Python3.5中,引入了新的语法async和await来实现协作程序。但是,有一个限制,即不能在同一个函数体中同时使用yield和await。在Python3.6中,这一限制被解除,允许定义异步生成器:
异步def ticker(延迟,至):
每隔*延迟*秒产生从0到*到*的数字
对于范围内的I(至):
产量I
Awaasyncio.sleep(延时)5。异步解析器允许在list list、set和dictionary dict解析器中使用async或await语法。
result=[i异步for i in aiter() if i % 2]
result=[await fun()for fun in fun if await condition()]6。一个新的模块:秘密已经被添加到标准库中。该模块用于生成一些安全性更高的随机数,以及管理密码、账户认证、安全令牌和相关秘密。
7.其他新特性新的PYTHONMALLOC环境变量允许开发人员设置内存分配器、注册调试挂钩等。Asyncio模块更加稳定高效,不再是临时模块,其API都是稳定版本。打字模块也得到了改进,不再是临时模块。Datetime.strftime和Datetime开始支持ISO 8601时间标识符% g,% u,% v. Hashlib和ssl模块开始支持OpenSSL 1 . 1 . 0 . lib模块开始支持新的Hashlib算法,如BLAKE2、SHA-3和SHAKE。Windows上文件系统和控制台的默认编码更改为UTF-8。json模块中的json.load()和json.loads()函数开始支持二进制类型输入。更多信息请参考官方文档:Python 3.6新增功能。
二。Python3.7新特性Python 3.7于2018年6月27日发布。它包含了许多新的特性和优化,并添加了许多新的类,可用于数据处理,优化脚本编译和垃圾收集,以及更快的异步I/O,主要如下:
用类处理数据时减少模板代码的数据类。一个可能不向后兼容的变化是在生成器中处理异常。面向解释者的“开发模式”。具有纳秒分辨率的时间对象。环境中默认使用UTF-8编码的UTF-8模式。触发调试器的新内置函数。1.添加内置函数断点()。使用这个内置函数相当于代码设置了一个断点,它会自动进入Pbd调试模式。
如果在环境变量中设置了PYTHONBREAKPOINT=0,则该函数将被忽略。此外,pdb只是众多可用调试器中的一个。您可以通过设置新的PYTHONBREAKPOINT环境变量来配置想要使用的调试器。
这里有一个简单的例子。用户需要输入一个数字来确定它是否与目标数字相同:
猜数字游戏
定义猜测(目标):
User_guess=input(请输入您猜测的数字)
如果user_guess==target:
返回“你猜对了!”
否则:
返回“猜错”
if __name__==__main__ :
a=100
Print(guess(a))遗憾的是,即使猜测的次数与目标数相同,打印的结果也是‘猜错’,没有任何异常或错误信息。
为了找出发生了什么,我们可以插入一个断点来调试它。以前我们通常使用打印解决方案或者IDE调试工具,现在可以使用断点()。
猜数字游戏
定义猜测(目标):
User_guess=input(请输入您猜测的数字)
断点()//加入此行
如果user_guess==target:
返回“你猜对了!”
否则:
返回“猜错”
if __name__==__main__ :
a=100
在pdb提示符下,我们可以调用locales()来查看当前局部作用域的所有变量。(pdb有大量的命令,您也可以在其中运行普通的Python语句)
请输入您的猜测值100。
d:\ work \ for _ test \ py3 _ test \ test . py(7)guess()
-如果用户猜测==目标:
(Pdb)局部变量()
{ 目标:100,用户猜测: 100}
(Pdb)类型(用户猜测)
明白了。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(目标:str):
User_guess:str=input(请输入您猜测的数字)
断点()
如果user_guess==target:
返回“你猜对了!”
否则:
返回“猜错”
if __name__==__main__ :
答:int=100
Print(guess(a))PyCharm会给我们一个规范性错误的灰色预警,而不是语法错误的红色预警。
当使用注释作为类型提示时,有两个主要问题:启动性能和前向引用。
定义时计算大量任意表达式相当影响启动性能,键入模块非常慢。不能用未声明的类型来注释类型化模块。这种缓慢的部分原因是,最初的设计目标是在不修改核心CPython解释器的情况下实现类型化模块。随着类型提示变得越来越流行,这种限制被取消了,这意味着现在有了对类型的核心支持。
作为前向参考,请看下面的例子:
类别用户:
def __init__(self,name: str,prev_user: User) - None:
错误是没有声明用户类型,此时prev_User不能定义为用户类型。
为了解决这个问题,Python3.7延迟了注释的求值。而且这种改变是向后不兼容的,需要先导入注释,只有Python 4.0以后才会成为默认行为。
从__未来_ _导入注释
类别用户:
def __init__(self,name: str,prev_user: User) - None:
或通过,如下例所示:
C类:
def validate_b(self,obj: B) - bool:
.
B类:
.3.添加数据类模块。Python3.7以后可能会常用这个功能,它的作用是什么?
假设我们需要编写下面的类:
从日期时间导入日期时间
导入日期实用程序
类别文章(对象):
def __init__(self,_id,author_id,title,text,tags=None,
created=datetime.now()、edited=datetime.now()):
自我。_id=_id
self.author_id=作者id
self.title=标题
self.text=text
如果tags是None else tags,则self.tags=list()
自我创造=创造
自我编辑=已编辑
如果类型(自创建)是str:
self . created=date util . parser . parse(self . created)
如果类型(自编)是str:
self . edited=date util . parser . parse(self . edited)
def __eq__(自己,其他):
如果不是isinstance(other,self。__class__):
返回未实现
回归(自我。_id,self.author_id)=(其他。_id,other.author_id)
def __lt__(自身,其他):
如果不是isinstance(other,self。__class__):
返回未实现
回归(自我。_id,self.author_id)(其他。_id,other.author_id)
def __repr__(self):
返回 {}(id={},author_id={},title={})。格式(
自我。_ _ class _ _。_ _ name _ _,self。_ ID,self。Author _ ID,本人。Title)要为大量初始化属性定义默认值,可能需要重新编写一堆神奇的方法来实现类实例的打印、比较、排序、去重等功能。
如果数据类用于转换,可以这样写:
从数据类导入数据类,字段
从输入导入列表
从日期时间导入日期时间
导入日期实用程序
@dataclass(order=True) //此处注意
类别文章(对象):
_id: int
author_id: int
标题:str=字段(比较=假)
text: str=field(repr=False,compare=False)
标签: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):
如果类型(自创建)是str:
self . created=date util . parser . parse(self . created)
如果类型(自编)是str:
self . edited=date util . parser . parse(self . edited)这使得类不仅易于设置,而且在我们创建实例并打印出来时,可以自动生成漂亮的字符串。与其他类实例相比,它的行为也很恰当。这是因为dataclasses不仅可以帮助我们自动生成__init__方法,还可以生成一些其他的特殊方法,比如repr、eq和hash。
Dataclasses使用field字段提供默认值,并手动构造field()函数来访问其他选项,从而更改默认值。例如,这里字段中的default_factory被设置为lambda函数,它提示用户输入其名称。
从数据类导入数据类,字段
类别用户:
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模块,以便在崩溃后,回溯将总是被转储。6.高精度时间函数Python 3.7中新的一类时间函数返回纳秒精度的时间值。虽然Python是一种解释性语言,但是Python的核心开发者Victor Stinner却主张报告纳秒时间。主要原因是在换算其他程序(如数据库)记录的时间值时可以避免精度的损失。
新的时间函数使用后缀_ns。例如,time.process_time()的纳秒版本是time.process_time_ns()。请注意,并不是所有的时间函数都有相应的纳秒版本。
7.其他新特征字典现在保持插入顺序。这在3.6中是非正式的,但现在它已经成为官方语言规范。在大多数情况下,普通的dict可以代替collections.OrderedDict。pyc文件是确定性的,它支持——的可重复构造。也就是说,对于相同的输入文件,总是生成相同的逐字节输出。添加了一个新的contextvars模块,为异步任务提供上下文变量。__main__中的代码显示一个弃用警告。添加UTF-8模式。在Linux/Unix系统上,系统的语言环境将被忽略,UTF-8将被用作默认编码。在非Linux/Unix系统上,需要使用-X utf8选项来启用UTF-8模式。允许模块定义__getattr__和__dir__函数,这有助于丢弃警告和延迟导入子模块。新线程本地存储C语言API。将Unicode数据更新到11.0。三。Python3.8 Python版新特性发布于2019年10月14日。下面是Python3.8相比3.7的新特性。
1.walrus赋值表达式的新语法:=,在更大的表达式中给变量赋值。它被亲切地称为“海象操作员”,因为它看起来像海象的眼睛和象牙。
“walrus operator”在某些时候可以让你的代码更整洁,比如:
在下面的示例中,赋值表达式可以避免调用len()两次:
if (n :=len(a)) 10:
print类似的好处(f list太长({n}个元素,预期=10))也可以体现在正则表达式匹配需要使用两次匹配对象的情况下,一次检测匹配是否发生,另一次提取子包:
折扣=0.0
if(mo:=re . search(r (\ d)% discount ,advertisement)):
折扣=浮动(mo。group (1))/100.0该运算符也可以与while循环一起使用,以计算一个值来检测循环是否终止,以及在循环体中是否再次使用了相同的值:
#在固定长度的块上循环
while (block :=f.read(256))!=:
Process(block)或者出现在列表派生中,并且在过滤条件中计算一个值,并且需要在表达式中使用相同的值:
[clean_name.title()用于名称中的名称
If (clean _ name:=normalize (NFC ,name)) in allowed _ names]请尽量限制使用walrus运算符来清除场合,以降低复杂性并提高可读性。
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=无,/):
模拟内置的pow()函数
r=x ** y
R if z is none else r % z另一个用例是在不需要参数名时排除关键字参数。比如内置len()函数的签名是len (obj,/)。这样可以排除如下笨拙的调用形式:
Len (obj= hello) #关键字参数影响可读性另一个好处是,将参数标记为仅位置参数将允许将来修改参数名称,而不会破坏客户的代码。例如,在统计模块中,参数名称dist将来可能会被修改。这使得描述以下功能成为可能:
定义分位数(dist,/,*,n=4,method=exclusive )
.由于/左侧的参数不会被公开为可用的关键字,因此其他参数名称仍然可以在**kwargs中使用:
def f(a,b,/,**kwargs):
.印刷(a、b、kwargs)
.
f(10,20,a=1,b=2,c=3) # a和b有两种用法
0 20 {a: 1, b: 2, c: 3}这大大简化了需要接受任意关键字参数的函数和方法的实现。例如,下面是集合模块中代码的摘录:
类别计数器(字典):
def __init__(self,iterable=None,/,**kwds):
#注意“iterable”是一个可能的关键字参数3,f字符串支持=
Add=字符串的说明符。f{expr=} 形式的f字符串将被扩展为表达式文本,加上一个等号和表达式的求值结果。例如:
user=eric_idle
member_since=date(1975,7,31)
f“{ user=} { member _ since=}”
user= Eric _ idle member _ since=datetime . date(July 31 of 1975) f字符串格式说明符允许对要显示的表达式结果进行更详细的控制:
delta=date . today()-member _ since
f“{ user=!s} {delta.days=:d}
User=eric _ idledelta.days=16,075=说明符将输出整个表达式以详细演示计算过程:
print(f{theta=} {cos(弧度(theta))=:3f} )
=30 cos(弧度())=0.8664。Python是对typing module的改进,是一种动态类型语言,但你可以通过typing module添加类型提示,以便第三方工具验证Python代码。Python 3.8为类型添加了一些新元素,因此它可以支持更健壮的检查:
Final decorator和final type annotation表示被修饰或注释的对象在任何时候都不应该被重写、继承或重新分配。文字类型将表达式限制为特定的值或值列表(不一定是同一类型的值)。TypedDict可用于创建字典,特定键的值仅限于一种或多种类型。请注意,这些限制仅用于在编译时确定值的合法性,在运行时不能受到限制。5.多进程SharedMemory多处理模块增加了共享内存类,可以在不同的Python城市之间创建共享内存区。
在旧版本的Python中,进程间共享数据只能通过写文件,通过网络套接字发送,或者通过Python的pickle模块序列化来完成。共享内存提供了一种更快的方法在进程间传输数据,这使得Python的多处理器和多核编程更加高效。
共享内存片段可以作为纯字节区域分配,也可以作为未修改的类似列表的对象分配,其中可以存储少量的Python对象,如数字类型、字符串、字节对象和None对象。
6.pickle协议Python的pickle模块的新版本提供了一种序列化和反序列化Python数据结构或实例的方法,这种方法可以按原样保存字典以供以后阅读。不同版本的Python支持不同的pickle协议,而3.8版本支持更广泛、更强大、更有效的序列化。
Python 3.8推出的pickle协议第5版可以使用一个新的方法pickle object,它可以支持Python的buffer协议,比如bytes、memoryviews或者Numpy array。新的pickle避免了拾取这些对象时的许多内存复制操作。
NumPy、Apache Arrow和其他外部库在其Python绑定中支持新的pickle协议。新的pickle也可以作为Python 3.6和3.7的插件,可以从PyPI安装。
7.性能提升。很多内置方法和函数的速度提升了20%~50%,因为之前很多函数需要不必要的参数转换。新的操作码缓存可以提高解释器中特定指令的速度。但目前只有LOAD_GLOBAL操作码实现了速度提升,速度提升了40%。在的未来版本中也会进行类似的优化。shutil.copyfile()和shutil.copytree()等文件复制操作现在使用特定于平台的调用和其他优化措施来加速操作。新创建的列表现在平均比以前小了12%,这要归功于这样一个事实,即如果可以提前知道列表的长度,就可以优化列表构造函数。在Python 3.8中,写入新类(比如A类(object))的类变量变得更快。Operator.itemgetter()和collections.namedtuple()也针对速度进行了优化。更多细节请参考Python 3.8.0文档:https://docs.python.org/zh-cn/3.8/whatsnew/3.8.html.
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。