python - self 参数是如何神奇地传递给实例方法的?

标签 python oop self language-implementation python-descriptors

我在做代码学院流,我在 Ruby 方面有一点经验。我不明白为什么 check_angles(self) 函数需要 self 参数。

我感到困惑的原因是我不明白在调用函数时将 self 参数传递给函数的是什么。函数调用(代码块的最后一行)似乎隐式传递了 self,但该函数需要将 self 显式定义为参数。

这是为什么?

class Triangle(object):
    def __init__(self, angle1, angle2, angle3):
        self.angle1 = angle1
        self.angle2 = angle2
        self.angle3 = angle3

    number_of_sides = 3

    def check_angles(self):
        sum_angles = self.angle1 + self.angle2 + self.angle3
        if sum_angles == 180:
            return True
        else:
            return False

    tri = Triangle(45,34,78)
    tri.check_angles(EMPTY BUT WHY)

最佳答案

这在 Python 中的工作方式是,一旦你用方法 bar(self) 实例化了一个类 Foo ,用于创建该方法的函数就被包装在一个instancemethod 类型的对象将其“绑定(bind)”到实例,因此调用 foo_inst.bar() 实际上会调用 Foo.bar(foo_inst) .

class Foo(object):
    def bar(self):
        print "called bar on %s" % self

foo_inst = Foo()

# these 2 calls are equivalent
foo_inst.bar()
Foo.bar(foo_inst)

或者,交互地:

>>> Foo.bar
<unbound method Foo.bar>

>>> Foo().bar
<bound method Foo.bar of <__main__.Foo object at 0x10675ecd0>>

如您所见,bar 仍然直接附加到类,但它是一个未绑定(bind)方法,并且仍然有 self 参数,但是,当从 Foo 实例中检索方法对象时,它已成为一个绑定(bind)方法,其 self 参数已预先设置为实例您从中检索了方法对象。

这也是为什么 self 可以真正被称为任何你想要的东西的原因,例如 arg0thismeputin

事实上,在这个例子中,方法实际上是底层函数变得更加明显:

class Foo(object):
    pass

def bar(arg0):
    print "called bar with %s" % arg0

Foo.bar = bar

Foo().bar()  # prints: called bar with <Foo object at 0x10675b2d0>

另见 Python 描述符@ https://docs.python.org/2/howto/descriptor.html了解这是如何实现的,以及您如何自己实现类似的方案。

关于python - self 参数是如何神奇地传递给实例方法的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23082509/

相关文章:

Python 异步监控

Python ipywidgets : create a savefig button

python - 替换给定索引处的所有 1 - numpy

c++ - 包装类中赋值运算符的返回类型?

Swift 在构建子节点时给出 "self used before all stored procedures are initialized"错误

python - 为什么我的分页 Bootstrap 样式不起作用?

r - 如何不覆盖泛型方法

javascript - 方法作为原型(prototype)中的属性

ios - 获取组件的变量名

php - new self(); 是什么意思?在 PHP 中是什么意思?