飞跃式发展的后现代 Python 世界
admin
2023-07-31 00:37:36
0

飞跃式发展的后现代Python世界

如果现代Python有一个标志性特性,那么简单说来便是Python对自身定义的越来越模糊。在过去的几年的许多项目都极大拓展了Python,并重建了“Python”本身的意义。

与此同时新技术的涌现侵占了Python的份额,并带来了新的优势:

  1. Go – ( Goroutines, Types, Interfaces )
  2. Rust – ( Traits, Speed, Types )
  3. Julia – ( Speed, Types, Multiple Dispatch )
  4. Scala – ( Traits, Speed, Types )
  5. Clojure ( Metaprogramming, DSLs, Protocols )

这是一篇Python对这些新技术、新库及模型响应的简短指南:

元编程

MacroPy 是一个元编程框架,它提供了多种语法结构,将现代语言元素编译成标准的Python代码,扩展了Python AST。举个例子,我们可以实现对代数数据类型的衡量:

1234567891011 from macropy.case_classes import case @caseclass Nil():    pass @caseclass Cons(x, xs):    pass Cons(1, Cons(2, Cons(3, Nil())))

然后模式和声明的类型相匹配了:

123456 def reduce(op, my_list):    with switch(my_list):        if Cons(x, Nil()):            return x        elif Cons(x, xs):            return op(x, reduce(op, xs))

消失的部分仍然是一个沿着camlp4路线,可扩展阶段的元编程系统。但是 Mython提供了一个pgen2解析框架,给引用块定义了新的语法,来解决这个问题。

12345678 my[namedtupledef] Point(x, y): pass my[c]:    int add (int x, int y) {        return x + y;    } print \”Regular Python\”

类型

Python 是动态类型语言,并且引以为傲。我当然不希望对类型的“圣战”煽风点火,但同时肯定有大学派认为构建可靠的应用程序需要有比只使用单元测试更加有力的保障。Benjamin Pierce对类型系统的定义如下:

…一种易于处理的语法,通过根据计算值的类型对词组分类证明了缺少了特定的程序行为

重点是证明有关运行空间的属性, 所有程序行为的运行空间替代了只是简单地罗列有限种情况的运行空间。全静态类型对于Python是否是正确的选择让人十分疑惑,但是在过度的动态类型和静态类型保证之间肯定有更加合适的方案。MyPy project找到了一个不错的平衡点,允许有类型的和没有类型的代码能够同时存于语言的超集中。例如:

12345678910 def simple_typed(x : int, y : int) -> int:    return x + y simple_typed(1, 2)     # Type-checks succesfully # Fails: Argument 2 to \”simple_typed\” has incompatible type # \”float\”simple_typed(1, 2.0) # Fails: Argument 2 to \”simple_typed\” has incompatible type \”str\”simple_typed(1, \”foo\”)

当然对C语言没有太多的用处。所以我们不只限于简单类型的函数,参数类型也有泛型,指针类型和各种各样内建的类型级的函数。

1234567891011 from typing import Iterator, typevar, Generic, Function, List T = typevar(\’T\’) def example_typed(x : Iterator[int]) -> Iterator[str]:    for i in x:        yield str(i) def example_generic(x : Iterator[T]) -> Iterator[T]:    for i in x:        yield i

我们也能定义更加高级的泛型结构例如函子和单元

123456789101112131415161718192021222324252627282930 a = typevar(\’a\’)b = typevar(\’b\’) class Functor(Generic[a]):    def __init__(self, xs : List[a]) -> None:        self._storage = xs     def iter(self) -> Iterator[a]:        return iter(self._storage) def fmap(f : Function[[a], b], xs : Functor[a]) -> Functor[b]:    return Functor([f(x) for x in xs.iter()]) class Monad(Generic[a]):    def __init__(self, val : a) -> None:        self.val = val class IdMonad(Monad):     # Monad m => a -> m a    def unit(self, x : a) -> Monad[b]:        return IdMonad(x)     # Monad m => m a -> (a -> m b) -> m b    def bind(self, x : Monad[a], f : Function[[a], Monad[b]]) -> Monad[b]:        return f(x.val)     # Monad m => m (m a) -> m a    def join(self, x : Monad[Monad[a]]) -> Monad[a]:        return x.val

速度

“高性能”Python最近最重要的进展是Pandas库提供的更高等级DataFrame容器的开发。Pandas混合各种Python进行操作,对于某些操作使用NumPy,其它的使用Cython,对于某些内部哈希表甚至使用C语言。Panda底层架构非教条式的方法已经让它成为数据分析领域的标准库。Pandas的开发体现了很多让数值Python生态系统成功的东西。

12345678910 In [1]: from pandas import DataFrame In [2]: titanic = DataFrame.from_csv(\’titanic.csv\’) In [3]: titanic.groupby(\’pclass\’).survived.mean()pclass1st       0.6191952nd       0.4296033rd       0.255289Name: survived

然而改善Python性能最近的尝试是利用LLVM编译器有选择的编译某些Python代码段为本地代码。虽然不同的技术的实现方式不同,但是大部分与下述方式类似:

  1. 在函数上添加@jit或@compile这样的装饰器。
  2. 函数的AST或者bytecode被提取出来放入编译器流水线,在流水线中被映射到内部AST,给定特定的输入类型集合决定如何将给定的函数逻辑降低为机器代码。
  3. 编译过的函数与一组类型一起被调用,参数被检查过,代码在给定类型下生成。生成的代码连同参数被缓存使得接下来的调用直接分发到本地代码。

这些项目增加了大家对Python语言技术和llvmpy项目开发的兴趣,我猜测llvmpy在Python的历史上比特定的JIT编译器更重要。

最简单的例子(来自极好的Kaleidescope教程)是创建一个简单的本地乘加函数,然后通过解箱三个Python整数调用它:

1234567891011121314151617181920212223242526272829303132333435 import llvm.core as lcimport llvm.ee as le mod = lc.Module.new(\’mymodule\’) i32 = lc.Type.int(32)funty = lc.Type.function(lc.Type.int(), [i32, i32, i32]) madd = lc.

相关内容

热门资讯

500 行 Python 代码... 语法分析器描述了一个句子的语法结构,用来帮助其他的应用进行推理。自然语言引入了很多意外的歧义,以我们...
定时清理删除C:\Progra... C:\Program Files (x86)下面很多scoped_dir开头的文件夹 写个批处理 定...
65536是2的几次方 计算2... 65536是2的16次方:65536=2⁶ 65536是256的2次方:65536=256 6553...
Mobi、epub格式电子书如... 在wps里全局设置里有一个文件关联,打开,勾选电子书文件选项就可以了。
scoped_dir32_70... 一台虚拟机C盘总是莫名奇妙的空间用完,导致很多软件没法再运行。经过仔细检查发现是C:\Program...
小程序支付时提示:appid和... [Q]小程序支付时提示:appid和mch_id不匹配 [A]小程序和微信支付没有进行关联,访问“小...
pycparser 是一个用... `pycparser` 是一个用 Python 编写的 C 语言解析器。它可以用来解析 C 代码并构...
微信小程序使用slider实现... 众所周知哈,微信小程序里面的音频播放是没有进度条的,但最近有个项目呢,客户要求音频要有进度条控制,所...
python查找阿姆斯特朗数 题目解释 如果一个n位正整数等于其各位数字的n次方之和,则称该数为阿姆斯特朗数。 例如1^3 + 5...
Apache Doris 2.... 亲爱的社区小伙伴们,我们很高兴地向大家宣布,Apache Doris 2.0.0 版本已于...