python在将参数传递给init时引用类变量

时间:2011-07-27 08:10:25

标签: python arguments default init class-variables

我想要达到的目标:
1.有一个类变量,保持创建的对象数量 2.该变量不应提供给对象/其他人,即对班级私有的人 3.如果在init期间未提供特定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的新手,所以请在这里帮助我:)

3 个答案:

答案 0 :(得分: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

答案 1 :(得分: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()

答案 2 :(得分:1)

首先,我将UserClass重命名为User(我们知道它是一个类),UserID重命名为id(它位于User class所以不需要重复“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____metaclass__这样的双尾跟下划线)是特殊的,用于实现类私有变量 - 阅读{{ 3}}了解更多信息。它会触发所谓的“名称重整”。最终结果是__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_countertype(self).__id_counter+= 1一起使用,因为对于SpecialUser实例,将SpecialUser._User__id_counter设置为User._User__id_counter + 1 SpecialUser,然后_User__id_counter将从此时开始使用自己的 _id_counter,这远远不是您想要的。

  • 如果您希望他们拥有他们自己的 ID计数器,请先使用__id_counter而不是_id_counter = 0,因为名称重整将带您朝着一个方向前进你不想去。

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

    • 使用元类为每个类赋予自己的计数器变量(这是一个比我目前可能感到困扰的更高级的主题,如果你愿意,可以询问更多细节)。

    • 在每个类定义中加入一行User(), User(), SpecialUser(), User(), SpecialUser(), SpecialUser(), User()。 (如果你没有,你会遇到ID起点问题 - 制作很多,例如0, 1, 2, 2, 3, 4, 3,他们将拥有(分别)0, 1, 0, 2, 1, 2而不是{{ 1}}。

    此处使用名称修改方法会产生额外的低效率,即子类中将包含多个计数器 - _User__id_counter_SpecialUser__id_counter等。