Reputation: 1094
I'd like to map over a property, so I tried
map(lambda o: cls.prop(o), list_of_objects)
The property is defined in an external library as:
@property
def prop(self):
However, I get a TypeError
error.
I tested it "unmapped", and cls.prop(an_object)
works just fine, as it should be, is equivalent to an_object.prop
.
What am I doing wrong? How could I achieve this?
(I'm aware list comprehension [o.prop for o in list_of_objects]
, but I want to learn and understand what went wrong above).
Upvotes: 5
Views: 11620
Reputation: 1121744
A property, accessed on the class, returns the property
object itself, and not the wrapped function. A property wraps three functions, the getter, setter and deleter (each of these can be None
):
>>> class Foo(object):
... @property
... def prop(self):
... return 'bar'
...
>>> Foo.prop
<property object at 0x107102bd8>
>>> Foo.prop.fget, Foo.prop.fset, Foo.prop.fdel
(<function Foo.prop at 0x1073366a8>, None, None)
You need to access the fget
attribute to get just the getter:
map(cls.prop.fget, list_of_objects)
Or, just access the attribute directly:
map(lambda o: o.prop, list_of_objects)
or use a operator.attrgetter()
object:
from operator import attrgetter
map(attrgetter('prop'), list_of_objects)
Using cls.prop.fget
or an attrgetter
have the advantage that the map()
C loop won't have to step back into the Python interpreter loop to execute the lambda
bytecode. Not that that matters much here, because the property getter implementation is still Python code.
Upvotes: 16