Python 从员工字典打印员工对象信息

Python 从员工字典打印员工对象信息,python,python-3.x,dictionary,Python,Python 3.x,Dictionary,我试图从雇员对象字典中打印雇员对象信息,而不使用for循环。以下是我迄今为止所做的工作: employee_dict = {} class Employee: def __init__(self, id, salary): self.id = id self.salary = salary self.employee_dictionary(self) def info(self): return "Employee ID:{} \nSalary:{}

我试图从雇员对象字典中打印雇员对象信息,而不使用for循环。以下是我迄今为止所做的工作:

employee_dict = {}

class Employee:

  def __init__(self, id, salary):
    self.id = id
    self.salary = salary
    self.employee_dictionary(self)

  def info(self):
    return "Employee ID:{} \nSalary:{}".format(self.id, self.salary)

  def employee_dictionary(self):
    employee_dict = {self.id: self}

emp = Employee(1, 10)
emp1 = Employee(2, 5)

employee = employee_dict[1]

print(employee.info())
有人能给我指出正确的方向吗?我觉得我很亲近。此代码给我的错误是:

Traceback (most recent call last):
  File "/home/rob/PycharmProjects/untitled4/sdfghsfdgjrtyrty.py", line 19, in <module>
    employee = employee_dict[1]
KeyError: 1
回溯(最近一次呼叫最后一次):
文件“/home/rob/PycharmProjects/untitled4/sdfghsfdgjrtyrty.py”,第19行,在
employee=employee_dict[1]
关键错误:1

这是一个范围问题
employee_dict={}
的行为与您想象的不一样

您没有在正确的范围内赋值。因此,您从未实际向其添加
员工。这会导致
键错误

在您的案例中,您所寻找的可能是使用一个类变量

class Employee:
    employee_dict = {}
    def __init__(self, id, salary):
        self.id = id
        self.salary = salary
        self.employee_dictonary(self)

    def info(self):
        return "Employee ID:{} \nSalary:{}".format(self.id, self.salary)

    @classmethod
    def employee_dictonary(cls,current_employee):
        cls.employee_dict[current_employee.id]=current_employee

emp = Employee(1, 10)
emp1 = Employee(2, 5)

print(Employee.employee_dict[1].info())
基本上,为了便于解释,您正在创建一个
employee\u dict
,它将在employee的所有实例中共享

还有,你必须记住的最后一件事是,如果有人像这样创造了两名员工

emp = Employee(1, 10)
emp2 = Employee(1, 100)
调用
print(Employee.Employee\u dict[1].info())
将输出

Employee ID:1 
Salary:100

这可能是您想要的,但仍然认为强调员工可以被覆盖是相关的。

您应该将员工定义为
全局

def employee_dictonary(self):
  global employee_dict
如果没有全局关键字,则指定给局部变量

第二个问题是使用
employee_dict={self.id:self}
分配给
employee_dict
。这样,每次调用都会覆盖变量。该行应该是
employee\u dict[self.id]=self

通过该更改,输出为:

Employee ID:1 
Salary:10

在大多数情况下,强烈反对使用全局变量,请参阅。

这里的根本问题是您没有正确使用字典。您不是将新员工添加到现有的全局员工目录中,而是尝试将该全局目录替换为新目录,仅包含新员工:

def employee_dictionary(self):
  employee_dict = {self.id: self}
如果你解决了这个问题,你实际上要问的问题甚至不会出现:

def employee_dictionary(self):
  employee_dict[self.id] = self
这将在dict中添加一个从
self.id
self
的新映射。因此,在您的两个
Employee
构造之后,使用id 1和id 2,您将在dict中得到两个条目,用于键
1
2
,一切都将正常工作


也应该至少考虑一下另外两个变化:

  • 用class属性替换全局变量,也可能用class方法替换
    employee\u dictionary
    方法,如中所述
  • 将方法从
    employee\u dictionary
    重命名为(a)标记为private(按惯例以
    \u
    开头的方法是private的,这意味着您的用户知道他们不应该调用它,除非他们有一个奇怪的用例),以及(b)更能反映它的功能。可能是
    \u寄存器
    \u添加到dict
第一个问题(同样,在scharette的回答中有详细说明)也会使你所问的问题消失。(但您仍然需要主修复程序。)


但您可能想了解更直接的范围问题,以及当您无法解决它时如何解决它

在Python中,在函数中指定的任何名称都是局部变量。如果函数中的任何地方都有一个
spam=…
(或者一个
带有鸡蛋作为spam:
或者其他类型的东西,当然也算是赋值),那么该函数中对
spam
的每一个引用都指向该本地。因此,
employee_dict={self.id:self}
创建一个名为
employee_dict
的局部变量,给它赋值,然后返回,此时所有的局部变量都消失了。它恰好与全局名称相同,这一事实对Python来说并不意味着什么(尽管对于像您这样的人类读者来说,这显然令人困惑)

您使用的任何名称都是局部变量、封闭变量、全局变量或内置变量,而不在任何位置为其赋值。当您执行
employee_dict[self.id]
时,因为任何地方都没有
employee_dict=…
,Python会搜索本地、封闭、全局和内置作用域,以查找您所指的
employee_dict
,并找到全局

您可以强制Python将名称视为全局变量,即使您为其赋值,也可以在函数顶部使用
global
语句:

def employee_dictionary(self):
  global employee_dict
  employee_dict = {self.id: self}
添加
global
是安全的,即使名称已经是全局名称。这通常是毫无意义的,但如果您不确定某个内容是否算作赋值(或者只是不确定代码的未来读者是否会确定…),并且您希望明确该变量是全局变量,则可以声明它:

def employee_dictionary(self):
  global employee_dict
  employee_dict[self.id] = self

你在这个问题上的缩进正确吗?如中所示,它表示您正在使用什么?您几乎肯定希望在这里使用的是
employee_dict[self.id]=self
,而不是
employee_dict={self.id:self}
。您希望将此员工添加到字典中,而不是将字典替换为仅处理此员工的字典,对吗?如果是这样,那就意味着你的另一个问题,即与局部变量和全局变量相关的问题,不会首先出现,因此你不需要解决它。使用
global
来解决这个问题并不是一个很强的建议,事实上,无论函数是否缩进为类主体的一部分,它都不能解决这个问题。你可以在本地测试。是的,它现在可以工作了。您最初的回答中没有
employee_dict[self.id]=self
。编辑后,这会产生误导。一旦您将
employee_dict={self.id:self}修改为
employee_dict[self.id]=self
,OP就不再将其声明为全局,也不再使用