5

I declare a class Employee and a list consist of it:

class Employee():
    def __init__(self, _name):
        self.name = _name
    def get_name(self):
        return self.name

Tom   = Employee("Tom")
Karl  = Employee("Karl")
John  = Employee("John")

employee_list = [Tom, Karl, John]

Now I want to have a list of their name by applying get_name in a map:

name_list = map(get_name, employee_list)


Traceback (most recent call last): File "ask.py", line 13, in <module> 
    name_list = map(get_name, employee_list) 
NameError: name 'get_name' is not defined

How could get_name be not defined?

How do I do to apply member function in a map?

Mazdak
  • 100,514
  • 17
  • 155
  • 179

5 Answers5

3

map(get_name, employee_list)in your code is equivalent to

[get_name(employee) for employee in employee_list]

not [employee.get_name() for employee in employee_list]

You should declare a get_name method outside of Employee class:

def get_name(employee):
    return employee.name

or an easier way with Lambda:

name_list = map(lambda employee: employee.name, employee_list)

Rahn
  • 4,528
  • 4
  • 25
  • 50
2

You have to call the method from the instance. You can use a lambda for this

name_list = map(lambda e: e.get_name(), employee_list)
salomonderossi
  • 2,072
  • 11
  • 20
2

This should be done using a list comprehension:

names = [employee.get_name() for employee in employee_list]

Additionally, I would suggest you to shorten the way you create the employee_list as well by not assigning intermediate variable names, but directly creating the instances inside the list literal:

employee_list = [Employee("Tom"), Employee("Karl"), Employee("John")]

This could be further shortened by using a list comprehension again:

employee_list = [Employee(name) for name in ("Tom", "Karl", "John")]
Byte Commander
  • 5,981
  • 4
  • 37
  • 66
2

While all other answers are correct, all miss one particular feature of python: "instance method" can be called in a "class method" manner, passing class instance as a first parameter. So (at least in python2.7), the following works just fine:

map(Employee.get_name, employee_list)

Refer to this SO question for some details on why and how it works.

Community
  • 1
  • 1
J0HN
  • 25,158
  • 5
  • 48
  • 84
0

map calls a function, but get_name() is a method. If you really want to use map then you can take advantage of the way that Python implements methods: they are equivalent to calling the function as an unbound method with the object as the first self argument:

name_list = map(Employee.get_name, employee_list)

To access the method without binding it to a specific instance you need to access through on the class. Note that this won't work correctly if you have a variety of subclasses of Employee and get_name is overridden.

The more Pythonic way is, as others have said, to use a list comprehension, but if you want to go 'Pythonic' then you shouldn't be using an accessor method at all: you should just be accessing the name attribute for a simple value like this, or turn it into a property if you need more complex access:

names = [employee.name for employee in employee_list]
Duncan
  • 86,487
  • 10
  • 115
  • 155