我正在进行代码学院流程,我在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)
答案 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
(或stifflersmom
或allyourbase
)。
另请参阅 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>实例会改变。
希望有所帮助。