【问题标题】:Why I need to add a square bracket when I pass an instance as a parameter to class?为什么在将实例作为参数传递给类时需要添加方括号?
【发布时间】:2021-12-27 22:57:02
【问题描述】:

下面是我的代码:

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()

当我尝试使用以下代码运行程序时,会弹出错误。

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

我收到的错误是TypeError: argument of type 'Employee' is not iterable。 但是,当我将方括号放在[frank] 周围时,错误就消失了。 你能帮我理解原因吗?

【问题讨论】:

  • 你用一个 frank 的员工列表初始化 Manager,但 frank 不是一个列表,它是一个员工。
  • 一个 Employee 确实是不可迭代的。一个列表
  • 附注,请使用if employees is None 而不是== - relevant question

标签: python class debugging


【解决方案1】:

正如其他人所说,在Manager__init__ 方法中,您允许给出Employees 的可选列表。如果给出了这个列表,那么Manager 实例会将其设置为employees 变量,否则它将设置一个空列表。在您的情况下,您正在使用 Employee 的实例而不是列表来初始化 Manager 类。

为了未来……

我建议对代码样式进行一些更改,以帮助避免此类问题:

  • 添加类型注释。这不仅有助于您回读代码,还可以让 linter 在您运行代码之前捕获类型错误。
  • 添加更多空格。在运算符、变量、参数、函数等之间添加空格,让阅读代码更容易。
  • 使用关键字参数。在下面的示例中,可以更轻松地查看每个参数的用途,并且通过扩展,您可以看到 employees 显然是一个列表。
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()

然后当你调用类时:

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

【讨论】:

  • 您也可以简化:self.employees = [] if employees is None else employees。随意添加。
  • 您还应该显示您从哪里导入了这些名称 [类型提示](考虑到某些人可能不清楚),也使用 Optional[List[Employee]] 似乎有点矫枉过正 IMO(尤其是对于初学者)一个简单的list 就足够了,但肯定会更好
【解决方案2】:

Python 期望 employees 是一个项目列表,而不是单个项目。在“frank”周围添加方括号会将其从简单的 Employee 对象转换为 Employee 对象列表,其中第一项是“frank”。

__init__add_emp 方法之间的代码不同。在__init__ 中,您将employees 设置为指定的值(在您的情况下使其成为Employee 对象),而在add_emp 中,您使用append() 将值添加到现有值中,将变量维护为列表。

让我们检查一下您的代码在这里实际做了什么:

  • 首先,您使用名称(字符串)和薪水(整数)创建两个 Employee 实例
  • 然后您创建一个经理,其名称、薪水和分配给self.employees 的单个员工对象
  • 然后您检查“John”员工是否在 sean 的员工变量中,但 sean 的员工变量不是员工列表,它只是一个员工 (frank)。您正在检查 john 是否在 frank,而不是 john 是否在当前包含 frank 的项目列表中

如果您只想在创建每个经理时传递一个员工,最好的解决方法是更改​​您的 __init__ 方法,如下所示:

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

如果你想传递多个员工,那么就按照你现在的方式做,传递一个列表,例如[frank] 不是 frank 到方法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-01-03
    • 2022-08-23
    • 2022-01-05
    • 2020-01-26
    • 1970-01-01
    • 1970-01-01
    • 2011-03-14
    • 1970-01-01
    相关资源
    最近更新 更多