今天看到有关python的文章,感觉很好奇,学了python很久了,但是还没有真正的用过,只是写一些小程序

看了这篇文章以后真的感觉自己所了解都是皮毛,在此与大家分享:

原文链接:http://www.stephendiehl.com/posts/postmodern.html

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

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

Go - ( Goroutines, Types, Interfaces )

Rust - ( Traits, Speed, Types )

Julia - ( Speed, Types, Multiple Dispatch )

Scala - ( Traits, Speed, Types )

Clojure ( Metaprogramming, DSLs, Protocols )

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

元编程

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

     from macropy.case_classes import case 

     @case
class Nil():
pass @case
class Cons(x, xs):
pass Cons(1, Cons(2, Cons(3, Nil())))

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

     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解析框架,给引用块定义了新的语法,来解决这个问题。

     my[namedtupledef] Point(x, y): pass 

     my[c]:
int add (int x, int y) {
return x + y;
} print "Regular Python"

类型

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

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

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

     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语言没有太多的用处。所以我们不只限于简单类型的函数,参数类型也有泛型,指针类型和各种各样内建的类型级的函数。

     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

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

     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生态系 统成功的东西。

     In [1]: from pandas import DataFrame 

     In [2]: titanic = DataFrame.from_csv('titanic.csv') 

     In [3]: titanic.groupby('pclass').survived.mean()
pclass
1st 0.619195
2nd 0.429603
3rd 0.255289
Name: survived

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

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

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

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

     import llvm.core as lc
import 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.Function.new(mod, funty, "multiply")
x = madd.args[0]
y = madd.args[1]
z = madd.args[2] block = madd.append_basic_block("L1") builder = lc.Builder.new(block)
x0 = builder.mul(x, y)
x1 = builder.add(x0, z) builder.ret(x1) print mod tm = le.TargetMachine.new(features='', cm=le.CM_JITDEFAULT)
eb = le.EngineBuilder.new(mod)
engine = eb.create(tm) ax = le.GenericValue.int(i32, 1024)
ay = le.GenericValue.int(i32, 1024)
az = le.GenericValue.int(i32, 1024) ret = engine.run_function(madd, [ax, ay, az]) print ret.as_int()
print mod.to_native_assembly()

上述代码编译生成下述LLVM IR。

     define i32 @multiply(i32, i32, i32) {
L1:
%3 = mul i32 %0, %1
%4 = add i32 %3, %2
ret i32 %4
}

虽然这个例子不太直观,但是可以生成很快的JIT'd函数,与NumPy这样的库集成的很好,把数据做为大块的解箱内存存储。

接口

分解行为到可组合的单元,而不是显式的继承层次结构是一个Python没有解决好的问题,经常导致噩梦般的复杂的使用mixin。然而通过使用ABC模组模仿静态定义的接口可以缓解这个问题。

     import heapq
import collections class Heap(collections.Sized):
def __init__(self, initial=None, key=lambda x:x):
self.key = key
if initial:
self._data = [(key(item), item) for item in initial]
heapq.heapify(self._data)
else:
self._data = [] def pop(self):
return heapq.heappop(self._data)[1] def push(self, item):
heapq.heappush(self._data, (self.key(item), item)) def len(self):
return len(self._data)

例如建立一个等价类,让所有类的实例实现eq()方法。我们可以这样做:

     from abc import ABCMeta, abstractmethod 

     class Eq(object): 

         __metaclass__ = ABCMeta 

         @classmethod
def __subclasshook__(cls, C):
if cls is Eq:
for B in C.__mro__:
if "eq" in B.__dict__:
if B.__dict__["eq"]:
return True
break
return NotImplemented def eq(a, b):
if isinstance(a, Eq) and isinstance(b, Eq) and type(a) == type(b):
return a.eq(b)
else:
raise NotImplementedError class Foo(object):
def eq(self, other):
return True class Fizz(Foo):
pass class Bar(object):
def __init__(self, val):
self.val = val def eq(self, other):
return self.val == other.val print eq(Foo(), Foo())
print eq(Bar(1), Bar(1))
print eq(Foo(), Bar(1))
print eq(Foo(), Fizz())

然后扩展这种类型的接口概念到多参数的函数,使得查询__dict__越来越可能发生,在组合的情况下很脆弱。问题的关键是分解所有的事情到单一类型不同的接口,当我们真正想要的是声明涵盖一组多类型的接口时。OOP中的这种缺点是 表达式问题的关键。

诸如Scala、Haskell和Rust这样的语言以trait和typeclass这样的形式提供该问题的解决方案。例如Haskell可以自动地为所有类型的交叉产品推导出微分方程。

     instance (Floating a, Eq a) => Floating (Dif a) where
pi = C pi exp (C x) = C (exp x)
exp (D x x') = r where r = D (exp x) (x' * r) log (C x) = C (log x)
log p@(D x x') = D (log x) (x' / p) sqrt (C x) = C (sqrt x)
sqrt (D x x') = r where r = D (sqrt x) (x' / (2 * r))

异步编程

在这个主题下,我们还是有很多缝缝补补的解决方案,解决了部分的问题,但是引入了一整与常规Python背道而驰的套限制和模式。Gevent通过剪接底层C堆栈保持了Python自己的一致性。生成的API非常优雅,但是使得推理控制流和异常非常复杂。

     import gevent 

     def foo():
print('Running in foo')
gevent.sleep(0)
print('Explicit context switch to foo again') def bar():
print('Explicit context to bar')
gevent.sleep(0)
print('Implicit context switch back to bar') gevent.joinall([
gevent.spawn(foo),
gevent.spawn(bar),
])

控制流展示在下面:

通过对标准库相当不优美的缝缝补补(monkey-patching),我们可以模仿Erlang式带有异步进入点和内部状态的actor行为:

     import gevent
from gevent.queue import Queue
from SimpleXMLRPCServer import SimpleXMLRPCServer class Actor(object):
_export = [
'push',
] def __init__(self, address):
self.queue = Queue() self._serv = SimpleXMLRPCServer(address, allow_none=True, logRequests=False)
self.address = address for name in self._export:
self._serv.register_function(getattr(self, name)) def push(self, thing):
self.queue.put(thing) def poll(self):
while True:
print(self.queue.get()) def periodic(self):
while True:
print('PING')
gevent.sleep(5) def serve_forever(self):
gevent.spawn(self.periodic)
gevent.spawn(self.poll)
self._serv.serve_forever() def main():
from gevent.monkey import patch_all
patch_all() serve = Actor(('', 8000))
serve.serve_forever()

DSLs

Z3工程是嵌在Python对象层的扩展API。用Z3的实例来解决N皇后问题可以被描述为Python表达式和扩展SMT来解决问题:

     from Z3 import * 

     Q = [ Int('Q_%i' % (i + 1)) for i in range(8) ] 

     # Each queen is in a column {1, ... 8 }
val_c = [ And(1 <= Q[i], Q[i] <= 8) for i in range(8) ]
# At most one queen per column
col_c = [ Distinct(Q) ] # Diagonal constraint
diag_c = [ If(i == j,
True,
And(Q[i] - Q[j] != i - j, Q[i] - Q[j] != j - i))
for i in range(8) for j in range(i) ] solve(val_c + col_c + diag_c)

在Theano,SymPy,PySpark中的其它工程大量使用基于Python表达式的重载操作符的方式。

     from sympy import Symbol
from sympy.logic.inference import satisfiable x = Symbol('x')
y = Symbol('y')
satisfiable((x | y) & (x | ~y) & (~x | y))

python 新时代的更多相关文章

  1. Vimer的福音 新时代的Vim C++自动补全插件 clang_complete

    使用vim的各位肯定尝试过各种各样的自动补全插件,比如说大名鼎鼎的 OmniCppComplete .这一类的插件都是对 Ctags 生成的符号表进行字符串匹配来获得可能的补全项.他们在编写 C 代码 ...

  2. MEAN实践——LAMP的新时代替代方案(上)

    摘要:90 年代,LAMP 曾风靡一时,然而随着需求的变迁和数据流量的激增,LAMP 已不可避免的走下神坛.近日,在 MongoDB Blog 中,Dana Groce 介绍了一个基于新时代架构的实践 ...

  3. 新时代的Vim C++自动补全插件 clang_complete

    Vimer的福音 新时代的Vim C++自动补全插件 clang_complete   使用vim的各位肯定尝试过各种各样的自动补全插件,比如说大名鼎鼎的 OmniCppComplete .这一类的插 ...

  4. WebAssembly,Web的新时代

    在浏览器之争中,Chrome凭借JavaScript的卓越性能取得了市场主导地位,然而由于javascript的无类型特性,导致其运行时消耗大量的性能做为代价,这也是JavaScript的瓶颈之一.W ...

  5. modern php笔记---1、新时代的php

    modern php笔记---1.新时代的php 一.总结 一句话总结: php有Zend Engine 和 Facebook开发的 HipHop Virtual Machine两套引擎 1.php也 ...

  6. Python一键转Jar包,Java调用Python新姿势!

    粉丝朋友们,不知道大家看故事看腻了没(要是没腻可一定留言告诉我^_^),今天这篇文章换换口味,正经的来写写技术文.言归正传,咱们开始吧! 本文结构: 需求背景 进击的Python Java和Pytho ...

  7. 组合式应用新利器?SaaS新时代事件网格如何解决集成标准化问题

    摘要:组合式应用需要面临的一个难题是如何解决各个应用之间的集成标准问题,比如应用可能仅支持HTTP.TCP等协议中的一种,而缺乏统一的通讯标准就给业务落地该架构带来了困难.下面介绍事件网格(Event ...

  8. 全景智慧城市——VR全景,开启VR营销新时代

    全景是一种新兴的富媒体技术. 与视频.声音.图片等传统主流媒体最大的区别是"可操作,可交互". 全景给人以三维立体感觉的实景360°全方位图像,此图像最大的三个特点: 全方位:展示 ...

  9. 2018 dnc 公司案例大全,迎接.NET Core开源新时代

    2018 dnc 公司案例大全,迎接.NET Core开源新时代   dnc = .NET Core.dotnet Core dnc是微软新一代主力编程平台,开源.免费.跨平台.轻量级.高性能,支持L ...

随机推荐

  1. 关于Excle中的VLookUp的函数的使用

    VLookUp函数的使用,VLookUp中的V是垂直的(vertical)意思,此外与此相类似的函数还有HLOOKUP(Horizonal水平的)意思. 下面主要谈谈VLookUp的使用方法. VLo ...

  2. hdu 4009 最小树形图

    思路:唯一一个值得一提的就是建一个0号根节点,往每个房子建一条边,权值为房子的高度乘以X. #include<iostream> #include<cstdio> #inclu ...

  3. Servlet & JSP - Form-based Authentication

    基本认证和摘要认证都只能使用浏览器自带的登录框而不能使用自定义的登录页面.如果必须使用自定义的登录页面,则可以选择基于表框的认证方式. 基于表框的认证的配置与基本认证和摘要认证的差别在于部署描述符中  ...

  4. HDOJ2019数列有序!

    数列有序! Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submi ...

  5. Android Support v4,v7,v13

    Android Support v4 是最早(2011年4月份)实现的库.用在Android1.6 (API lever 4)或者更高版本之上.它包含了相对V4, V13大的多的功能. 例如:Frag ...

  6. CDH离线安装之安装包下载地址

    cloudermanager安装包地址:http://archive.cloudera.com/cm5/cm/5/cloudera-manager-el6-cm5.3.0_x86_64.tar.gz, ...

  7. 开源而又强大的迷你型web服务器推荐

    appweb显然是不二之选,看了下最新版,已经到了4了 下载下来,http://appwebserver.org/software/appweb-4.4.4-0-src.tgz,十几M,直接吓傻,离我 ...

  8. Could not load the "defaultimg" image referenced from a nib in the bundle with identifier "com.abc"

    出现这个错误提示,是因为在xib中使用了.jpg格式的图片,在图片名称后面加上.jpg即可;

  9. 【转】fread函数和fwrite函数

    1.函数功能   用来读写一个数据块. 2.一般调用形式   fread(buffer,size,count,fp);   fwrite(buffer,size,count,fp); 3.说明   ( ...

  10. 致vi老大 2011.1

    文/安然 亲爱的,你即将离去 飞机起飞的一刻, 请珍藏起我们2010的回忆 桃源仙谷,曾留下我们踏青的足迹 难忘,石头上小憩 小北门外,我们在大排档里尽情欢喜 见证,杯盘狼藉 饺子店,是冬日里四面八方 ...