【问题标题】:Why does `class X: mypow = pow` work? What about `self`?为什么`class X: mypow = pow` 有效? “自我”呢?
【发布时间】:2015-08-22 00:06:07
【问题描述】:

这很有效,可以愉快地打印 81:

class X:
    mypow = pow

print(X().mypow(3, 4))

但是为什么呢?该方法不是给出了额外的“自我”参数,应该完全混淆吗?

为了比较,我也用自己的Pow函数试了一下:

def Pow(x, y, z=None):
    return x ** y

class Y:
    myPow = Pow

print(Pow(3, 4))
print(Y().myPow(3, 4))

直接函数调用打印 81 并且方法调用按预期崩溃,因为它确实获得了额外的实例参数:

Python 3:  TypeError: unsupported operand type(s) for ** or pow(): 'Y' and 'int'
Python 2:  TypeError: unsupported operand type(s) for ** or pow(): 'instance' and 'int'

Python 拥有的pow 为什么/如何在这里工作? The documentation 没有帮助,我找不到源。

【问题讨论】:

  • 以同样的方式传递给我的Pow? @PadraicCunningham
  • 这是因为内置函数的__self__属性不可写,所以pow总是None
  • @vaultah 在 Python 2 中尝试。
  • @AshwiniChaudhary 谢谢,我正在调查__self__,还不知道。

标签: python methods self


【解决方案1】:

嗯,@tynn 已经指出了pow 没有__get__ 的原因,所以不能转化为bound method

但是为什么呢?所有这些事情背后的关键是descriptor protocol。如果有人想更好地了解Python,那就去了解descriptor protocol,这并不难,但非常简单和强大。

【讨论】:

    【解决方案2】:

    此行为与method binding 有关。看看 Python 告诉你的关于这些函数/方法的内容:

    >> pow
    <built-in function pow>
    >>> X.mypow
    <built-in function pow>
    >>> X().mypow
    <built-in function pow>
    

    >>> Pow
    <function Pow at 0x7f88f5715f50>
    >>> Y.myPow
    <unbound method Y.Pow>
    >>> Y().myPow
    <bound method Y.Pow of <__main__.Y instance at 0x7f88f57117e8>>
    

    进一步的文档说明:

    类字典将方法存储为函数。在类定义中,方法是使用deflambda 编写的,它们是创建函数的常用工具。 [...]

    为了支持方法调用,函数包括__get__() 方法,用于在属性访问期间绑定方法。这意味着所有函数都是非数据描述符,它们返回绑定或未绑定的方法,具体取决于它们是从对象还是类调用。 [...]

    但是内置函数没有__get__() 方法。这就是为什么pow 没有被绑定并且可以按照你观察到的方式使用,而Pow 不能。

    【讨论】:

      【解决方案3】:

      这是因为在 C(内置)中定义的 python 函数具有自动处理的 self 参数。这是 pow 函数头:

      static PyObject * math_pow(PyObject *self, PyObject *args) 在这里你可以看到 self 总是被解释器传递。

      【讨论】:

      • 那不是math.pow,不是pow
      • 这是 math.pow,但行为是一样的。
      • 嗯,我检查并确认它在这方面确实表现相同(即,愉快地返回 81.0)。我找到了the source of that,它只是忽略了self 参数。我想我需要知道用户定义的方法如何忽略它才能真正理解它。 AshwiniChaudhary 还评论了关于内置的 __self__ not writable 的一些内容,我确认了这一点,但我想如果它不被使用也没关系。我会稍微研究一下这两个问题。
      • 问题是用户定义的方法与 C 方法相比表现不同。每个 python C 方法都必须定义 self,并且总是填充一些东西(当前对象、全局等)。用户方法没有该选项,这意味着当使用您所显示的方式时,第一个参数将填充 self,但像往常一样使用时,它不会。
      猜你喜欢
      • 2016-10-05
      • 1970-01-01
      • 1970-01-01
      • 2018-01-04
      • 1970-01-01
      • 1970-01-01
      • 2013-05-01
      • 1970-01-01
      • 2017-06-09
      相关资源
      最近更新 更多