On Sun, Mar 11, 2012 at 07:02:11PM -0700, Michael Lewis wrote:
> Why do I have to use "self.example" when calling a method inside a class?
> For example:
> def Play(self):
> '''find scores, reports winners'''
> self.scores = 
> for player in range(self.players):
> print 'Player', player + 1
> I have another method called take turns (not shown for brevity purposes).
> When I want to call it, why can't I just call it like a function and use
> TakeTurns() instead of self.TakeTurns()?
When you call range() inside a method, as you do above, do you
expect to get the global range() function, or the self.range()
method (which likely doesn't exist)?
Same for len(), or any other built-in or global.
Similarly, how do you expect Python to distinguish between a persistent
attribute, like self.scores, and a local variable, like player?
Since Python can't read your mind, one way or another you have to
explicitly tell the compiler which of the two name resolution
orders to use:
(1) The normal function scope rules:
- local variables have priority over:
- non-locals, which have priority over:
- globals, which have priority over:
(2) or the attribute search rules, which is quite compilicated but a
simplified version is:
- instance attributes or methods
- class attributes or methods
- superclass attributes or method
- computed attributes or methods using __getattr__
Python refuses to guess which one you want, since any guess is likely to
be wrong 50% of the time. Instead, Python's design is to always use
function scope rules, and if you want attributes or methods, you have to
explicitly ask for them. This makes MUCH more sense than having to
explicitly flag local variables!
Other languages made other choices. For instance, you might demand that
the programmer declare all their variables up-front, and all their
instance attributes. Then the compiler can tell at compile-time that
range is a built-in, that player is a local variable, and that TakeTurns
is an instance attribute. That's a legitimate choice, and some languages
do it that way.
But having programmed in some of these other languages, give me Python's
lack of declarations anytime!
Since all names (variables and attributes) in Python are generated at
runtime, the compiler normally cannot tell what the scope of a name is
until runtime (with a few exceptions).
> On Sun, Mar 11, 2012 at 07:02:11PM -0700, Michael Lewis wrote:
>> Why do I have to use "self.example" when calling a method inside a class?
>> For example:
>> def Play(self):
>> '''find scores, reports winners'''
>> self.scores = 
>> for player in range(self.players):
>> print 'Player', player + 1
>> I have another method called take turns (not shown for brevity purposes).
>> When I want to call it, why can't I just call it like a function and use
>> TakeTurns() instead of self.TakeTurns()?
Steven's notes about scoping rules are one reason. Another is the
matter of object instance binding. When you call a method, you're not
just calling a regular function. You're calling a function bound to a
particular object, so by saying self.TakeTurns(), Python knows that the
object "self" is invoking that method, not some other instance of the
Play class. That method then can access all of that specific object's
attributes as necessary.
> On 12/03/12 02:02, Michael Lewis wrote:
>> I have another method called take turns (not shown for brevity
>> purposes). When I want to call it, why can't I just call it like a
>> function and use TakeTurns() instead of self.TakeTurns()?
> The Steve's have given technical answers, its also stylistically
> better because it removed ambiguity for the reader as well as
> for Python.
> Many corporate style guides advocate using this same style
> when using C++ or Java to make it explicit when you are using
> a class attribute rather than a local or global value/function.
> It improves code clarity and therefore reduces potential bugs
> and speeds up maintenance for a tiny loss in initial coding
> Alan G
> Author of the Learn to Program web site
> http://www.alan-g.me.uk/ >
> Tutor maillist - [hidden email] > To unsubscribe or change subscription options:
i want to expand specifically on steve's response and note the big distinction that needs to be made for everyone is that this is primary the difference between calling a *function* and calling a *method* (which is a function that belongs to/defined for a class).
with that instance (self), that method is considered "bound," and Python automagically passes it in as the first argument to that method (self). if you wish to call an *unbound* method, you need to pass an instance on your own *and* reference it via its class, i.e., YourClass.TakeTurns(self) -- readability takes a blow there.
btw, if you want to make just a function call *and* that function doesn't have much to do with the class, then just define it as a function. a seldomly-used alternative is to make it a static method (using the @staticmethod decorator) -- this lets you define a method within a class but pretend it's like a function (where you don't need to use the instance [self]).