A Sz
A Sz

Reputation: 1094

Apply `map` over property in python

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

Answers (1)

Martijn Pieters
Martijn Pieters

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

Related Questions