发布于 2026-01-05 6 阅读
0

Python 3.8 已发布🚀🚀 让我们一起来参观 Python38_Tour

Python 3.8 已发布🚀🚀 让我们一起来参观一下

Python38之旅

封面图片由 Onur Ömer Yavuz 在 Pixabay上的
!python --version
Enter fullscreen mode Exit fullscreen mode
Python 3.8.0rc1
Enter fullscreen mode Exit fullscreen mode

启动页面

Python 3.8 是 Python 的一个重要版本。以下是一些新特性的汇总。

  1. 新的语法规则!
  2. 并行数据运维改进!
  3. 静态类型检查功能!
  4. CPython 相关内容!

让我们从一条新的语法规则开始:

表达式中的赋值(PEP 572)

Python 现在允许你在表达式内部创建变量(例如列表推导式的主体)。

def f(x):
    for k in range(10000000):
        x*x*x/x+x+x+x+x
    return x

x = 2

# Reuse a value that's expensive to compute
%timeit [y := f(x), y**2, y**3]

# Without reuse
%timeit [f(x), f(x)**2, f(x)**3]
Enter fullscreen mode Exit fullscreen mode
1.78 s ± 13.5 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
5.45 s ± 93.9 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
Enter fullscreen mode Exit fullscreen mode

PEP强烈不鼓励在“裸露”的表情中这样做。参见:例外情况

PEP 572

这里还有一条新的语法规则:

位置限定的精氨酸(PEP 570)

这个问题让我很困惑,直到我向下滚动到语法部分才明白,所以我们来看看它的实际应用:

def prelaunch_func(foo, bar, baz=None):
    print(f"\nFoo:{foo}\nBar:{bar}\nBaz:{baz}")

def pep570_func(foo, /, bar, baz=None):
    print(f"\nFoo:{foo}\nBar:{bar}\nBaz:{baz}")
Enter fullscreen mode Exit fullscreen mode

/调用签名中的` pep570_func<` 表示仅位置参数的结束位置。这些函数将让我们看到 PEP 570 带来的实际差异。

prelaunch_func(foo=1, bar=2, baz=3)
Enter fullscreen mode Exit fullscreen mode
Foo:1
Bar:2
Baz:3
Enter fullscreen mode Exit fullscreen mode
# Violating positional-only
pep570_func(foo=1, bar=2, baz=3)
Enter fullscreen mode Exit fullscreen mode
---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

<ipython-input-4-9e9851275486> in <module>
      1 # Violating positional-only
----> 2 pep570_func(foo=1, bar=2, baz=3)


TypeError: pep570_func() got some positional-only arguments passed as keyword arguments: 'foo'
Enter fullscreen mode Exit fullscreen mode
# This is fine, as bar is right of the "/" in the call signature
pep570_func(1, bar=2, baz=3)
Enter fullscreen mode Exit fullscreen mode
Foo:1
Bar:2
Baz:3
Enter fullscreen mode Exit fullscreen mode
# This was wrong before PEP-570 of course
pep570_func(foo=1, 2, baz=3)
Enter fullscreen mode Exit fullscreen mode
  File "<ipython-input-6-adcd14865e94>", line 2
    pep570_func(foo=1, 2, baz=3)
                       ^
SyntaxError: positional argument follows keyword argument
Enter fullscreen mode Exit fullscreen mode

我最喜欢这个 PEP 的一点是,它还允许你使用带有默认值的位置参数,如下所示:

def pep570_func(foo, bar=None, baz=1, /):
    print(f"\nFoo:{foo}\nBar:{bar}\nBaz:{baz}")

pep570_func(10)
Enter fullscreen mode Exit fullscreen mode
Foo:10
Bar:None
Baz:1
Enter fullscreen mode Exit fullscreen mode
# But don't mistake them for kwargs
pep570_func(10, bar=1)
Enter fullscreen mode Exit fullscreen mode
---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

<ipython-input-8-05c1c4b07ca6> in <module>
      1 # But don't mistake them for kwargs
----> 2 pep570_func(10, bar=1)


TypeError: pep570_func() got some positional-only arguments passed as keyword arguments: 'bar'
Enter fullscreen mode Exit fullscreen mode

更多详情请参阅 PEP:PEP-570

现在我们来谈谈并行数据处理:

共享记忆和新泡菜

3.8 版本中的两项重要改进受到了dask等库的启发,这些库旨在解决进程间数据传递的问题。其中一项改进是创建了一个新版本,pickle该版本可以使用零拷贝缓冲区在进程间传递数据对象,从而实现更高效的内存共享。

这些第三方序列化方案的共同点在于生成一个对象元数据流(包含类似 pickle 格式的被序列化对象信息)和一个单独的零拷贝缓冲区对象流,用于存储大型对象的有效载荷。需要注意的是,在这种方案中,诸如整数之类的小对象可以与元数据流一起转储。改进方案还可以包括根据数据类型和布局对大型数据进行机会性压缩,例如 Dask 的做法。

本 PEP 旨在使 pickle 能够以某种方式使用,即以单独的零拷贝缓冲区流来处理大数据,从而使应用程序能够以最佳方式处理这些缓冲区。

PEP-574

该类别中的另一项重大改进是进程拥有了一个新的内存共享接口:SharedMemory`and` SharedMemoryManager。文档中提供了一个非常精彩的示例:

import multiprocessing
from multiprocessing.managers import SharedMemoryManager

# Arbitrary operations on a shared list
def do_work(shared_list, start, stop):
    for idx in range(start, stop):
        shared_list[idx] = 1

# Example from the docs
with SharedMemoryManager() as smm:
    sl = smm.ShareableList(range(2000))
    # Divide the work among two processes, storing partial results in sl
    p1 = multiprocessing.Process(target=do_work, args=(sl, 0, 1000))
    p2 = multiprocessing.Process(target=do_work, args=(sl, 1000, 2000))
    p1.start()
    p2.start()  # A multiprocessing.Pool might be more efficient
    p1.join()
    p2.join()   # Wait for all work to complete in both processes
    total_result = sum(sl)  # Consolidate the partial results now in sl

# `do_work` set all values to 1 in parallel
print(f"Total of values in shared list: {total_result}")
Enter fullscreen mode Exit fullscreen mode
Total of values in shared list: 2000
Enter fullscreen mode Exit fullscreen mode

这些改进能否为并行操作库开辟一条通往成功的道路,还有待观察。无论如何,这令人振奋。点击SharedMemory 此处查看详情。

现在我们来看一些静态类型检查的内容:

类型化词典(PEP 589)

类型提示无法处理嵌套字典,数据类也无法很好地解析为 JSON,因此 Python 现在将支持对具有已知键集的字典进行一些静态类型检查。请看下面的脚本:

# scripts/valid_589.py
from typing import TypedDict

class Movie(TypedDict):
    name: str
    year: int

# Cannonical assignment of Movie
movie: Movie = {'name': 'Wally 2: Rise of the Garbage Bots', 'year': 2055}
Enter fullscreen mode Exit fullscreen mode

mypy不会出现任何问题,因为字典是某种类型的有效实现。

!mypy scripts/valid_589.py
Enter fullscreen mode Exit fullscreen mode
[1m[32mSuccess: no issues found in 1 source file[m
Enter fullscreen mode Exit fullscreen mode

现在来看下面这个无效的脚本——它的值类型错误:

# scripts/invalid_values_589.py
from typing import TypedDict

class Movie(TypedDict):
    name: str
    year: int

def f(m: Movie):
    return m['year']

f({'year': 'wrong type', 'name': 12})
Enter fullscreen mode Exit fullscreen mode
!mypy scripts/invalid_values_589.py
Enter fullscreen mode Exit fullscreen mode
scripts/invalid_values_589.py:10: [1m[31merror:[m Incompatible types (expression has type [m[1m"str"[m, TypedDict item [m[1m"year"[m has type [m[1m"int"[m)[m
scripts/invalid_values_589.py:10: [1m[31merror:[m Incompatible types (expression has type [m[1m"int"[m, TypedDict item [m[1m"name"[m has type [m[1m"str"[m)[m
[1m[31mFound 2 errors in 1 file (checked 1 source file)[m
Enter fullscreen mode Exit fullscreen mode

您还可以使用构造函数检查缺失值、无效字段,或者创建TypedDict接受缺失值的字段。total=False

PEP 589

最终性(PEP 591)

3.8 版本还将实现最终性。我们可以阻止对象被重写或继承。@final装饰器可以与定义一起使用class来阻止继承,而Final类型可以阻止重写。以下是 PEP 中的两个示例:

# Example 1, inheriting a @final class
from typing import final

@final
class Base:
    ...

class Derived(Base):  # Error: Cannot inherit from final class "Base"
    ...

# Example 2, overriding an attribute
from typing import Final

class Window:
    BORDER_WIDTH: Final = 2.5
    ...

class ListView(Window):
    BORDER_WIDTH = 3  # Error: can't override a final attribute
Enter fullscreen mode Exit fullscreen mode

最终性可以应用于方法、属性和继承。请查看PEP 591中的所有特性。

字面值(PEP 586)

如果函数期望的参数 s 位于某个范围内,那么类型提示调用签名def f(k: int):就帮不上忙了。它需要一个来自特定字符串集合的参数。这时 s 就派上用场了!intopenmode: strLiteral

# scripts/problematic_586.py
def problematic_586(k: int):
    if k < 100:
        return k
    else:
        raise ValueError('Gotta be less than 100')
problematic_586(144)
Enter fullscreen mode Exit fullscreen mode
!mypy scripts/problematic_586.py
Enter fullscreen mode Exit fullscreen mode
[1m[32mSuccess: no issues found in 1 source file[m
Enter fullscreen mode Exit fullscreen mode

相反,我们可以将一个值传递Literal给参数的类型提示k

# scripts/valid_586.py
from typing import Literal

def valid_586(k: Literal[0, 1, 2, 99]):
    if k < 100:
        return k
    else:
        return float(k)
valid_586(43)
Enter fullscreen mode Exit fullscreen mode
!mypy scripts/valid_586.py
Enter fullscreen mode Exit fullscreen mode
scripts/valid_586.py:8: [1m[31merror:[m Argument 1 to [m[1m"valid_586"[m has incompatible type [m[1m"Literal[43]"[m; expected [m[1m"Union[Literal[0], Literal[1], Literal[2], Literal[99]]"[m[m
[1m[31mFound 1 error in 1 file (checked 1 source file)[m
Enter fullscreen mode Exit fullscreen mode

使用起来有一些细微差别Literal,所以如果您决定进一步探索,请从PEP-586开始。

就是这样!我暂时不会写关于 CPython 特性的文章,因为坦白说,我希望在对 CPython 整体及其特性有更深入的了解之后再去写。

感谢阅读!

PS:如果您想尝试本博客中的任何示例,或者想在不安装的情况下试用 Python 3.8,我已在下方提供了本博客的源代码仓库。其中包含一个 Dockerfile,可以快速启动一个 Python 3.8 JupyterLab 环境。

GitHub 标志 CharlesDLandau / python38_blog

包含博客源代码的仓库

Python38之旅

这是本博客的源代码仓库,其中还包含一个 Dockerfile,用于直接启动 Python 3.8,而无需在本地安装。具体如下:

//建造
docker build -t < img_tag >  .
//在* nix
上运行
docker run -p 8888:8888 -it --rm -v $( PWD ) :/code --name dev < img_tag >

//在 Windows 上运行
docker run -p 8888:8888 -it --rm -v %CD%:/code --name dev < img_tag >
Enter fullscreen mode Exit fullscreen mode

如果一切顺利,系统会提示您将 URL 复制到浏览器中,该 URL 将指向本地端口 8888,并附带一个令牌以授权访问 Jupyter 实例。

文章来源:https://dev.to/charlesdlandau/python-3-8-has-been-released-let-s-take-a-tour-bj3