问题
I'm doing the code academy stream and I have a little experience in Ruby. I don't understand why the check_angles(self)
function needs the self
parameter.
The reason I'm confused is that I don't understand what is passing the self parameter to the function when it is called. it seems like the function call (the last line of the code block) is passing self implicitly, but the function requires self explicitly defined as a parameter.
Why is this?
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)
回答1:
The way this works in Python is that once you instantiate a class Foo
with a method bar(self)
, the function used to create the method is wrapped in an object of type instancemethod
which "binds" it to the instance, so that calling foo_inst.bar()
actually calls 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)
or, interactively:
>>> Foo.bar
<unbound method Foo.bar>
>>> Foo().bar
<bound method Foo.bar of <__main__.Foo object at 0x10675ecd0>>
so as you can see, while still attached directly to the class, bar
is an unbound method and still has the self
argument, however, when retrieving the method object from a Foo
instance, it has become a bound method whose self
parameter is already pre-set to the instance you retrieved the method object from.
This is also the reason why self
can really be called anything you want such as arg0
(or stifflersmom
or allyourbase
).
See also Python Descriptors @ https://docs.python.org/2/howto/descriptor.html for how this is implemented and how you can implement similar schemes yourself.
In fact, it becomes even more visible that methods are actually functions under the hood in this example:
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>
Note: assigning functions to class objects after they've been declared (known as monkeypatching) is not a recommended style of programming in dynamic languages such as Python because it's A) error prone (might overwrite something in a future version of the same class because there is no compiler to verify that's not the case) and B) hard to comprehend (not possible to know which methods instances of a class actually have just by looking at the class definition because there's no compiler/IDE to find the added methods).
回答2:
When you call tri.check_angles()
you are confused because the function check_angles
takes one argument. In fact, you're right. The tri
is the argument that is passed as self
.
self
is used in classes to hold variables that are local to a specific instance of the class.
Example
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
whereas, if you had just x
instead of self.x
and you changed the value of x
for one instance, the value of x
for all instances would change.
Hope that helps.
来源:https://stackoverflow.com/questions/23082509/how-is-the-self-argument-magically-passed-to-instance-methods