newbie: self.member syntax seems /really/ annoying

C

Charles Fox

I've just started playing around with Python, as a possible
replacement for a mix of C++, Matlab and Lisp. The language looks
lovely and clean with one huge exception: I do a lot of numerical
modeling, so I deal with objects (like neurons) described
mathematically in papers, by equations like
a_dot = -k(a-u)
In other languages, this translates nicely into code, but as far as I
can tell, Python needs the ugly:
self.a_dot = -self.k(self.a-self.u)
For large equations this is going to make my code seriously unreadable
to the point of needing to switch back to Matlab -- and it seems to go
against everything else about python's simplicity and elegance. Am I
missing something? Is there something like a 'with' command that lets
me set the scope, like

with self:
.a_dot = -.k(.a-.u)

It's premature to make language suggestions as I am new to the
language, but I would have though that making a 'with self' explicit
in all methods would have been neat, so I could just write
.a_dot = -.k(.a-.u)
which would still avoid confusion with local function variables, since
'.a' is different from 'a'.

Please help if I am missing something -- this looks like a great
language but I am going to mad trying to read numerical code full of
'self.'s breaking up the equations.
 
M

Michele Simionato

I've just started playing around with Python, as a possible
replacement for a mix of C++, Matlab and Lisp. The language looks
lovely and clean with one huge exception: I do a lot of numerical
modeling, so I deal with objects (like neurons) described
mathematically in papers, by equations like
a_dot = -k(a-u)
In other languages, this translates nicely into code, but as far as I
can tell, Python needs the ugly:
self.a_dot = -self.k(self.a-self.u)
For large equations this is going to make my code seriously unreadable
to the point of needing to switch back to Matlab -- and it seems to go
against everything else about python's simplicity and elegance. Am I
missing something? Is there something like a 'with' command that lets
me set the scope, like

with self:
.a_dot = -.k(.a-.u)

It's premature to make language suggestions as I am new to the
language, but I would have though that making a 'with self' explicit
in all methods would have been neat, so I could just write
.a_dot = -.k(.a-.u)
which would still avoid confusion with local function variables, since
'.a' is different from 'a'.

Please help if I am missing something -- this looks like a great
language but I am going to mad trying to read numerical code full of
'self.'s breaking up the equations.

You can always use aliases

a = self.a
u = self.u
....

or even s = self

or play games with dictionaries.


Michele Simionato
 
D

David

Please help if I am missing something -- this looks like a great
language but I am going to mad trying to read numerical code full of
'self.'s breaking up the equations.

You could try this in your functions:

s = self

Then you can use code like this: s.a_dot = s.k(s.a-s.u)

Another option, if you use the vars a lot in a given function, is to
copy them to local vars. This can also slightly speed up your code
(fewer member lookups).
 
D

Diez B. Roggisch

with self:
.a_dot = -.k(.a-.u)

It's premature to make language suggestions as I am new to the
language, but I would have though that making a 'with self' explicit
in all methods would have been neat, so I could just write
.a_dot = -.k(.a-.u)
which would still avoid confusion with local function variables, since
'.a' is different from 'a'.

Please help if I am missing something -- this looks like a great
language but I am going to mad trying to read numerical code full of
'self.'s breaking up the equations.

This is a FAQ - and the short answer is: no, you don't miss anything, and
it's not going change. If you want, you can shorten the expressions like
this:

s = self
s.a * s.b

Or choose any other valid name, e.g. the underscore.

Another (yet rather ugly) alternative would be to push the names into the
global namespace. But that could of course create major mayhem! So take
this with a huge grain of salt:

globals().update(self.__dict__)

a * b

Diez
 
B

Bruno Desthuilliers

Charles Fox a écrit :
I've just started playing around with Python, as a possible
replacement for a mix of C++, Matlab and Lisp. The language looks
lovely and clean with one huge exception: I do a lot of numerical
modeling, so I deal with objects (like neurons) described
mathematically in papers, by equations like
a_dot = -k(a-u)
In other languages, this translates nicely into code, but as far as I
can tell, Python needs the ugly:
self.a_dot = -self.k(self.a-self.u)

"ugliness" is a very subjective notion. As far as I'm concerned, I hate
the "m_myMember" C++ convention, and have always used the 'this' (or
whatever it's named) pointer/reference/pseudo-reference/whatever in
languages where it's implicit - because I don't like such an important
thing to be implicit.

self.a_dot = - self.k(self.a - self.u)
For large equations this is going to make my code seriously unreadable

Ok, but this is another problem.
to the point of needing to switch back to Matlab -- and it seems to go
against everything else about python's simplicity and elegance. Am I
missing something?
Yes.

Is there something like a 'with' command that lets
me set the scope, like

with self:
.a_dot = -.k(.a-.u)

Nope. There's a 'with' statement, but it has nothing to do with this.

The obvious solution to your problem is to make local references to the
needed attributes at the start of your method, ie:

def some_calc(self, whatever):
k = self.k # yes, it works for methods too
a = self.a
u = self.u

self.a_dot = -k(a-u)
It's premature to make language suggestions as I am new to the
language, but I would have though that making a 'with self' explicit
in all methods would have been neat, so I could just write
.a_dot = -.k(.a-.u)
which would still avoid confusion with local function variables, since
'.a' is different from 'a'.

Please help if I am missing something -- this looks like a great
language but I am going to mad trying to read numerical code full of
'self.'s breaking up the equations.

The mandatory 'self' (FWIW, you can name it as you want, 'self' is just
a convention) has long been the topic of lot of debates. While I do
understand your motivations, there are actually good reasons for this
design choice, but understanding these reasons requires some knowledge
of Python's object model internals. As far as I'm concerned, I'm quite
happy with the current design, but I don't do much maths !-)
 
D

David

You could try this in your functions:

s = self

Then you can use code like this: s.a_dot = s.k(s.a-s.u)

Another option, if you use the vars a lot in a given function, is to
copy them to local vars. This can also slightly speed up your code
(fewer member lookups).

Also, there is no rule saying you need to use "self", it's just a
convention. You can declare your methods like this instead:

def foo(s, arg1, arg2):
s.a_dot = s.k(s.a-s.u)
 
R

Ryan Ginstrom

On Behalf Of Charles Fox
described mathematically in papers, by equations like
a_dot = -k(a-u)
In other languages, this translates nicely into code, but as
far as I can tell, Python needs the ugly:
self.a_dot = -self.k(self.a-self.u)

In addition to the other advice you've received, if you don't need to
preserve state, you could avoid the "self" business by putting your
functions in a module instead of an object.

def k(a):
return a**3

def dot(a, u)
return -k(a-u)

Python modules are also objects, so they can serve in place of class
instances much of the time.

Regards,
Ryan Ginstrom
 
J

Jeremy Sanders

Charles said:
I've just started playing around with Python, as a possible
replacement for a mix of C++, Matlab and Lisp. The language looks
lovely and clean with one huge exception: I do a lot of numerical
modeling, so I deal with objects (like neurons) described
mathematically in papers, by equations like

I thought it was horrible when I started, but now when looking at somebody
else's C++ code I find it very hard to work out whether something is a
global, a member or a local variable, unless they use some sort of naming
convention.

If you alias self as "s", it's only two more characters per variable access,
which is the same as the C++ "m_" naming convention.
 
S

Steven D'Aprano

I've just started playing around with Python, as a possible replacement
for a mix of C++, Matlab and Lisp. The language looks lovely and clean
with one huge exception: I do a lot of numerical modeling, so I deal
with objects (like neurons) described mathematically in papers, by
equations like
a_dot = -k(a-u)
In other languages, this translates nicely into code, but as far as I
can tell, Python needs the ugly:
self.a_dot = -self.k(self.a-self.u)

I think you've been seriously mislead. You don't NEED self. That's only
for writing classes.

Although Python is completely object oriented, and everything is an
object, you don't have to put your code in classes.

Instead of doing something like this:

class Adder(object):
"""Pointless class to add things."""
def __init__(self, value):
self.value = other
def add(self, other):
x = self.value + other
return float(x)

you don't need a class. Just write a function:

def add(x, other):
"""Function that adds other to x."""
return float(x + other)

Here's how I would write your function above:

def function(a, u, k):
"""Calculate a_dot from a, u and k."""
return -k(a-u)

And here is how I would use it:

a = 57 # or whatever...
u = 54
k = 3
a_dot = function(a, u, k)


See? Not a single "self" in sight.


You might also like to read about a strange, bizarre programming that
forces you to put everything inside classes:

http://steve-yegge.blogspot.com/2006/03/execution-in-kingdom-of-nouns.html
 
D

Dave Hansen

I've just started playing around with Python, as a possible
replacement for a mix of C++, Matlab and Lisp. The language looks
lovely and clean with one huge exception: I do a lot of numerical
modeling, so I deal with objects (like neurons) described
mathematically in papers, by equations like
a_dot = -k(a-u)
In other languages, this translates nicely into code, but as far as I
can tell, Python needs the ugly:
self.a_dot = -self.k(self.a-self.u)
For large equations this is going to make my code seriously unreadable
to the point of needing to switch back to Matlab -- and it seems to go
against everything else about python's simplicity and elegance. Am I

It goes back to the Zen of Python (import this): Explicit is better
than implicit. And it's a boon to future maintainers of your code
missing something? Is there something like a 'with' command that lets
me set the scope, like

with self:
.a_dot = -.k(.a-.u)

The name "self" is just a convention. You can give it any name you
wish. Using "s" is common.

As others have mentioned, you can also provide local synonyms if the
dot syntax is too onerous. But make sure you use the member access
syntax if the result of an expression is an immutable type. For
example, I assume a_dot is a mutable type, such as a list. If so,
then you could simply use

a_dot, k, a, u = self.a_dot, self.k, self.a, self.u
a_dot = -k(a-u)

However, if it's an immutable type, such as a scalar, strung, or
tuple, you need

self.a_dot = -k(a-u)

And it gets trickier if you have members taking intermediate values...
It's premature to make language suggestions as I am new to the

That's for sure ;-)

Regards,

-=Dave
 
B

Bruno Desthuilliers

Dave Hansen a écrit :
(snip)
As others have mentioned, you can also provide local synonyms if the
dot syntax is too onerous. But make sure you use the member access
syntax if the result of an expression is an immutable type. For
example, I assume a_dot is a mutable type, such as a list. If so,
then you could simply use

a_dot, k, a, u = self.a_dot, self.k, self.a, self.u
a_dot = -k(a-u)

However, if it's an immutable type, such as a scalar, strung, or
tuple, you need

self.a_dot = -k(a-u)

Hmmm... Actually, whether self.a_dot is an instance of a mutable or
immutable type won't change anything - in both case, it's only the
*local* name a_dot that'll be rebound. So <op> as soon as you want to
rebind (iow:assign to) an attribute, you *need* to use
self.the_attr_name on the LHS.

Of course, *mutating* is a different situation...
 
C

Charles Fox

Thanks guys -- yeah these two stategies (short s.varname; and explicit
rescoping, a=self.a etc) are more or less what I was using. That's
still kind of annoying though.

The s.varname approach still makes numerical code much harder to read.

I had a nasty bug with the boilerplate approach when forgetting to
reassign some of the variables back to members (self.a=a). And that's
a lot of boilerplate you need -- I thought the python way was to
minimize redundant code? (Ditching header files and curley brackets
was a main reason for me coming here).

I see the argument for making self explicit -- what would be wrong
with just .a instead of self.a though? That's still explicit but much
easier to read. (I think I've seen that somewhere else, is it C#?)
 
T

Tim Golden

Charles said:
Thanks guys -- yeah these two stategies (short s.varname; and explicit
rescoping, a=self.a etc) are more or less what I was using. That's
still kind of annoying though.

The s.varname approach still makes numerical code much harder to read.

I had a nasty bug with the boilerplate approach when forgetting to
reassign some of the variables back to members (self.a=a). And that's
a lot of boilerplate you need -- I thought the python way was to
minimize redundant code? (Ditching header files and curley brackets
was a main reason for me coming here).

I see the argument for making self explicit -- what would be wrong
with just .a instead of self.a though? That's still explicit but much
easier to read. (I think I've seen that somewhere else, is it C#?)

Charles, while you are quite right to air your ideas, do bear in mind
that this issue has been thrashed out again and again on this group
and in other forums. I hope you have at least read the FAQ:

http://www.python.org/doc/faq/gener...ed-explicitly-in-method-definitions-and-calls

and PEP 3099:

http://www.python.org/dev/peps/pep-3099/

If you take the trouble to search the archives of this list alone
for, say, explicit+self, you'll see that there are quite strong arguments
(and argumentors) on both sides. In that sort of situation the status quo
tends to hold sway. (And in this case, GvR has only recently responded to
similar comments by Bruce Eckels -- a couple of heavyweights -- in a way
which makes it unlikely that this is going to change).

I think it's one of those things which comes down, fairly enough, to: we
do things this way and it works for us; other languages do other things
and it works for them.

TJG
 
M

Michele Simionato

Thanks guys -- yeah these two stategies (short s.varname; and explicit
rescoping, a=self.a etc) are more or less what I was using. That's
still kind of annoying though.

The s.varname approach still makes numerical code much harder to read.

I had a nasty bug with the boilerplate approach when forgetting to
reassign some of the variables back to members (self.a=a). And that's
a lot of boilerplate you need -- I thought the python way was to
minimize redundant code? (Ditching header files and curley brackets
was a main reason for me coming here).

You still can play with dictionaries, for instance:

def __init__(self, a, b, c):
vars(self).update(locals())

correspond to

self.a = a
self.b = b
self.c = c

(and actually also to self.self =self).
I see the argument for making self explicit -- what would be wrong
with just .a instead of self.a though? That's still explicit but much
easier to read. (I think I've seen that somewhere else, is it C#?)

This has been proposed many times. But self is handy because you can
give
a different name to it: for instance it becomes cls when you are
inside a classmethod.


Michele Simionato
 
G

Grant Edwards

I think it's one of those things which comes down, fairly
enough, to: we do things this way and it works for us; other
languages do other things and it works for them.

But not as nearly well as our way works for us, of course. ;)
 
J

J. Clifford Dyer

Thanks guys -- yeah these two stategies (short s.varname; and explicit
rescoping, a=self.a etc) are more or less what I was using. That's
still kind of annoying though.

The s.varname approach still makes numerical code much harder to read.

For what it's worth, if you stick with python for a while, you will stop noticing the self, and be able to see what you're looking for quite clearly.

Moreso if you use s.

Cheers,
Cliff
 
K

kyosohma

Charles said:
I've just started playing around with Python, as a possible
replacement for a mix of C++, Matlab and Lisp. The language looks
lovely and clean with one huge exception: I do a lot of numerical
modeling, so I deal with objects (like neurons) described
mathematically in papers, by equations like
a_dot = -k(a-u)
In other languages, this translates nicely into code, but as far as I
can tell, Python needs the ugly:
self.a_dot = -self.k(self.a-self.u)
For large equations this is going to make my code seriously unreadable
to the point of needing to switch back to Matlab -- and it seems to go
against everything else about python's simplicity and elegance. Am I
missing something? Is there something like a 'with' command that lets
me set the scope, like

with self:
.a_dot = -.k(.a-.u)

It's premature to make language suggestions as I am new to the
language, but I would have though that making a 'with self' explicit
in all methods would have been neat, so I could just write
.a_dot = -.k(.a-.u)
which would still avoid confusion with local function variables, since
'.a' is different from 'a'.

Please help if I am missing something -- this looks like a great
language but I am going to mad trying to read numerical code full of
'self.'s breaking up the equations.

I don't know if it'll help or not, but you might try using matplotlib,
numpy or pymat. One of those may make it easier to do your
calculations.

Mike
 
C

Chris Mellon

Thanks guys -- yeah these two stategies (short s.varname; and explicit
rescoping, a=self.a etc) are more or less what I was using. That's
still kind of annoying though.

The s.varname approach still makes numerical code much harder to read.

I had a nasty bug with the boilerplate approach when forgetting to
reassign some of the variables back to members (self.a=a). And that's
a lot of boilerplate you need -- I thought the python way was to
minimize redundant code? (Ditching header files and curley brackets
was a main reason for me coming here).

I see the argument for making self explicit -- what would be wrong
with just .a instead of self.a though? That's still explicit but much
easier to read. (I think I've seen that somewhere else, is it C#?)


This is terrible and horrible, please don't use it. That said,
presenting the magic implicit_self context manager!

from __future__ import with_statement
import sys

class implicit_self(object):
def __init__(self, obj):
self.obj = obj
def __enter__(self):
local = sys._getframe(1).f_locals
local.update(self.obj.__dict__)
def __exit__(self, exc, obj, tb):
local = sys._getframe(1).f_locals
for k in self.obj.__dict__:
setattr(self.obj, k, local[k])

if __name__ == '__main__':
class Test(object):
pass
t = Test()
t.a = 10
t.b = 20
with implicit_self(t):
print a
print b
a = 40
b = a * 2

print t.a
print t.b
 
N

Neil Cerutti

This has been proposed many times. But self is handy because
you can give a different name to it: for instance it becomes
cls when you are inside a classmethod.

The treatment of self in the function's parameter list seems to
be the pitfall of any .member shortcut proposal. Most proposals
don't even address that point.

Does it become:

class Foo:
def __init__():
.bar = 40

or

class Foo:
def __init__(.):
.bar = 40

or

class Foo:
def __init__(self):
.bar = 40

I guess the middle one is the most consistent, but it seems
ugly compared to what we have now.
 
A

Alex Martelli

Chris Mellon said:
This is terrible and horrible, please don't use it. That said,
presenting the magic implicit_self context manager!

....which doesn't work in functions -- just try changing your global
code:
with implicit_self(t):
print a
print b
a = 40
b = a * 2

into a function and a call to it:

def f():
with implicit_self(t):
print a
print b
a = 40
b = a * 2
f()

....even with different values for the argument to _getframe. You just
can't "dynamically" add local variables to a function, beyond the set
the compiler has determined are local (and those are exactly the ones
that are *assigned to* in the function's body -- no less, no more --
where "assigned to" includes name-binding statements such as 'def' and
'class' in addition to plain assignment statements, of course).

Making, say, 'a' hiddenly mean 'x.a', within a function, requires a
decorator that suitably rewrites the function's bytecode... (after
which, it WOULD still be terrible and horrible and not to be used, just
as you say, but it might at least _work_;-). Main problem is, the
decorator needs to know the set of names to be "faked out" in this
terrible and horrible way at the time the 'def' statement executes: it
can't wait until runtime (to dynamically determine what's in var(self))
before it rewrites the bytecode (well, I guess you _could_ arrange a
complicated system to do that, but it _would_ be ridiculously slow).

You could try defeating the fundamental optimization that stands in your
way by adding, say,
exec 'pass'
inside the function-needing-fakeouts -- but we're getting deeper and
deeper into the mire...;-)


Alex
 

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,756
Messages
2,569,535
Members
45,008
Latest member
obedient dusk

Latest Threads

Top