美文网首页python热爱者
如果你还在用 python 3.6,那么你应该掌握它的这些特点!

如果你还在用 python 3.6,那么你应该掌握它的这些特点!

作者: 48e0a32026ae | 来源:发表于2018-09-20 11:17 被阅读0次

原文丨董明伟

Learn Python the Hard Way第四版早已经开始使用Python 3.6。想起现在还有很多朋友并有更新还一直在用Python 3.6 ,好吧,我也来列一下Python 3.6中非常值得一提的秘密。(最详细的当然还是看官方的What’s New)。

Literal String Interpolation

新增了格式化字符串变量语法,通过字符串的前缀f,实现类似于Scala/Swift等语言的字符串插值:

>>> name = 'Fred'

>>> f'My name is {name}'

'My name is Fred'

>>> date = datetime.datetime.now().date()

>>> f'{date} was on a {date:%A}'

'2017-02-25 was on a Saturday'

>>> f'{"quoted string"}'

'quoted string'

>>> def foo():

... return 20

...

>>> f'result={foo()}'

'result=20'

Asynchronous Generators

新增异步生成器语法,可以直接在协程中用生成器:

async def coro():

for item in range(10):

yield item

async def main():

async for item in coro():

...

Async comprehensions

新增异步解析语法:

result = [await fun() for fun in funcs]

result = {await fun() for fun in funcs}

result = {fun: await fun() for fun in funcs}

result = [func async for fun in funcs]

result = {func async for fun in funcs}

result = {func async for fun in funcs}

Variable annotations

在Python 3.5的时候已经添加了类型标注语法:

primes = [] # type: List[int]

primes = 1

不过得通过mypy做类型检查:

❯ mypy prime.py

prime.py:2: error: Incompatible types in assignment (expression has type "int", variable has type List[int])

现在又新增给变量添加注释语法:

>>> from typing import List

>>> primes: List[int] = []

>>> __annotations__

{'primes': typing.List[int]}

Underscores in Numeric Literals

新增数字变量使用下划线语法:

>>> '{:_}'.format(1000000)

'1_000_000'

>>> 10_000_000.0

10000000.0

新模块secrets

用来以简化使用于管理密码,比如账号认证,令牌等的密码的随机数的生成:

重新实现了dict

之前的大量实验证实,Python 3一直比较慢,这也是我一直观望的原因。目前看,Python 2.7还是最快的Python解释器。官方一直致力于速度的提升,所以 Python 3.4 < Python 3.5 < Python 3.6。

所以,3.6中参考PyPy重新实现了字典dict,使其更加紧凑。此次重新实现的dict比Python3.5中的字典内存使用减少了20%-25%。

PS: 看目前正在开发的3.7, 也会有一些显著的改善。

定制类的创建使用新协议进行了简化

Simpler customisation of class creation提供了一种可以在不使用元类的情况下自定义子类的方法。每当创建一个新的子类时,新的__init_subclass__类方法会被调用:

>>> class PluginBase:

>>> subclasses = []

>>> def __init_subclass__(cls, **kwargs):

>>> super().__init_subclass__(**kwargs)

>>> cls.subclasses.append(cls)

>>> class Plugin1(PluginBase):

>>> pass

>>> class Plugin2(PluginBase):

>>> pass

>>> PluginBase.subclasses

[__main__.Plugin1, __main__.Plugin2]

这样让自定义类的变得更简单了。

描述符协议增强

描述符是一个具有绑定行为的对象属性,由于它的优先级高会改变一个属性的基本的获取、设置和删除方式,我们先看一个例子:

class Integer(object):

def __init__(self, name):

self.name = name

def __get__(self, instance, owner):

return instance.__dict__[self.name]

def __set__(self, instance, value):

if value < 0:

raise ValueError('Negative value not allowed')

instance.__dict__[self.name] = value

class Movie(object):

score = Integer('score')

amount = Integer('amount')

movie = Movie()

movie.score = 9

print(movie.score)

相当于把score和amount这个2个属性都绑定上Integer的对象上了,结果会是:

❯ python3 movie.py9

上面的用法有个问题,就是初始化的时候都明确让属性的值绑定在Integer上的name属性上,而无法获知所有者类的属性名。使用在PEP487上提供的可选的__set_name__()可以获得这个属性名字,并且可以自定义这部分内容:

class Integer(object):

def __get__(self, instance, owner):

return instance.__dict__[self.name]

def __set__(self, instance, value):

if value < 0:

raise ValueError('Negative value not allowed')

instance.__dict__[self.name] = value

def __set_name__(self, owner, name):

self.name = name

class Movie(object):

score = Integer()

amount = Integer()

movie = Movie()

movie.score = 9

print(movie.score)

Preserving Class Attribute Definition Order

我们知道Python 2中dict是不能保存键值顺序的:

❯ python2

>>> d = {'a': 1, 'b': 2, 'c': 3}

>>> d

{'a': 1, 'c': 3, 'b': 2}

现在则会保存类属性定义顺序。也就是按照源码中属性名出现的顺序存储在__dict__ 的属性中。

而且我发现dict的实现也保留了顺序:

❯ python3

Python 3.6.0 (default, Dec 24 2016, 00:01:50)

...

>>> d = {'a': 1, 'b': 2, 'c': 3}

>>> d

{'a': 1, 'b': 2, 'c': 3}

>>>

看来OrderdDict要失业了~

Preserving Keyword Argument Order

现在也会保存关键字参数顺序了:

>>> def test(**kw):

... print(kw)

...

>>> test(a=1, b=2, c=3)

{'a': 1, 'b': 2, 'c': 3}

asyncio可用于生产环境

asyncio模板添加了很多新的功能、重要的可用性、性能改进以及大量的bug,现在asyncio模块的API已经很稳定,可用于生产环境了。其中:

有了一个更快的asyncio.Future的C的实现。有了一个更快的asyncio.Task的C的实现。

使用这2个实现可以让效率提高15%左右。而使用第三方的uvloop还能让速度提升5%-10%。

re模块

在正则表达式中,增加对spans修饰符的支持。示例: '(?i:p)ython' 匹配 'python' 和 'Python', 但不匹配 'PYTHON'; '(?i)g(?-i:v)r' 匹配 'GvR' 和 'gvr', 但不匹配 'GVR'。匹配对象组可通过__getitem__访问, 它就等价于 group()。因此, 现在mo['name'] 就等价于 mo.group('name')。Match对象支持index-like对象一样的组索引。

glob优化

通过os.scandir对glob模块中的glob()及iglob()进行优化,使得它们现在大概快了3-6倍。 唉,我当时咋没想到呢。有兴趣的可以看Issue 25596。如果你正常也有这种目录扫描的需求,请参看实现。

pickle优化

当对大量小对象进行反序列化时,pickle.load()和pickle.loads()的速度可提高10%。

相关文章

网友评论

    本文标题:如果你还在用 python 3.6,那么你应该掌握它的这些特点!

    本文链接:https://www.haomeiwen.com/subject/hutinftx.html