Python方法*参数*的双下划线

tkf*_*tkf 13 python

我知道双重下划线对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)
Run Code Online (Sandbox Code Playgroud)

运行此脚本会产生:

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'
Run Code Online (Sandbox Code Playgroud)

我用Python 2.7.2检查了这个.


其他一些例子

这有效:

def egg(self, __a):
    return __a


class Spam(object):

    egg = egg

Spam().egg(__a=1)
Run Code Online (Sandbox Code Playgroud)

这不是:

class Spam(object):

    def _egg(self, __a=None):
        return __a

    def egg(self, a):
        return self._egg(__a=a)

Spam().egg(1)
Run Code Online (Sandbox Code Playgroud)

小智 13

名称修改适用于具有前导双下划线的所有标识符,无论它们出现在何处(该部分中的倒数第二句):

此转换独立于使用标识符的语法上下文.

这更容易实现和定义,并且更加一致.这可能看起来很愚蠢,但整个名字的整理交易是一个丑陋的小黑客恕我直言; 并且除了属性/方法之外,你不应该使用这样的名字.

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
Run Code Online (Sandbox Code Playgroud)

这可能源于这样一个事实:关键字参数等同于传递一个dict(在这种情况下{'__a': 1}),它的键也不会被破坏.但老实说,我只是把它称为一个丑陋的角落案件,在一个已经很丑陋的特殊情况下继续前进.这并不重要,因为你不应该使用这样的标识符.