本文介绍了将内置函数类型转换为方法类型(在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 __

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

您也可以看到这很好与:

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

为支持方法调用,函数包括 __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中)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-05 10:43