Reputation: 1597
I have the following Python 2.7 code:
from collections import namedtuple
Point = namedtuple('Point',['x','y'])
Point2 = namedtuple('Point2',['x','y'])
Point._revert = tuple
Point2._revert = lambda s: tuple(s)
for pointClass in [Point,Point2]:
instance = pointClass(x=10,y=20)
print "{} reverts to {}".format(instance,instance._revert())
The output is;
Point(x=10, y=20) reverts to ()
Point2(x=10, y=20) reverts to (10, 20)
So, what about the lambda is making the Point2._revert call work?
A simpler, standalone, example, requiring no imports:
class A(tuple):
fTuple = tuple
fLambda = lambda s: tuple(s)
a = A((1,2))
print repr(a.fTuple())
print repr(a.fLambda())
Upvotes: 1
Views: 73
Reputation: 1597
The brief answer is that the lambda implements the method __get__
:
>>> (lambda s: tuple(s)).__get__
<method-wrapper '__get__' of function object at 0x101a37b90>
See the descriptor documentation for what this means, but basically, when the value stored in an attribute has a __get__
method, reading that attribute returns the result of the __get__
method on the value, not the value itself.
So, in the code:
globalLambda = lambda s: tuple(s)
class A(object):
attrLambda = globalLambda
a = A()
print globalLambda # --> <function <lambda> at 0x102137b90>
print A.attrLambda # --> <unbound method A.<lambda>>
print a.attrLambda # --> <bound method A.<lambda> of <__main__.A object at 0x102134790>>
these are three different things.
Since tuple
is a type
object, it has no __get__
method, the access a.fTuple
just returns tuple
.
Upvotes: 1
Reputation: 13498
tuple
is a class, that does not require a parameter to be constructed.
Calling instance.tuple()
returns tuple()
which is just an empty tuple.
The difference with your anonymous function is that it is a function. When calling a class function from outside of the functional scope using instance.function()
, self
is automatically passed in as a parameter. Classes don't have this same treatment.
What's passed in is ._revert(instance)
, which calls tuple(instance)
which actually reverts your tuple.
from collections import namedtuple
Point = namedtuple('Point',['x','y'])
Point2 = namedtuple('Point2',['x','y'])
class test:
def __init__(self):
print(self)
def func(a):
print(a)
Point._revert = test
Point2._revert = func
instance = Point(x=10,y=20)
instance._revert()
>>><__main__.test object at 0x0000020ECAE1DFD0>
instance = Point2(x=10,y=20)
instance._revert()
>>>Point2(x=10, y=20)
Upvotes: 2