Home > OS >  Why I need to add a square bracket when I pass an instance as a parameter to class?
Why I need to add a square bracket when I pass an instance as a parameter to class?

Time:12-28

Below is my code:

class Person():
    def __init__(self,name):
        self.name=name
        self.pet=None
    def print_name(self):
        print(f"The person's name is {self.name}")

class Employee(Person):
    raise_amt=1.04
    def __init__(self,name,salary):
        super(Employee,self).__init__(name)
        self.salary=salary
    def apply_raise(self):
        self.salary=int(self.salary*self.raise_amt)

class Manager(Person):
    def __init__(self,name,salary,employees=None):
        super().__init__(name)
        self.salar=salary
        if employees==None:
            self.employees=[]
        else:
            self.employees=employees
    def add_emp(self,emp):
        if emp not in self.employees:
            self.employees.append(emp)
    def print_emps(self):
        for emp in self.employees:
            emp.print_name()

When I try to run the program with below code, the error will pop up.

frank=Employee("Frank",120000)
john=Employee("John",10000)
sean=Manager("Sean",20000,frank)
sean.add_emp(john)
sean.print_emps()

The error I receive is TypeError: argument of type 'Employee' is not iterable. However, when I put the square bracket around [frank], the error is gone. Can you help me to understand the reason?

CodePudding user response:

As others have said, in the Manager class __init__ method, you allow an optional list of Employees to be given. If this list is given then the Manager instance will set it as the employees variable else it will set an empty list. In your case, you are initializing the Manager class with an instance of Employee and not a list.

For the future...

I recommend a few code style changes to help avoid these kind of issues:

  • Add type annotations. This is not only great for you reading back your code, it enables linters to catch type errors before you run the code.
  • Add more whitespace. Add spaces between operators, variables, parameters, functions, etc. It makes reading the code much easier.
  • Use keyword arguments. In the example below, it's much easier to see what each argument is for and by extension, you can see employees is clearly a list.
from typing import Optional, List

class Manager(Person):

    def __init__(self, name: str, salary: int, employees: Optional[List[Employee]] = None):
        super().__init__(name)
        self.salary = salary
        if employees is None:
            self.employees = []
        else:
            self.employees = employees

    def add_emp(self, emp: Employee):
        if emp not in self.employees:
            self.employees.append(emp)

    def print_emps(self):
        for emp in self.employees:
            emp.print_name()

And then when you're calling the classes:

frank = Employee(name="Frank", salary=120000)
sean = Manager(name="Sean", salary=20000, employees=[frank])

CodePudding user response:

Python is expecting employees to be a list of items, not a single item. Adding the square brackets around "frank" turns it from a simple Employee object to a list of Employee objects, with the first item being "frank".

You have differing code between your __init__ and add_emp methods. In __init__, you set employees to the value specified (making it in your case an Employee object), whereas in add_emp you use append() to add the value to the existing values, maintaining the variable as a list.

Let's examine what your code actually does here:

  • First you create two instances of Employee with names (strings) and salaries (ints)
  • Then you create a Manager with a name, salary, and a single employee object assigned to self.employees
  • You then check if the "John" employee is in sean's employees variable, but sean's employees variable is not a list of employees, it's just a single employee (frank). You're checking if john is in frank, not if john is in a list of items that currently includes frank.

If you only want to pass a single employee when creating each manager the best fix would be to change your __init__ method as follows:

def __init__(self,name,salary,employees=None):
        super().__init__(name)
        self.salar=salary
        self.employees = []
        if employees:
            self.employees.append(employees)

If you want to pass in multiple employees, then do exactly as you are currently, pass a list e.g. [frank] not frank to the method.

  • Related