Python 自参数是如何神奇地传递给实例方法的?

Python 自参数是如何神奇地传递给实例方法的?,python,self,Python,Self,我正在做代码学院流,我在Ruby方面有一点经验。我不明白为什么check_angles(self)函数需要self参数 我感到困惑的原因是,我不明白在调用self参数时是什么将其传递给函数的。看起来函数调用(代码块的最后一行)是自隐式传递的,但函数需要自显式定义为参数 为什么会这样 class Triangle(object): def __init__(self, angle1, angle2, angle3): self.angle1 = angle1

我正在做代码学院流,我在Ruby方面有一点经验。我不明白为什么
check_angles(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)

调用
tri.check_angles()
时,您会感到困惑,因为函数
check_angles
只包含一个参数。事实上,你是对的。
tri
是作为
self
传递的参数

self
在类中用于保存类的特定实例的局部变量

例子 然而,如果您只是使用
x
而不是
self.x
,并且您更改了一个实例的
x
值,那么所有实例的
x
值都会更改


希望这会有所帮助。

在Python中的工作方式是,一旦您使用一个方法
bar(self)
实例化一个类
Foo
,用于创建该方法的函数将被包装在类型为
instancemethod
的对象中,该对象将其“绑定”到实例,以便调用
Foo_inst.bar()
实际调用
Foo.bar(Foo\u inst)

或者,以交互方式:

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

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

注意:在声明类对象后将函数分配给类对象(称为monkeypatching)不是Python等动态语言中推荐的编程风格,因为它容易出错(可能会在同一类的未来版本中覆盖某些内容,因为没有编译器来验证这一点)B)难以理解(仅通过查看类定义不可能知道类的实例实际包含哪些方法,因为没有编译器/IDE来查找添加的方法)。

self
不是函数参数。它表示“函数”是一个类方法。因此,您可以从刚才定义的method中访问类属性和其他方法。@AleksanderLidtke:应该使用术语实例方法;类方法/属性在Python中有非常特殊的含义;它们指的是用
@classmethod
修饰的方法,以及在实际类对象上存储和调用的属性。@AleksanderLidtke:事实上,从技术上讲,
self
只是一个函数参数;没有更多,也没有更少:)请看我的答案了解原因。@ErikAllik:)不太熟悉Python的“幕后”视角,很有趣。谢谢。还忘记了
@classmethod
。也许类的方法更合适。
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>>
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>