【问题标题】:python catching functionspython捕捉函数
【发布时间】:2012-06-27 20:09:28
【问题描述】:

我编写了以下有效的代码。

from operator import mul
from operator import truediv #python 3.2

class Vec(list):

    def __mul__(self, other):
        return Vec(map(mul, self, other))

    def __truediv__(self, other):
        return Vec(map(truediv, self, other))


>>> xs = Vec([1,2,3,4,5])
>>> ys = Vec([4,5,6,7,4])
>>> zs = xs * ys
>>> zs.__class__
<class 'vector.Vec'>
>>> zs
[4, 10, 18, 28, 20]

但是是否可以创建这样的东西:

class Vec(list):

    allowed_math = [__add__, __mul__, __truediv__, __subtract__] # etc

    def __catchfunction__(self, other, function):
        if function in allowed_math:
            return Vec(map(function, self, other))

澄清一下,这不是我试图重新创建 NumPy,我只是想了解如何使用 Python。

【问题讨论】:

    标签: python function operator-keyword


    【解决方案1】:

    达到预期效果的一个选项是:

    class Vec(list):
        pass
    
    functions = {"__add__": operator.add,
                 "__mul__": operator.mul,
                 "__truediv__": operator.truediv,
                 "__sub__": operator.sub}
    for name, op in functions.iteritems():
        setattr(Vec, name, lambda self, other, op=op: Vec(map(op, self, other)))
    

    请注意,op=op 参数对于避免 lambda 函数成为 op 的闭包是必要的。

    不过,使用 NumPy 可能会好得多——它提供了比在纯 Python 中自己创建的更通用和更高效的数值数组实现。

    【讨论】:

    • apropos NumPy,完全同意,但这更多是我思考如何做到这一点的问题。
    • 我很确定实现__getattr__ 将不起作用; __methods__ 绕过正常的属性查找以提高效率,不能以这种方式陷入困境。
    • 那么您的建议是创建一个包含我想要包含的所有函数的字典,然后使用单个函数来设置所有类的属性?所以一个类真的不能“看到”什么函数被传递给它?还是我的意思是课程正在传递给?
    • @MattAnderson:你说得对——因为我们派生自list,所以我们得到了一个新式类。
    • @ThemanontheClaphamomnibus:代码没有为所有特殊方法使用一个函数——它为每个方法动态创建一个新函数。特殊方法内部存储在每个操作的“槽”中。如果两个对象要相乘,Python 会在第一个对象的类型对应的槽中查找乘法函数。分配给类型的__mul__ 属性会隐式更新此槽。这也是__getattr(ibute)__() 方法不起作用的原因。
    【解决方案2】:

    要知道的重要一点是每个http://docs.python.org/reference/datamodel.html#new-style-special-lookuphttp://docs.python.org/dev/reference/datamodel.html#special-method-lookup 用于 Python 3):

    对于自定义类,特殊方法的隐式调用只有在对象类型上定义时才能保证正常工作,而不是在对象的实例字典中。 ... 隐式特殊方法查找通常也会绕过对象元类的__getattribute__() 方法。

    因此,通过特殊方法名称实现运算符重载的唯一方法是在类上定义它们(内联或以编程方式创建类之后)。

    有关更多详细信息和示例,请参阅http://code.activestate.com/recipes/577812-see-how-__getattribute__-interacts-with-special-me/。另请参阅 Overriding special methods on an instance 了解相关问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-04-04
      • 1970-01-01
      • 2013-05-20
      • 2016-09-26
      • 1970-01-01
      • 2017-07-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多