自我论证如何神奇地传递给实例方法?

时间:2014-04-15 11:35:58

标签: python self

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

2 个答案:

答案 0 :(得分:8)

这在Python中的工作方式是,一旦使用方法Foo实例化类bar(self),用于创建方法的函数将包装在instancemethod类型的对象中。将其“绑定”到实例,以便调用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是一个未绑定的方法,但仍然有self参数,但是,在检索方法时来自Foo实例的对象,它已成为绑定方法,其self参数已预先设置为从中检索方法对象的实例。

这也是为什么self可以真正被调用的原因,例如arg0(或stifflersmomallyourbase)。

另请参阅 Python描述符@ https://docs.python.org/2/howto/descriptor.html,了解其实现方式以及如何自行实施类似方案。


事实上,在这个例子中,方法实际上是功能更加明显:

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>

注意:在声明了类对象之后将它们分配给类对象(称为monkeypatching)不是推荐的动态语言(如Python)的编程风格,因为它是A)容易出错(可能会覆盖)在同一个类的未来版本中的东西,因为没有编译器来验证不是这种情况)和B)难以理解(不可能只是通过查看类定义来知道类的实例具有哪些实例,因为没有编译器/ IDE来查找添加的方法。)

答案 1 :(得分:0)

当你致电tri.check_angles()时,你会感到困惑,因为函数check_angles只有一个参数。事实上,你是对的。 tri是作为self传递的参数。

self在类中用于保存特定类的实例的本地变量。

实施例

class A():
    def __init__(self):
        self.x = 2

>>> a = A()
>>> b = A()
>>> print a.x
2
>>> print b.x
2
>>> a.x = 5
>>> print a.x
5
>>> print b.x
2

然而,如果您只有x而不是self.x并且您为一个实例更改了x的值,那么所有<x的值/ strong>实例会改变。

希望有所帮助。