Python - 对象属性赋值失败

1 投票
1 回答
549 浏览
提问于 2025-04-17 18:18

我的问题是,在这一行之后:-> self.__serverUrl = serverUrl

为什么会出现这样的情况?:*** AttributeError: Client instance has no attribute '__serverUrl'

详细信息

我正在使用Beatbox与Salesforce进行交互,但遇到了一个错误

*** AttributeError: Client instance has no attribute '_Client__serverUrl'

我想知道为什么在设置之前就访问了这个字段,所以我添加了pdb.set_trace(),想着可以找到一些答案。这是我看到的(注意第67行):

(Pdb)
--Call--
> /app/env/local/lib/python2.7/site-packages/beatbox/_beatbox.py(65)useSession()
-> def useSession(self, sessionId, serverUrl):
(Pdb) l
 64         # initialize from an existing sessionId & serverUrl, useful if we're being launched via a custom link
 65  ->     def useSession(self, sessionId, serverUrl):
 66             self.sessionId = sessionId
 67             self.__serverUrl = serverUrl
 68             (scheme, host, path, params, query, frag) = urlparse(self.__serverUrl)
 69             self.__conn = makeConnection(scheme, host)
 70

我检查了serverUrl的值,一切正常。然后我到了第67行,让它执行,想着serverUrl的值应该在self.__serverUrl里。显然不是……

> /app/env/local/lib/python2.7/site-packages/beatbox/_beatbox.py(67)useSession()
-> self.__serverUrl = serverUrl
(Pdb) n
> /app/env/local/lib/python2.7/site-packages/beatbox/_beatbox.py(68)useSession()
-> (scheme, host, path, params, query, frag) = urlparse(self.__serverUrl)
(Pdb) self.__serverUrl
*** AttributeError: Client instance has no attribute '__serverUrl'

这里发生了什么!?这不应该发生。看起来这个赋值悄悄地失败了。为什么这个值没有在这里被赋值?

源代码

我正在使用的源代码在这里

我创建了一个beatbox客户端并登录

svc = PythonClient()
svc.login(username, password)

这调用了python_client.Client的登录方法。python_client.Client.login又调用了它的父类_beatbox.Client的登录方法,长这样:

class Client:
    def __init__(self, serverUrl=None):
       ...

    # login, the serverUrl and sessionId are automatically handled, returns the loginResult structure       
    def login(self, username, password):
        lr = LoginRequest(self.serverUrl, username, password).post()
        self.useSession(str(lr[_tPartnerNS.sessionId]), str(lr[_tPartnerNS.serverUrl]))
        return lr

    # initialize from an existing sessionId & serverUrl, useful if we're being launched via a custom link   
    def useSession(self, sessionId, serverUrl):
        self.sessionId = sessionId
        self.__serverUrl = serverUrl
        (scheme, host, path, params, query, frag) = urlparse(self.__serverUrl)
        self.__conn = makeConnection(scheme, host)

赋值发生在_beatbox.Client.useSession中,这是对象svc的父类

1 个回答

3

以双下划线开头(但没有以双下划线结尾)的名字在类的范围内会被“搞混”,也就是名字会被改成其他形式。具体来说,它们会在前面加上_<classname>

如果你在全局范围内定义一个函数,并且这个函数设置了一个以双下划线开头的名字,那么你会设置错误的属性,因为这个名字不会被搞混。如果你在一个派生类中定义了这样的函数,你也会访问到错误的属性,因为名字搞混会加上派生类的名字,而不是基类的名字(所以,名字搞混实际上实现了一种弱的私有属性)。

如果子类需要访问这个属性,最好的做法是完全避免名字搞混,或者使用属性。如果实在无法避免,你就得使用这个临时解决方案:

self._Client__serverUrl = ...

撰写回答