将内置函数类型转换为方法类型(在Python 3中) [英] Convert builtin function type to method type (in Python 3)

查看:141
本文介绍了将内置函数类型转换为方法类型(在Python 3中)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑一个简单的函数,例如

Consider a simple function like

def increment(self):
    self.count += 1

它通过Cython运行并编译为扩展模块。现在假设我想将此函数作为类的方法。例如:

which is run through Cython and compiled into an extension module. Suppose now I'd like to make this function a method on a class. For example:

class Counter:
    def __init__(self):
        self.count = 0

from compiled_extension import increment
Counter.increment = increment

现在这将不起作用,因为C级别的调用约定将被破坏。例如:

Now this will not work, as the calling convention at the C level will be broken. For example:

>>> c = Counter()
>>> c.increment()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: increment() takes exactly one argument (0 given)

但是在Python 2中,我们可以通过执行以下操作将函数转换为非绑定方法:

But in Python 2, we can convert the function to an unbound method by doing:

Counter.increment = types.MethodType(increment, None, Counter)

我如何在Python 3中完成同样的事情?

一种简单的方法是使用超薄包装:

One simple way is to use a slim wrapper:

from functools import wraps
def method_wraper(f):
    def wrapper(*args, **kwargs):
        return f(*args, **kwargs)
    return wraps(f)(wrapper)

Counter.increment = method_wrapper(increment)

是否有

推荐答案

首先要正确获取名称:

>>> def increment(obj):
...     obj.count += 1
...
>>> class A(object):
...     def __init__(self):
...         self.count = 0
...
>>> o = A()
>>> o.__init__
<bound method A.__init__ of <__main__.A object at 0x0000000002766EF0>>
>>> increment
<function increment at 0x00000000027797C8>

所以专有名称是函数绑定方法。现在,您可以查找如何 绑定未绑定方法 ,您可能最终会阅读有关 描述符

So proper names are functions and bound methods. Now you can look for how to Bind an Unbound Method and you will probably end up reading about descriptors:


通常,描述符是具有绑定
行为的对象属性,该描述符的属性访问已被描述符中的方法
覆盖协议。这些方法是 __ get __ __ set __
__ delete __ 。如果为对象定义了这些方法中的任何一个,则称其为描述符。

In general, a descriptor is an object attribute with "binding behavior", one whose attribute access has been overridden by methods in the descriptor protocol. Those methods are __get__, __set__, and __delete__. If any of those methods are defined for an object, it is said to be a descriptor.

您可以通过以下方式轻松地将函数转换为方法只是使用 __ get __

You can easily transform function to method by just using different invocation of __get__

>>> increment.__get__(None, type(None))
<function increment at 0x00000000027797C8>
>>> increment.__get__(o, type(o))
<bound method A.increment of <__main__.A object at 0x00000000027669B0>>

它就像一种魅力:

>>> o = A()
>>> increment.__get__(None, type(None))(o)
>>> o.count
1
>>> increment.__get__(o, type(o))()
>>> o.count
2

您可以轻松地添加这些新边界方法到对象:

You can easily add these newly bounded methods to objects:

def increment(obj):
    obj.count += 1

def addition(obj, number):
    obj.count += number

class A(object):
    def __init__(self):
        self.count = 0

o = A()
o.inc = increment.__get__(o)
o.add = addition.__get__(o)
print(o.count) # 0
o.inc()
print(o.count) # 1
o.add(5)
print(o.count) # 6

或者创建自己的描述符,它将转换功能绑定方法

Or create your own descriptor that will will convert function to bound method:

class BoundMethod(object):
    def __init__(self, function):
        self.function = function

    def __get__(self, obj, objtype=None):
        print('Getting', obj, objtype)
        return self.function.__get__(obj, objtype)

class B(object):
    def __init__(self):
        self.count = 0

    inc = BoundMethod(increment)
    add = BoundMethod(addition)


o = B()
print(o.count) # 0
o.inc()
# Getting <__main__.B object at 0x0000000002677978> <class '__main__.B'>
print(o.count) # 1
o.add(5) 
# Getting <__main__.B object at 0x0000000002677978> <class '__main__.B'>
print(o.count) # 6

您也可以看到这很好与 function / 一致绑定方法原理

And you also can see that this is nicely consistent with function/bound method principles:


类词典将方法存储为函数。在类定义中,使用def和lambda(创建函数的常用工具)编写方法。与常规函数的唯一区别是第一个参数是为对象实例保留的。按照Python约定,实例引用称为self,但可以称为此引用或任何其他变量名称。

Class dictionaries store methods as functions. In a class definition, methods are written using def and lambda, the usual tools for creating functions. The only difference from regular functions is that the first argument is reserved for the object instance. By Python convention, the instance reference is called self but may be called this or any other variable name.

为支持方法调用,函数包括 __get __()方法,用于在属性访问期间绑定方法。这意味着所有函数都是非数据描述符,它们返回绑定或非绑定方法,具体取决于它们是从对象还是从类调用。

To support method calls, functions include the __get__() method for binding methods during attribute access. This means that all functions are non-data descriptors which return bound or unbound methods depending whether they are invoked from an object or a class.

功能在实例初始化期间成为绑定方法

And functions becomes bound method during instance initialization:

>>> B.add
# Getting None <class '__main__.B'>
<function addition at 0x00000000025859C8>
>>> o.add
# Getting <__main__.B object at 0x00000000030B1128> <class '__main__.B'>
<bound method B.addition of <__main__.B object at 0x00000000030B1128>>

这篇关于将内置函数类型转换为方法类型(在Python 3中)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆