Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
135 views
in Technique[技术] by (71.8m points)

Python method-wrapper type?

What is the method-wrapper type in Python 3? If I define a class like so:

class Foo(object):
    def __init__(self, val):
        self.val = val
    def __eq__(self, other):
        return self.val == other.val

And then do:

Foo(42).__eq__

I get:

<bound method Foo.__eq__ of <__main__.Foo object at 0x10121d0>>

But if I do (in Python 3 ):

Foo(42).__ne__

I get:

<method-wrapper '__ne__' of Foo object at 0x1073e50>

What is a "method-wrapper" type?

Edit: sorry to be more accurate: class method-wrapper is the type of __ne__, as if I do:

>>> type(Foo(42).__ne__)
<class 'method-wrapper'>

Whereas the type of __eq__ is:

>>> type(Foo(42).__eq__)
<class 'method'>

Furthermore method-wrapper seems to be the type of any undefined magic method on a class (so __le__, __repr__, __str__ etc if not explicitly defined will also have this type).

What I am interested in is how the method-wrapper class is used by Python. Are all "default implementations" of methods on a class just instances of this type?

question from:https://stackoverflow.com/questions/10401935/python-method-wrapper-type

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

This is because 'unbound methods' don't exist in Python 3.

In Python 3000, the concept of unbound methods has been removed, and the expression "A.spam" returns a plain function object. It turned out that the restriction that the first argument had to be an instance of A was rarely helpful in diagnosing problems, and frequently an obstacle to advanced usages --- some have called it "duck typing self" which seems an appropriate name. (Source)

In Python 2.x, we had bound methods and unbound methods. A bound method was bound to an object, meaning that when it was called, it passed the object instance as the first variable (self, normally). An unbound method was one where the function was a method, but without a instance it belonged to - it would throw an error if something other than an object instance was passed in to the method.

Now, in 3.x, this has been changed. Instead of bound/unbound methods, when you request a method of an object, it returns the function object, but wrapped in a wrapper function that passes the instance variable in. This way there is no need to make a distinction between bound and unbound methods - bound methods are wrapped, unbound are not.

To clarify the difference:

2.x:

a = A()
f = A.method # f is an unbound method - you must pass an instance of `A` in to it as the first argument.
f = a.method # f is a bound method, bound to the instance `a`.

3.x:

a = A()
f = A.method # f is a function
f = a.method # f is a wrapped function with it's first argument filled with `a`.

a.method can be thought of as:

def method-wrapper():
    A.method(a)

For more on this, check out Guido's blog - the history of Python.

Edit:

So, the reason this all applies is that, here, __ne__() has not been overridden - it's at a default state, which is an identity check, implemented in C (line 980ish). The wrapper is there to provide the method with the above functionality.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...