简体   繁体   English

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

[英]Printing employee object information from a dictionary of employees

I am attempting to print employee object information from a dictionary of employee objects without using a for loop. 我试图从员工对象的字典中打印员工对象信息,而不使用for循环。 Here is what I have done so far: 这是我到目前为止所做的:

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

Could someone point me in the right direction? 有人能指出我正确的方向吗? I feel like I am close. 我觉得我很亲密。 The error this code gives me is: 这段代码给我的错误是:

Traceback (most recent call last):
  File "/home/rob/PycharmProjects/untitled4/sdfghsfdgjrtyrty.py", line 19, in <module>
    employee = employee_dict[1]
KeyError: 1

The underlying problem here is that you're not using the dictionary right. 这里的根本问题是你没有正确使用字典。 Instead of adding the new employee to the existing global employee_dict , you're trying to replace that global dict with a new one, containing just the new employee: 您没有将新员工添加到现有的全局employee_dict ,而是尝试将新的员工替换为新的员工,只包含新员工:

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

If you fix this, the problem you're actually asking about won't even come up: 如果你解决这个问题,你实际问的问题甚至都不会出现:

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

This will add a new mapping from self.id to self in the dict. 这将在dict中添加从self.idself的新映射。 So, after your two Employee constructions, with IDs 1 and 2, you'll end up with two entries in the dict, for keys 1 and 2 , and everything will just work. 因此,在您的两个Employee构造之后,ID为1和2,您将在dict中得到两个条目,对于键1和键2 ,一切都将正常工作。


Also, you should definitely at least consider two other changes: 此外,你绝对应该至少考虑另外两个变化:

  • Replace the global variable with a class attribute, and possibly also replace the employee_dictionary method with a class method, as detailed in scharette's answer . 用class属性替换全局变量,并且可能还用class方法替换employee_dictionary方法,详见scharette的答案
  • Rename the method from employee_dictionary to something (a) marked private (methods starting with _ are private by convention, meaning your users know they aren't supposed to be calling it unless they have a weird use case), and (b) more reflective of what it does. employee_dictionary的方法重命名为(a)标记为private的方法(以_开头的方法按惯例是私有的,这意味着您的用户知道他们不应该调用它,除非他们有一个奇怪的用例),并且(b)更具反思性它的作用。 Maybe _register or _add_to_dict ? 也许_register_add_to_dict

The first one of these would also (as, again, detailed in scharette's answer) have made the problem you're asking about go away. 这些中的第一个( 就是scharette的回答中详细说明)已经让你问的问题消失了。 (But you still need the main fix anyway.) (但你仍然需要主要修复。)


But you probably want to understand the more immediate scope problem anyway—and how to solve it when you can't just make it go away. 但是你可能想要了解更直接的范围问题 - 以及当你不能让它消失时如何解决它。

In Python, any name that you assign to in a function is a local variable. 在Python中,您在函数中指定的任何名称都是局部变量。 If there's a spam = … anywhere in the function (or a with eggs as spam: or certainly other kinds of things that also count as assignment), every reference to spam in that function is to that local. 如果在函数中的任何地方都有spam = … (或者将with eggs as spam:或者其他类似的东西也算作分配),那么该函数中对spam每次引用都是针对本地的。 So, employee_dict = {self.id: self} creates a local variable named employee_dict , assigns a value to it, and then returns, at which point all the locals go away. 因此, employee_dict = {self.id: self}创建一个名为employee_dict的局部变量,为其赋值,然后返回,此时所有本地人都会消失。 The fact that it happens to have the same name as a global doesn't mean anything to Python (although to a human reader, like you, it's obviously confusing). 它恰好与全局同名的事实对Python来说没有任何意义(尽管对于像你这样的人类读者来说,它显然令人困惑)。

Any name that you use without assigning to it anywhere is a local-or-enclosing-or-global-or-builtin variable. 您在不在任何地方分配的任何名称都是本地或封闭或全局或内置变量。 When you do employee_dict[self.id] , because there's no employee_dict = … anywhere, Python searches the local, enclosing, global, and builtin scopes to find what you meant by employee_dict , and it finds the global. 当你执行employee_dict[self.id] ,因为在任何地方都没有employee_dict = … ,Python搜索本地,封闭,全局和内置范围以查找employee_dict含义,并找到全局。

You can force Python to treat a name as a global variable, even if you assign to it, with a global statement at the top of the function: 您可以强制Python将名称视为全局变量,即使您使用函数顶部的global语句分配给它也是如此:

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

Adding global is safe even if the name would already be a global. 即使名称已经是全局名称,添加global也是安全的。 This is usually pointless—but if you're not sure whether something counts as an assignment (or just not sure future readers of your code would be sure…), and you want to make it clear that the variable is a global, you can declare it: 这通常是毫无意义的 - 但是如果你不确定某些东西是否算作一个任务(或者只是不确定你的代码的未来读者是否确定......),并且你想明确该变量是全局的,你可以声明:

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

This is a scope problem . 这是一个范围问题 employee_dict = {} is not acting like you think. employee_dict = {}并不像你想象的那样。

You're not assigning the value in the right scope. 您没有在正确的范围内分配值。 Therefore, you're never actually adding an Employee to it. 因此,您实际上从未向其中添加Employee Which cause the KeyError . 这导致KeyError

What you are looking for in your case is probably using a class variable like so, 在你的情况下你正在寻找的可能是使用这样的类变量

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

Basically, for the sake of explanation, you're creating a employee_dict which will be share among all instances of Employee. 基本上,为了便于解释,您创建的employee_dict将在Employee的所有实例之间共享。

Also, there's one last thing you have to keep in mind is if someone create 2 employee like so, 此外,还有一件事要记住,如果有人像这样创造2名员工,

emp = Employee(1, 10)
emp2 = Employee(1, 100)

calling print(Employee.employee_dict[1].info()) will output 调用print(Employee.employee_dict[1].info())将输出

Employee ID:1 
Salary:100

which is probably what you want, but still thought it was relevant to underline that an employee can be overridden. 这可能是你想要的,但仍然认为强调员工可以被覆盖是相关的

You should define employee_dict as global : 您应该将employee_dict定义为全局

def employee_dictonary(self):
  global employee_dict

Without the global keyword you are assigning to local variable. 没有您分配给局部变量的全局关键字。

The second problem is using employee_dict = {self.id: self} for assigning to employee_dict . 第二个问题是使用employee_dict = {self.id: self}来分配employee_dict With that, you overwriting the variable with each call. 这样,您可以在每次调用时覆盖变量。 That line should be employee_dict[self.id] = self . 该行应该是employee_dict[self.id] = self

With that change, the output is: 通过该更改,输出为:

Employee ID:1 
Salary:10

Using global variables is strongly discouraged in most cases, see Why are global variables evil? 在大多数情况下强烈建议不要使用全局变量,请参阅为什么全局变量是邪恶的? .

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM