我想要达到的目标:
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的新手,所以请在这里帮助我:)
答案 0 :(得分:4)
要访问__user_id_counter
,需要引用对象或类。在参数列表中,self
或UserClass
无法访问,因此:
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_counter
或type(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
等。