类的计数器变量

25

我在运行这段代码时遇到了问题。这个类是Student,其中有一个IdCounter,而且似乎问题就出在这里(在第8行)。

class Student:
    idCounter = 0
    def __init__(self):
        self.gpa = 0
        self.record = {}
        # Each time I create a new student, the idCounter increment
        idCounter += 1
        self.name = 'Student {0}'.format(Student.idCounter)

classRoster = [] # List of students
for number in range(25):
    newStudent = Student()
    classRoster.append(newStudent)
    print(newStudent.name)

我正在尝试在Student类中使用这个idCounter,以便将其作为学生姓名的一部分(实际上是一个ID号码,例如Student 12345)。但我一直收到错误信息。

Traceback (most recent call last):
  File "/Users/yanwchan/Documents/test.py", line 13, in <module>
    newStudent = Student()
  File "/Users/yanwchan/Documents/test.py", line 8, in __init__
    idCounter += 1
UnboundLocalError: local variable 'idCounter' referenced before assignment

我尝试将 idCounter += 1 放在 before、after、all 组合中,但仍然遇到“referenced before assignment”错误,你能解释一下我做错了什么吗?


1
你看过紧接着的那行代码了吗? - Ignacio Vazquez-Abrams
为什么我没有想到那个...(原本我的代码写成了Student.idCounter = 0 - George
1
除了特定的错误之外,Python 中递增操作不是原子操作,因此简单的计数器可能会导致竞争条件。更好的方法是使用 itertools.count - bereal
在您的示例此处中发布了对您问题的跟进问题。 - hussam
2个回答

43

必须通过类名来访问类变量,在此示例中为Studend.idCounter:

class Student:
    # A student ID counter
    idCounter = 0
    def __init__(self):
        self.gpa = 0
        self.record = {}
        # Each time I create a new student, the idCounter increment
        Student.idCounter += 1
        self.name = 'Student {0}'.format(Student.idCounter)

classRoster = [] # List of students
for number in range(25):
    newStudent = Student()
    classRoster.append(newStudent)
    print(newStudent.name)

感谢Ignacio和Vazquez-Abrams指出的问题,我已经弄清楚了...


另外,请注意你的第一条评论非常不准确。 - Ignacio Vazquez-Abrams
是的,实际上这只是一个计数器,没有别的了。(不知道该如何评论它,也许应该完全删除这个评论)。非常感谢Ignacio Vazquez-Abrams。 - George

2

之前看到这个答案帮助我找到了解决类变量和实例变量及其作用域的方法。现在,有一个相同功能的扩展,只不过它使用了生成器。生成器像idCounter一样为学生分配唯一的编号,只是它消耗了这些值。据我所知,生成器类上没有“prev”方法。idGenerator和idCounter都没有被记忆化,因此如果您想将列表外部化,然后回来添加一个或多个学生,您需要相应地更新range(start,,) ,或者在不分配任何值的情况下迭代每个值,直到您到达序列中的唯一值,使用idCounter可以更简单地完成这个任务,您只需使用一个虚拟实例构造即可。

class Student:
    """ Implement a shared generator among all sub-classes
    in addition to idCounter. """

    # A student ID counter
    idCounter = 0
    # A student ID from generator
    idGenerator = (x for x in range(0xAAAAAA, 0xEEEEEE, 0xBA))

    def __init__(self):
        self.gpa = 0
        self.record = {}
        # Each time I create a new student, the idCounter increment
        Student.idCounter += 1
        self.id = Student.idGenerator.__next__()
        self.name = f"{self.id} Student {Student.idCounter}"

classRoster = [] # List of students
for number in range(25):
    newStudent = Student()
    classRoster.append(newStudent)
    print(newStudent.name)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接