我知道双重下划线对Python类属性/方法意味着什么,但它是否意味着方法参数?
看起来你不能将以双下划线开头的参数传递给方法。这很令人困惑,因为你可以为正常的功能做到这一点。
考虑这个脚本:
def egg(__a=None):
return __a
print "egg(1) =",
print egg(1)
print
class Spam(object):
def egg(self, __a=None):
return __a
print "Spam().egg(__a=1) =",
print Spam().egg(__a=1)
运行此脚本会产生:
egg(1) = 1
Spam().egg(__a=1) =
Traceback (most recent call last):
File "/....py", line 15, in <module>
print Spam().egg(__a=1)
TypeError: egg() got an unexpected keyword argument '__a'
我用Python 2.7.2检查了这个。
其他一些例子
这有效:
def egg(self, __a):
return __a
class Spam(object):
egg = egg
Spam().egg(__a=1)
这不是:
class Spam(object):
def _egg(self, __a=None):
return __a
def egg(self, a):
return self._egg(__a=a)
Spam().egg(1)
答案 0 :(得分:13)
名称修改适用于具有前导双下划线的所有标识符regardless of where they occur(该部分中倒数第二句):
此转换独立于使用标识符的语法上下文。
这更容易实现和定义,并且更加一致。这可能看起来很愚蠢,但整个名字的整理交易是一个丑陋的小黑客恕我直言;并且除了属性/方法之外,你不应该使用这样的名字。
Spam().egg(_Spam__a=1)
以及Spam().egg(1)
确实有效。但即使你可以使它工作,前导下划线(任意数量)在参数名称中没有位置。或者在任何局部变量(例外:_
)中。
编辑:您似乎找到了一个没有人考虑的角落案例。这里的文档不精确,或者实现有缺陷。它出现的关键字参数名称不会被破坏。查看字节码(Python 3.2):
>>> dis.dis(Spam.egg)
3 0 LOAD_FAST 0 (self)
3 LOAD_ATTR 0 (_egg)
6 LOAD_CONST 1 ('__a') # keyword argument not mangled
9 LOAD_FAST 1 (a)
12 CALL_FUNCTION 256
15 RETURN_VALUE
>>> dis.dis(Spam._egg)
2 0 LOAD_FAST 1 (_Spam__a) # parameter mangled
3 RETURN_VALUE
这可能源于这样一个事实:关键字参数等同于传递一个dict(在这种情况下为{'__a': 1}
),其键也不会被破坏。但老实说,我只是把它称为一个丑陋的角落案件,在一个已经很丑陋的特殊情况下继续前进。这并不重要,因为你不应该使用这样的标识符。
答案 1 :(得分:3)
它会转换为_Spam__a
:
In [20]: class Spam(object):
....:
....: def egg(self, __a=None):
....: return __a
....:
In [21]: Spam.egg.__func__.__code__.co_varnames
Out[21]: ('self', '_Spam__a')
答案 2 :(得分:1)
类上下文中的双下划线或Name Mangling是私有标识符。在您的示例中尝试dir(Spam.egg),您将看到参数__a现在是_Spam__egg
。
您现在可以使用:
Spam().egg(_Spam__a=1)