understanding self

  • Thread starter bruce stockwell
  • Start date
B

bruce stockwell

Using 'self' in classes seems pretty straight forward. My curiosity is
why I have to use it. Shouldn't it be implied? If I create an instance
of 'human' called 'bruce' and call the method 'blink' why do I have to
pass bruce into the method e.g.

class human:
...code
def blink(self,times):
for i in range(times):
if self.eye_is_closed:
self.eye_open()
self.eye_close()
else:
self.eye_close()
self.eye_open()
def eye_open(self):
...code
def eye_close(self):
...code


bruce = human()
bruce.blink(5)

blink is a method of bruce because bruce is an instance of human.
Reading this silly code I can understand what is going on if self was
not included. Can anyone enlighten me as to why we have self?

by the way..six months of python and I'm 10 times the programmer I was
with vb


v/r
Bruce
 
J

Jeff Shannon

bruce said:
Using 'self' in classes seems pretty straight forward. My curiosity is
why I have to use it. Shouldn't it be implied?

The problem is that an implied 'self' is harder to read than an explicit
'self', and also opens the door for ambiguity when an instance attribute
has the same name as a global or builtin attribute.

Let's look at an example in a hypothetical Python variant where 'self'
is implied --

class eye:
def open(which):
# do stuff here

def close(which):
# do stuff here

def blink(which):
if closed:
open(which)
close(which)
else:
close(which)
open(which)

e = eye()
e.blink('right')

But wait -- open() is an obsolete built-in function for opening a file.
Which should eye.blink() do -- open and close the right eye, or open a
file with the name of 'right' ?? If it's the former, then what do you
do if you *want* to open that file? If it's the latter, then what
happens when the next version of Python comes along and open() has been
removed from built-ins?

Even without these namespace conflicts, it's difficult when you're
reading a long method and see a call to "make_thingumbob()" -- where do
you look to see what that does? It might be another method of that
class, or it might be a global (or even built-in) function. It then
requires extra thought and search-time to figure out the intent.

One of the design principles of Python is that ease of *reading* is more
important than ease of *writing*. It's worth a few extra keystrokes if
it will save you a second or two of time when reading unfamiliar code --
because most code is only written once, but read *many* times.

Jeff Shannon
Technician/Programmer
Credit International
 
V

Ville Vainio

Jeff> But wait -- open() is an obsolete built-in function for
Jeff> opening a file. Which should eye.blink() do -- open and
Jeff> close the right eye, or

I'll just like to point out that open() is in no way obsolete, even if
it's aliased to "file". ItÃ's probably intop 5% of builtins in terms
of frequency in existing code, so deprecating it would deprecate
pretty much all the existing python code.

IÃ'm sure äll see "print" being deprecated before "open".
 
J

Jeff Shannon

Ville said:
Jeff> But wait -- open() is an obsolete built-in function for
Jeff> opening a file. Which should eye.blink() do -- open and
Jeff> close the right eye, or

I'll just like to point out that open() is in no way obsolete, even if
it's aliased to "file". ItÃ's probably intop 5% of builtins in terms
of frequency in existing code, so deprecating it would deprecate
pretty much all the existing python code.

IÃ'm sure äll see "print" being deprecated before "open".

Okay, perhaps "legacy" is a better term than "obsolete". In either
case, it's recommended that it not be used in new code, even if there is
no current plan to remove it. Not that the specifics of this case are
particularly germane to the point I was making...

Jeff Shannon
Technician/Programmer
Credit International
 
G

Greg Ewing

Jeff said:
Okay, perhaps "legacy" is a better term than "obsolete". In either
case, it's recommended that it not be used in new code

In a recent exchange on python-dev, Guido has made it clear
that this is NOT the case -- he wants people to continue
using open(), since it might not remain a synonym for
file() in the future. He has acknowledged that the
documentation needs clarification on this.
 
D

Dennis Lee Bieber

In a recent exchange on python-dev, Guido has made it clear
that this is NOT the case -- he wants people to continue
using open(), since it might not remain a synonym for
file() in the future. He has acknowledged that the
documentation needs clarification on this.

Now there is a scary thought... one or the other will
incorporate the functions of anydbm, and a few other file specific
modules -- attempting to determine what is needed to process any file
found on a system.

--
 
D

David Fraser

Jeff said:
The problem is that an implied 'self' is harder to read than an explicit
'self', and also opens the door for ambiguity when an instance attribute
has the same name as a global or builtin attribute.

Let's look at an example in a hypothetical Python variant where 'self'
is implied --

class eye:
def open(which):
# do stuff here

def close(which):
# do stuff here

def blink(which):
if closed:
open(which)
close(which)
else:
close(which)
open(which)

e = eye()
e.blink('right')

But wait -- open() is an obsolete built-in function for opening a file.
Which should eye.blink() do -- open and close the right eye, or open a
file with the name of 'right' ?? If it's the former, then what do you
do if you *want* to open that file? If it's the latter, then what
happens when the next version of Python comes along and open() has been
removed from built-ins?

Even without these namespace conflicts, it's difficult when you're
reading a long method and see a call to "make_thingumbob()" -- where do
you look to see what that does? It might be another method of that
class, or it might be a global (or even built-in) function. It then
requires extra thought and search-time to figure out the intent.

One of the design principles of Python is that ease of *reading* is more
important than ease of *writing*. It's worth a few extra keystrokes if
it will save you a second or two of time when reading unfamiliar code --
because most code is only written once, but read *many* times.

You are assuming here that "self." would be implied on potential
attribute accesses (like this in C++). The reason this is problematic is
that it complicates Python's scoping structured. But it is not
neccessarily the only way that having an implicit self could be used -
self could be implicit in the parameter list, but explicit for any other
use.

For example, there could be a keyword 'method' which defines a method
object that takes self as its first parameter even though it's not
declared. So the two __cmp__ definitions below would be equivalent:

class Complex:
# ...
def cmpabs(self, other):
return self.abs().__cmp__(other.abs())
method cmpabs2(other):
return self.abs().__cmp__(other.abs())

a = Complex(3,4)
b = Complex(4,3)
print a.cmpabs(b)
print a.cmpabs2(b)

David
 
A

Albert Hofkamp

blink is a method of bruce because bruce is an instance of human.
Reading this silly code I can understand what is going on if self was
not included. Can anyone enlighten me as to why we have self?

ok, what about this?

def f():
# do something
return 5

class X:
def f(self):
# do something else
return 4


def doit(self):
x=self.f()
y=f()

The example is very silly, but when executing doit(), it is clear that x
will contain 4 and y will contain 5 afterwards.

Now if we drop self, we get

def doit(self):
x=f()
y=f()

Now there is no difference between both calls any more. That means that
the computer does not understand that you are aiming for calling
different functions f() here. We can agree that f() means the f in the
class, but then I cannot reach the global f any more, or vice versa. In
both cases, I lose expressiveness.


Albert
 
C

Colin J. Williams

Jeff said:
The problem is that an implied 'self' is harder to read than an explicit
'self', and also opens the door for ambiguity when an instance attribute
has the same name as a global or builtin attribute.

Let's look at an example in a hypothetical Python variant where 'self'
is implied --

class eye:
def open(which):
# do stuff here

def close(which):
# do stuff here

def blink(which):
if closed:
open(which)
close(which)
else:
close(which)
open(which)

e = eye()
e.blink('right')

But wait -- open() is an obsolete built-in function for opening a file.
Which should eye.blink() do -- open and close the right eye, or open a
file with the name of 'right' ?? If it's the former, then what do you
do if you *want* to open that file? If it's the latter, then what
happens when the next version of Python comes along and open() has been
removed from built-ins?

Even without these namespace conflicts, it's difficult when you're
reading a long method and see a call to "make_thingumbob()" -- where do
you look to see what that does? It might be another method of that
class, or it might be a global (or even built-in) function. It then
requires extra thought and search-time to figure out the intent.

One of the design principles of Python is that ease of *reading* is more
important than ease of *writing*. It's worth a few extra keystrokes if
it will save you a second or two of time when reading unfamiliar code --
because most code is only written once, but read *many* times.

Jeff Shannon
Technician/Programmer
Credit International
I'm sure this issue has been flogged before.

Couldn't both clarity and simplicity be achieved by replacing the
"self." with ".". self is not normally at the left of an assignment and
the self would not need to appear in the method signature.

Version 3 pehaps?

Colin W.
 
R

Roy Smith

David Fraser said:
For example, there could be a keyword 'method' which defines a method
object that takes self as its first parameter even though it's not
declared. So the two __cmp__ definitions below would be equivalent:

class Complex:
# ...
def cmpabs(self, other):
return self.abs().__cmp__(other.abs())
method cmpabs2(other):
return self.abs().__cmp__(other.abs())

Yes, you are right, you could design things to work that way. But why
would you want to? Having two ways to do the same thing just adds
complexity without adding my value.

People learning the language have to learn two different things. Some
people will adopt one style, and some will adopt the other. As a
result, we would have two different bodies of code floating around.
You'd end up with things like this:

1) Pythonista A has adopted the "explicit self" style, and convinces his
friend to learn the language. He teaches the "explicit self" style to
his friend.

2) The friend is happy with the new language and goes out into the world
confident that he's added a new and useful skill to his portfolio.

3) The friend picks up a piece of code written by pythonista B, who has
adopted the "implicit self" style, and discovers that he can't make
heads or tails of it.

4) The friend changes his mind about Python, saying, "Gee, if I wanted a
language in which there's more than one way to do it, I would have stuck
with Perl".

5) The Python world has lost another potential convert, ultimately
hastening the end of all intelligent life as we know it.
 
J

Jeff Shannon

David said:
For example, there could be a keyword 'method' which defines a method
object that takes self as its first parameter even though it's not
declared. So the two __cmp__ definitions below would be equivalent:

class Complex:
# ...
def cmpabs(self, other):
return self.abs().__cmp__(other.abs())
method cmpabs2(other):
return self.abs().__cmp__(other.abs())


Another Python design principle is to minimize the number of keywords.
You *could* do that... but it doesn't really gain you anything except an
extra keyword. And I personally find it clearer to see "self" in the
parameter list than to have to think "Oh yeah, this is a method, so
there's an implied self..."

But most importantly, an implicit 'self' would violate the second "Zen
of Python" guideline -- "Explicit is better than implicit." Unless you
can point to a significant *gain* by having 'self' implicit, then it's
better (or at least, more Pythonic) to have it explicit. So far, I've
heard plenty of alternatives to having explicit 'self', but very little
indication of why it would be an improvement other than that it would
allow less typing -- and Python has always placed ease-of-reading over
ease-of-typing. ("Readability counts.")

(Heck, back when I was learning C++, I tended to explicitly use 'this'
when referring to class members/methods even though it was unnecessary,
simply because it made it easier to *see* what was a class member and
what wasn't; the "m_***" naming convention that's often used instead
strikes me as just being a weak way of doing the same thing...)

Jeff Shannon
Technician/Programmer
Credit International
 
J

Jeff Shannon

Greg said:
In a recent exchange on python-dev, Guido has made it clear
that this is NOT the case -- he wants people to continue
using open(), since it might not remain a synonym for
file() in the future. He has acknowledged that the
documentation needs clarification on this.


Okay, I was following the implication in the documentation, and IIRC
some conversation I'd seen (presumably based off of that same
implication). This thread is the first indication I've seen since
Python 2.2 came out that file() *wasn't* the preferred way to open
files... (Not that I've even been following *this* newsgroup steadily in
that time.) I'll keep this in mind from now on.

(But preferences regarding file() and open() are *still* not germane to
the point I was making about explicit 'self'. ;) )

Jeff Shannon
Technician/Programmer
Credit International
 
S

Steve Lamb

So far, I've heard plenty of alternatives to having explicit 'self', but
very little indication of why it would be an improvement other than that it
would allow less typing -- and Python has always placed ease-of-reading over
ease-of-typing. ("Readability counts.")

Good thing, too, lest we devolve into Ruby's wannabe Perl line-noise to
denote what's what. Isn't @ in ruby a class variable?
 
B

bruno modulix

bruce stockwell a écrit :
Using 'self' in classes seems pretty straight forward. My curiosity is
why I have to use it. Shouldn't it be implied? If I create an instance
of 'human' called 'bruce' and call the method 'blink' why do I have to
pass bruce into the method e.g.
(snip)

blink is a method of bruce because bruce is an instance of human.
Reading this silly code I can understand what is going on if self was
not included. Can anyone enlighten me as to why we have self?

You already got some good answers. I'll just add my two cents :

class Test:
pass

t = Test()

def fun(self, arg):
self.arg = arg
print self.arg

Test.fun = fun

t.fun(42)
Could you do this without self ?
by the way..six months of python and I'm 10 times the programmer I was
with vb

Enjoy !-)

Bruno
 
D

David Fraser

Roy said:
Yes, you are right, you could design things to work that way. But why
would you want to? Having two ways to do the same thing just adds
complexity without adding my value.

People learning the language have to learn two different things. Some
people will adopt one style, and some will adopt the other. As a
result, we would have two different bodies of code floating around.
You'd end up with things like this:

1) Pythonista A has adopted the "explicit self" style, and convinces his
friend to learn the language. He teaches the "explicit self" style to
his friend.

2) The friend is happy with the new language and goes out into the world
confident that he's added a new and useful skill to his portfolio.

3) The friend picks up a piece of code written by pythonista B, who has
adopted the "implicit self" style, and discovers that he can't make
heads or tails of it.

4) The friend changes his mind about Python, saying, "Gee, if I wanted a
language in which there's more than one way to do it, I would have stuck
with Perl".

5) The Python world has lost another potential convert, ultimately
hastening the end of all intelligent life as we know it.

Actually since method binding is happening anyway the programmer always
has to be aware of it. So I don't think the stylistic change is hard to
follow.

David
 
D

David Fraser

Jeff said:
Another Python design principle is to minimize the number of keywords.
You *could* do that... but it doesn't really gain you anything except an
extra keyword. And I personally find it clearer to see "self" in the
parameter list than to have to think "Oh yeah, this is a method, so
there's an implied self..."
But most importantly, an implicit 'self' would violate the second "Zen
of Python" guideline -- "Explicit is better than implicit." Unless you
can point to a significant *gain* by having 'self' implicit, then it's
better (or at least, more Pythonic) to have it explicit. So far, I've
heard plenty of alternatives to having explicit 'self', but very little
indication of why it would be an improvement other than that it would
allow less typing -- and Python has always placed ease-of-reading over
ease-of-typing. ("Readability counts.")

(Heck, back when I was learning C++, I tended to explicitly use 'this'
when referring to class members/methods even though it was unnecessary,
simply because it made it easier to *see* what was a class member and
what wasn't; the "m_***" naming convention that's often used instead
strikes me as just being a weak way of doing the same thing...)

Jeff Shannon
Technician/Programmer
Credit International

Actually the reason I think its worthwhile having another keyword here
is that Python actually has separate types for functions and methods.
Explicit is better than implicit - at the moment the method binding to
self all happens behind the scenes, and you have bound and unbound
method types that are all produced using the 'def' keyword like
functions, but can actually operate differently.

I think it is more readable, I'm not so concerned about the typing.
There is magic happening here but no evidence for it ... a method
keyword would justify the magic... That's why I still think you should
refer to members of the class using self. rather than having magical
name binding

David
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,581
Members
45,056
Latest member
GlycogenSupporthealth

Latest Threads

Top