4

我正在做代码学院流,我对 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)
4

2 回答 2

9

这在 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真的可以被称为任何你想要的东西的原因,比如arg0or thisor meor putinetc。

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

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 Descriptors @ https://docs.python.org/2/howto/descriptor.html,了解这是如何实现的以及如何自己实现类似的方案。

于 2014-04-15T11:38:51.463 回答
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.xxx

希望有帮助。

于 2014-04-15T11:37:10.143 回答