1

I have tried using list and/or dictionaries to store the objects that I create, but my attempts have failed.

A reasons to use a list or a dictionary is to have python keep a reference to the object so as prevent the garbage collection component from discarding our object. My issues seems to be more with the initialization of the object itself, and with naming the object.

My script takes data out of a database and then automatically creates objects for each item in the list, in our case, employees.

Here is my class:

class Employee:
    empCount = 0

    def __init__(self, employee_id, name, age):
        self.employee_id = employee_id
        self.name = name
        self.age = age
        Employee.empCount += 1

    def display_employee_count(self):
        print("Total Employee %d" % Employee.empCount)

    def display_employee(self):
        print("Employee ID : ", self.employee_id,
              " First name : ", self.name,
              ' Age : ', self.age)

I know that to create an object I would call

joe1883 = Employee('joe1883', 'Joe', 21)

To display the objects attributes I would

joe1883.display_employee()

which yields:

Employee ID :  joe1883  First name :  Joe  Age :  21

My question is, how do I do this through a loop ?

# Data set has, employee id, first name, and age
my_list = [['joe1883', 'joe', 21],
           ['bob1492', 'bob', 22],
           ['frank1889','frank',34]]

for names in my_list:
    employee_id = names[0]
    name = names[1]
    age = names[2]

    #print("Employee ID : " + employee_id + " First name : " + name + ' Age : ' + str(age))

    # This is the line that creates my error !
    employee_id = Employee(employee_id, name, age)

If I insert this line into the loop statement

employee_id = Employee(employee_id, name, age)

And then call

joe1883 = Employee('joe1883', 'Joe', 21)

I get a #NameError: name 'joe1883' is not defined.

martineau
  • 119,623
  • 25
  • 170
  • 301
  • 2
    Are you sure you're showing the code exactly as-is? There doesn't appear to be anything wrong, aside from indentation in the provided code. In your very last line, you're showing that you did use quotes around 'joe1883'. The error you mentioned could suggest that you did not use the quotes in your actual code? – Aravinda Feb 22 '15 at 18:49
  • 1
    You *wouldn't* get `NameError` for the last. You *would* get `NameError` for `joe1883.display_employee()`. Please recheck your question and make sure that it has a clear problem statement. – Antti Haapala -- Слава Україні Feb 22 '15 at 18:49
  • 1
    Your example works fine. Are you sure you copied and pasted the exact case? From the error it looks like you are trying to run `joe1883 = Employee(joe1883, 'Joe', 21)` (without single quotes around joe1883). – Selcuk Feb 22 '15 at 18:49
  • The code works fine if I use : joe1883 = Employee('joe1883', 'Joe', 21) manually... I want the code to create objects automatically, by having ...: employee_id = Employee(employee_id, name, age) in the for loop, or some variation of code that allows for object initialization – Eduard Florea Feb 22 '15 at 18:56
  • When you place objects in a container, their "name" in it will depend on the type of container. For lists, it's an integer index between `0` and the `len()` of the list. For dictionaries, it's whatever key values are being associated with each entry -- so in your case you'd probably want to the use the employee id — which would allow you to randomly access `Employee` instances in the container with something like: `employee_dict['joe1883']` instead of `employee_list[index]` as would be needed for a list. I show doing it both ways in my answer. – martineau Feb 22 '15 at 20:49

3 Answers3

1

You need to keep a reference to an object around not just so it isn't garbage-collect, but also so you can reference it. The reference can be by giving it a variable name, like joe1883, or it can be by storing the object in a container, like a list or dictionary.

If you put it in a list, each element in the list can be reference with an integer index, such as employees[42]. To find an employee in such a container you will need to search through potentially all of them, by index, until you find the one you want.

If you want to find an employee quickly given their id, you should store them in a dictionary instead, then you could do something like employees['joe1883'] to directly access one of them.

Since you don't know kind of container an Employee instance will be put in, if any, it makes little sense to keep an empCount in the class. If you put a bunch of them in a list or dictionary, and ever need to know how many, you can find that by using the built-in len() function on the container object, i.e. len(employee_list) or len(employee_dict).

class Employee:
    def __init__(self, id, name, age):
        self.id = id
        self.name = name
        self.age = age

    def display(self):
        print("Employee ID : ", self.id, 
              " First name : ", self.name, 
              ' Age : ', self.age)

# create a single employee object and name it joe1883
joe1883 = Employee('joe1883', 'Joe', 21)
joe1883.display()

# now create a list of employees by converting dataset
# my_list into a list of Employee instances named employees

# dataset
my_list = [
    ['joe1883', 'joe', 21],
    ['bob1492', 'bob', 22],
    ['frank1889','frank', 34],
]

employees = [Employee(item[0], item[1], item[2]) for item in my_list]

# display each employee in list
for employee in employees:
    employee.display()

# or you could do it this (non-pythonic) way:
for i in range(len(employees)):
    employees[i].display()

# to print an employee with a given id
# you'd need to search for it in the list
for employee in employees:
    if employee.id == 'joe1883':
        employee.display()
        break  # found, so stop loop

# Here's how to create a dictionary of employees by converting dataset
# my_list into Employee instances keyed by their id
employees = {item[0]: Employee(item[0], item[1], item[2]) for item in my_list}

# look one of them up
if 'joe1883' in employees:
    employees['joe1883'].display()
martineau
  • 119,623
  • 25
  • 170
  • 301
0

If I understand your question correctly, you are trying to create a set of objects-employees based on the list with the arguments for each of the objects.

I modified/simplified your code a little bit and this is working fine:

class Employee:
    empCount = 0

    def __init__(self, employee_id, name, age):
        self.employee_id = employee_id
        self.name = name
        self.age = age
        Employee.empCount += 1

    def display_employee_count(self):
        print("Total Employee %d" % Employee.empCount)

    def display_employee(self):
        print("Employee ID : {0} First name : {1} Age : {2}".format(self.employee_id, self.name,self.age))

my_list = [('joe1883', 'joe', 21), ('bob1492', 'bob', 22), ('frank1889', 'frank', 34)] # in this format arguments will be easier to pass as parameters to your class constructor

list_of_employees = [] # list where you can  put created objects

for emp in my_list:
    list_of_employees.append(Employee(*emp)) # now you just pass your tuple of arguments like that

for emp in list_of_employees: #looping through the list with objects you created and printing results    
    emp.display_employee() 
Dinara
  • 41
  • 2
0

@eduard You are doing 2 things wrong.

  • 1) the indentation is bad, so the methods of the class Employee are not inside the class.
  • 2) You are not storing the objects anywhere.

Id suggest you to do it in this way:

employ_dic={}

class Employee:

    def __init__(self, employee_id, name, age):
       self.employee_id = employee_id
       self.name = name
       self.age = age

       employ_dic[employee_id]=self


    def display_employee(self):
        print '''Employee ID: {0}, First Name: {1}, Age: {2}'''.format(self.employee_id, self.name, self.age)


lists = [['joe1883', 'joe', 21],['bob1492', 'bob', 22],['frank1889','frank',34]]

for list in lists:
    employee_id = Employee(list[0], list[1], list[2])



employ_dic['joe1883'].display_employee()

# to display the count:

print len(employ_dic)