Python的最佳维护通用函数实现是什么?

joe*_*ker 8 python generics

一个通用的功能是基于其所有参数的类型出动.程序员定义了函数的几种实现.在调用时根据其参数的类型选择正确的一个.这对于对象适应等很有用.Python有一些通用函数,包括len().

这些包往往允许代码如下所示:

@when(int)
def dumbexample(a):
    return a * 2

@when(list)
def dumbexample(a):
    return [("%s" % i) for i in a]

dumbexample(1) # calls first implementation
dumbexample([1,2,3]) # calls second implementation
Run Code Online (Sandbox Code Playgroud)

我最近一直在考虑的一个不那么愚蠢的例子是需要用户的Web组件.集成商不需要特定的Web框架,只需编写如下内容:

class WebComponentUserAdapter(object):
    def __init__(self, guest):
        self.guest = guest
    def canDoSomething(self):
        return guest.member_of("something_group")

@when(my.webframework.User)
componentNeedsAUser(user):
    return WebComponentUserAdapter(user)
Run Code Online (Sandbox Code Playgroud)

Python有一些通用的函数实现.为什么我会选择其中一个呢?如何在应用程序中使用该实现?

我对Zope很熟悉zope.component.queryAdapter(object, ISomething).程序员注册一个可调用的适配器,该适配器将特定类的对象作为其参数,并返回与接口兼容的东西.这是允许插件的有用方法.与猴子修补不同,即使对象需要使用相同的方法名称来适应多个接口,它也能工作.

Dir*_*irk 7

我推荐P. Eby 的PEAK规则库.同一作者(虽然已弃用)是RuleDispatch包(PEAK-Rules的前身).后者不再维持IIRC.

PEAK-Rules有许多不错的功能,其中之一就是(好,不容易,但是)可扩展.除了onty类型的"经典"调度之外,它还将任意表达式的调度称为"监护人".

len()函数不是一个真正的泛型函数(至少在上面提到的包的意义上,在某种意义上,这个术语在Common Lisp,DylanCecil等语言中使用),因为它只是一个方便的语法调用特别命名(但其他常规)方法:

len(s) == s.__len__()
Run Code Online (Sandbox Code Playgroud)

另请注意,这只是单一调度,即实际接收器(s在上面的代码中)确定调用的方法实现.甚至是一个假设

def call_special(receiver, *args, **keys):
    return receiver.__call_special__(*args, **keys)
Run Code Online (Sandbox Code Playgroud)

仍然是单调度函数,因为在解析要调用的方法时仅使用接收器.其余的参数只是传递,但它们不会影响方法选择.

这与多分派不同,其中没有专用接收器,并且所有参数都用于查找要调用的实际方法实现.这就是实际上使整个事情变得有价值的东西.如果它只是一些奇怪的语法糖,没有人会打扰使用它,恕我直言.

from peak.rules import abstract, when

@abstract
def serialize_object(object, target):
    pass

@when(serialize_object, (MyStuff, BinaryStream))
def serialize_object(object, target):
    target.writeUInt32(object.identifier)
    target.writeString(object.payload)

@when(serialize_object, (MyStuff, XMLStream))
def serialize_object(object, target):
    target.openElement("my-stuff")
    target.writeAttribute("id", str(object.identifier))
    target.writeText(object.payload)
    target.closeElement()
Run Code Online (Sandbox Code Playgroud)

在这个例子中,一个叫做的话

serialize_object(MyStuff(10, "hello world"), XMLStream())
Run Code Online (Sandbox Code Playgroud)

考虑两个参数以决定实际必须调用哪个方法.

对于Python中泛型函数的一个很好的使用场景,我建议阅读重构的代码,peak.security它为使用泛型函数(使用RuleDispatch)访问权限检查提供了一个非常优雅的解决方案.