1

我想要实现的目标:
1. 有一个类变量来记录创建的对象数量
2. 该变量不应该对对象/其他人可用,即类私有
3. 如果在初始化期间未提供特定 ID,请使用此计数器分配object.ID的变量
我有以下python代码

class UserClass(object) :
    __user_id_counter = 0
    def __init__(self, UserID=__user_id_counter) :
        self.UserID = UserID
        __user_id_counter += 1

myuser = UserClass()

但我知道 UnboundLocalError: local variable '_UserClass__user_id_counter' referenced before assignment
我是 python 新手,所以请在这里帮助我:)

4

3 回答 3

4

需要访问__user_id_counter对象或类引用。在参数列表中selfUserClass无法访问,因此:

class UserClass(object) :
    __user_id_counter = 0
    def __init__(self, UserID=None) :
        self.UserID = self.__user_id_counter if UserID is None else UserID
        UserClass.__user_id_counter += 1
于 2011-07-27T08:17:14.887 回答
1

你必须写self.__user_id_counter。如果找不到实例变量,这也会查找类变量。

编辑: Sudhi 指出,在参数列表中,self声明无效。要避免此问题,请尝试以下操作:

class UserClass(object) :
    __user_id_counter = 0
    def __init__(self, UserID=None) :
        if UserID is None:
            self.UserID = self.__user_id_counter
            self.__class__.__user_id_counter += 1
        else:
            self.UserID = UserID

myuser = UserClass()
于 2011-07-27T08:13:30.970 回答
1

首先,我将重命名UserClassUser(我们知道它是一个类)和UserIDid它在User类中,因此无需重复“用户”位,Python 风格推荐小写)和__user_id_counter__id_counter同上)。阅读PEP 8了解 Python 风格指南。

那么,我们的出发点是:

class User(object):
    __id_counter = 0
    def __init__(self, id=None) :
        self.id = self.__id_counter if id is None else id
        __id_counter += 1
myuser = User()
myuser2 = User()
myuser3 = User()

现在,双前导下划线(没有像__init__and之类的双尾下划线__metaclass__)是特殊的,用于实现类私有变量 - 请阅读Python 手册中的私有变量以获取更多信息。它触发了所谓的“名称修改”。它最终__id_counter被重命名为_User__id_counter整个班级。这既有用又危险。在这种情况下,我认为这可能只是没有必要。

这可能导致子类出现问题。

class SpecialUser(User):
    def __init__(self):
        self.__id_counter

现在,SpecialUser()将触发AttributeError: 'SpecialUser' object has no attribute '_SpecialUser__id_counter'.

那么问题来了,您希望子类具有相同的ID 计数器,还是它们自己的ID 计数器?

  • 如果您希望它们具有相同的ID 计数器,请使用User.__id_counter. 不要self.__class__.__id_counterortype(self).__id_counter与 一起使用+= 1,例如,这将SpecialUser设置SpecialUser._User__id_counterUser._User__id_counter + 1,然后从此时开始SpecialUser使用它自己的,这与您想要的相去甚远。 _User__id_counter

  • 如果您希望他们拥有自己的ID 计数器,请从使用_id_counter而不是开始__id_counter,因为名称修改会将您带到您不想去的方向。

    您可以采取以下几种方法:

    • 使用元类为每个类提供自己的计数器变量(这是一个比我目前无法写的更高级的主题,如果您愿意,请询问更多详细信息)。

    • _id_counter = 0在每个类定义中加入一行。(如果你不这样做,你会在 ID 起点遇到麻烦 - 制作很多它们,例如User(), User(), SpecialUser(), User(), SpecialUser(), SpecialUser(), User(),它们将具有(分别)0, 1, 2, 2, 3, 4, 3而不是0, 1, 0, 2, 1, 2.

    在这里使用名称修饰方法会产生的另一个低效率是子类将有多个计数器 - _User__id_counter_SpecialUser__id_counter等。

于 2011-07-27T16:38:15.830 回答