设为首页收藏本站

LUPA开源社区

 找回密码
 注册
文章 帖子 博客
LUPA开源社区 首页 业界资讯 技术文摘 查看内容

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

2013-8-19 14:57| 发布者: 红黑魂| 查看: 2266| 评论: 0|来自: 开源中国

摘要: 如果现代Python有一个标志性特性,那么简单说来便是Python对自身定义的越来越模糊。在过去的几年的许多项目都极大拓展了Python,并重建了“Python”本身的意义。与此同时新技术的涌现侵占了Python的份额,并带来了新 ...


接口

分解行为到可组合的单元,而不是显式的继承层次结构是一个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))

英文原文:Navigating the Postmodern Python World

参与翻译(4人)袁不语小pandaGarfieltyale8848

本文转自:开源中国社区 [http://www.oschina.net]
本文标题:飞跃式发展的后现代 Python 世界
本文地址:
http://www.oschina.net/translate/postmodern-python


酷毙
2

雷人

鲜花
1

鸡蛋

漂亮

刚表态过的朋友 (3 人)

  • 快毕业了,没工作经验,
    找份工作好难啊?
    赶紧去人才芯片公司磨练吧!!

最新评论

关于LUPA|人才芯片工程|人才招聘|LUPA认证|LUPA教育|LUPA开源社区 ( 浙B2-20090187 浙公网安备 33010602006705号   

返回顶部