473,836 Members | 1,472 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

the annoying, verbose self

Is there any trick to get rid of having to type the annoying,
character-eating "self." prefix everywhere in a class? Sometimes I
avoid OO just not to deal with its verbosity. In fact, I try to use
Ruby anywhere speed is not crucial especially for @ prefix is better-
looking than self.

But things grow -- is there any metaprogramming tricks or whatnot we
can throw on the self?

Cheers,
Alexy
Nov 21 '07
84 7241
On Sat, 24 Nov 2007 09:12:34 +0100, Ton van Vliet wrote:
Just bringing up something I sometimes miss from good-old Turbo-Pascal
here, which has the WITH statement to reduce the typing overhead with
(long) record/struct prefixes, used like:

with <prefixdo begin
a = ...
b = ...
end;

where all variables would be automatically prefixed with the <prefix>
(if present in the already available record definition!)
And here lies the problem: The compiler decides at compile time which
names are local to a function and there is no equivalent of a record
definition to make that decision.

Ciao,
Marc 'BlackJack' Rintsch
Nov 24 '07 #31
Ton Van Vliet:
[... using/with ...]
This looks like a really nice little construct, and solves my small
quirk issue (which has popped up maybe twice in my python experience).
It could also be a solution to the OP's problem. The issue of course
is disambiguation. Is EVERY name looked up in the tagged object, or
only assignments? Does it copy attributes over and make everything
local and then copy it back at the end (like you would kind of expect
in a function)? Or is everything routed to the parent. It gets very
sticky very fast, but since it's in a block, the issues aren't as evil
as when they show up if you try to get rid of self altogether. It
also solves more than just the self issue, allowing you to more
quickly assign multiple attributes of an object as well.

In your example:

def somefunction(se lf, ...):
using self:
a = ...
b = ...
...
c = a + b

The biggest issue is, what if you need to do more:

def somefunction(se lf, ...):
using self:
a = ...
b = ...
c = a + int(b)

What is int? Is it self.int? I suppose the simplest solution is to:
always assign as an attribute, and lookup as an attribute first going
to normal lookup rules after that.

As far as using [xxx], I don't think the interpreter needs to deal
with [xxx] until it actually executes the line. [xxx] would just be a
normal python expression, the result of which is used for the
attribute lookup and assignments within the block.

This would somewhat solve the toy vector example:

def abs(self):
using self:
return math.sqrt(x*x + y*y + z*z)

Unfortunately the performance would be slightly worse do to the extra
lookup rules (self.math? no, self.__getattr_ _(math)? no,
self.parentclas s.__getattr__(m ath)? no, etc)

The OP will probably say, "why not build the [using self] block into a
method definition":

def abs():
return math.sqrt(x*x .....

But this would cause problems and slowdown for pretty much all python
code in existence, and reopens the whole discussion of why removing
self is bad :)

Anyway, I'm for the "using" construct, as unlikely as it is. It's not
necessary, but something similar could help alleviate a bit of the
tedium that is perceived by some python users, without affecting
anyone else.

Of course, this is all theory, and it's unknown (by me) if the python
compiler can even handle such a thing. Even if it could, it's
probably not an easy task.
Nov 24 '07 #32
On Nov 23, 7:16 pm, "Patrick Mullen" <saluk64...@gma il.comwrote:
Most of the time self doesn't bother me in the slightest. The one
time it does bother me however, is when I am turning a function into a
method. In this case, often I have many local variables which I
actually want to be instance variables, so I have to add self to all
of them. Of course, this is going to cause me some grief no matter
which language I am using. If it was enough trouble, it wouldn't be
hard to make a filter that converts my code automatically.
I've had the same thought, along with another. You see, on of my pet
peeves about all OO languages that that when creating new code, I
generally begin by writing something like this:

cat = 'felix'
dog = 'rover'
def example():
global cat, dog # not always required, but frequently needed
return ', '.join((cat, dog))

Later, I inevitably decide to encapsulate it inside a class, which
means lots of source changes to change my function into a method:

class my_pets:
cat = 'felix'
dog = 'rover'
def example(self):
return ', '.join((self.ca t, self.dog))

My idea is to introduce syntax that treats top-level functions as
methods of a global, anonymous, class:

cat = 'felix'
dog = 'rover'
def example():
return ', '.join((.cat, .dog))

(btw, we'll also stop auto-magically recognizing global variables
inside functions, forcing the use of the '.' in global names.) Thus,
to convert the above into a class, we just need to add one line and
alter the indentation:

class my_pets:
cat = 'felix'
dog = 'rover'
def example(): # anonymous 'self' is implicit inside class defs.
return ', '.join((.cat, .dog))

You'd need someway to refer to higher lexical levels, possibly by
chaining periods; this would break ellipsis but that could be replaced
by a keyword such as 'to'. And you'd probably want to keep 'global',
but as a keyword for those rare cases where you need to force a
reference to the outer-most lexical level:

warming = 42
def generator(facti od):
def decorator(func) :
def wrapper(*args, **kwds):
if ..factoid == None:
return .func(*args, **kwds)
else:
return ..factoid + global.warming
return wrapper
return decorator
Nov 24 '07 #33
On Sat, 24 Nov 2007 01:55:38 -0800, samwyse wrote:
I've had the same thought, along with another. You see, on of my pet
peeves about all OO languages that that when creating new code, I
generally begin by writing something like this:

cat = 'felix'
dog = 'rover'
def example():
global cat, dog # not always required, but frequently needed
return ', '.join((cat, dog))
Ouch that's bad design IMHO. The need to use ``global`` is a design
smell, if needed *frequently* it starts to stink.

Ciao,
Marc 'BlackJack' Rintsch
Nov 24 '07 #34
On Nov 24, 4:07 am, Marc 'BlackJack' Rintsch <bj_...@gmx.net wrote:
On Sat, 24 Nov 2007 01:55:38 -0800, samwyse wrote:
I've had the same thought, along with another. You see, on of my pet
peeves about all OO languages that that when creating new code, I
generally begin by writing something like this:
cat = 'felix'
dog = 'rover'
def example():
global cat, dog # not always required, but frequently needed
return ', '.join((cat, dog))

Ouch that's bad design IMHO. The need to use ``global`` is a design
smell, if needed *frequently* it starts to stink.
I'm not sure what you mean. In the example that I gave, the 'global'
statement isn't needed. However, here's a different example:
>>top_score = 0
def leaderboard(my_ score):
if my_score top_score:
print "A new high score!"
top_score = myscore
print "Top score:", top_score

Traceback (most recent call last):
File "<pyshell#4 9>", line 1, in <module>
leaderboard(7, 'samwyse')
File "<pyshell#4 7>", line 2, in leaderboard
if my_score top_score:
UnboundLocalErr or: local variable 'top_score' referenced before
assignment
Nov 24 '07 #35
BJörn Lindqvist wrote:
On Nov 22, 2007 2:08 PM, Colin J. Williams <cj*@sympatico. cawrote:
>>be*********** *@lycos.com wrote:
>>>Alexy:

Sometimes I
avoid OO just not to deal with its verbosity. In fact, I try to use
Ruby anywhere speed is not crucial especially for @ prefix is better-
looking than self.

Ruby speed will increase, don't worry, as more people will use it.

Bye,
bearophile

I don't see this as a big deal, but


The big deal is that "self." occupies important horizontal screen real
estate. That is, it is usually not self in itself that is problematic,
but the overflowing lines is. Take this silly vector class for
example:

1 class Vector:
2 def __init__(self, x, y, z):
3 self.x = x
4 self.y = y
5 self.z = z
6 def abs(self):
7 return math.sqrt(self. x * self.x + self.y * self.y +
self.z * self.z)

Line 7 is 82 characters long which is, if you care about the
readability of your code, a very real problem because the line is to
long. So you break it:

7 return math.sqrt(self. x * self.x +
self.y * self.y +
self.z * self.z)

Better, but definitely not as nice as it would have been with a
shorter self prefix like you propose. And in my eyes, having to break
lines like this instantly makes the code much less attractive. There
is probably not a single language in existance in which wrapping lines
doesn't make the code uglier.

I also notice that the lines in your mail are nicely broken at about
column 45, probably because you are typing on a PDA or similar? In
those situations, where you require much shorter lines than the
standard 78 characters, for example when typesetting code examples for
a book, the problem with line breaks is even worse.

>>suppose that the syntax were
expanded so that, in a method, a dot
".", as a precursor to an identifier,
was treated as "self." is currently treated?


I like that a lot. This saves 12 characters for the original example
and removes the need to wrap it.

7 return math.sqrt(.x * .x + .y * .y + .z * .z)

+1 Readability counts, even on small screens.

Below is my coding standard - I'm lazy, even lazy to persuade
comutinties into strange (imho) language syntax extensions.
class Vector:
def __init__(s, x, y, z):
s.x = x
s.y = y
s.z = z
def abs(s):
return math.sqrt(s.x * s.x + s.y * s.y + s.z * s.z)

Admit that changing habits may be more difficult then to change a
language syntax.

Jakub

occasional lamerish Python user
Nov 24 '07 #36
On 24 Nov 2007 08:48:30 GMT, Marc 'BlackJack' Rintsch <bj****@gmx.net >
wrote:
>On Sat, 24 Nov 2007 09:12:34 +0100, Ton van Vliet wrote:
>Just bringing up something I sometimes miss from good-old Turbo-Pascal
here, which has the WITH statement to reduce the typing overhead with
(long) record/struct prefixes, used like:

with <prefixdo begin
a = ...
b = ...
end;

where all variables would be automatically prefixed with the <prefix>
(if present in the already available record definition!)

And here lies the problem: The compiler decides at compile time which
names are local to a function and there is no equivalent of a record
definition to make that decision.
The whole clause following 'using self:' could be seen as the record
definition: all attribute assignments/bindings in there should be
prefixed with 'self' (if not already existing in the self namespace?)
and thereby become instance attributes, which outside the 'using self'
clause still need 'self.' as the (namespace?) prefix.

It would not bring an 'implicit' self, but could possibly improve
readability in some areas (btw, personally, I don't have anything
against the 'explicit' self in general)

Even in Pascal the 'with' statement was not meant to improve speed,
but merely for readability, especially with complex records.

Please, bear with me, I am relatively new to Python (reading books,
scanning newsgroups, etc) and feel in no way capable of giving
'educated' or 'well overthought' advise, just my 2 cents ;-)

--
Ton
Nov 24 '07 #37
On Sat, 24 Nov 2007 02:54:27 -0800, samwyse wrote:
On Nov 24, 4:07 am, Marc 'BlackJack' Rintsch <bj_...@gmx.net wrote:
>On Sat, 24 Nov 2007 01:55:38 -0800, samwyse wrote:
I've had the same thought, along with another. You see, on of my pet
peeves about all OO languages that that when creating new code, I
generally begin by writing something like this:
cat = 'felix'
dog = 'rover'
def example():
global cat, dog # not always required, but frequently needed
return ', '.join((cat, dog))

Ouch that's bad design IMHO. The need to use ``global`` is a design
smell, if needed *frequently* it starts to stink.

I'm not sure what you mean. In the example that I gave, the 'global'
statement isn't needed. However, here's a different example:
I mean that global names that are (re)bound from within functions couple
these functions in a non-obvious way and make the code and data flow harder
to follow and understand. Also it makes refactoring and testing more
difficult because of the dependencies.

Ciao,
Marc 'BlackJack' Rintsch
Nov 24 '07 #38
On Sat, 24 Nov 2007 14:09:04 +0100, Ton van Vliet wrote:
On 24 Nov 2007 08:48:30 GMT, Marc 'BlackJack' Rintsch <bj****@gmx.net >
wrote:
>>On Sat, 24 Nov 2007 09:12:34 +0100, Ton van Vliet wrote:
>>Just bringing up something I sometimes miss from good-old Turbo-Pascal
here, which has the WITH statement to reduce the typing overhead with
(long) record/struct prefixes, used like:

with <prefixdo begin
a = ...
b = ...
end;

where all variables would be automatically prefixed with the <prefix>
(if present in the already available record definition!)

And here lies the problem: The compiler decides at compile time which
names are local to a function and there is no equivalent of a record
definition to make that decision.

The whole clause following 'using self:' could be seen as the record
definition: all attribute assignments/bindings in there should be
prefixed with 'self' (if not already existing in the self namespace?)
and thereby become instance attributes, which outside the 'using self'
clause still need 'self.' as the (namespace?) prefix.
So::

def meth(self):
using self:
tmp = raw_input('Ente r age: ')
age = int(tmp)

becomes::

def meth(self):
using self:
self.tmp = self.raw_input( 'Enter age: ')
self.age = self.int(tmp)

Binding `tmp` unnecessarily to the object and trying to get `raw_input()`
and `int()` from the object. Ouch. :-)

Ciao,
Marc 'BlackJack' Rintsch
Nov 24 '07 #39
On 24 Nov 2007 13:56:37 GMT, Marc 'BlackJack' Rintsch <bj****@gmx.net >
wrote:
>On Sat, 24 Nov 2007 14:09:04 +0100, Ton van Vliet wrote:
>On 24 Nov 2007 08:48:30 GMT, Marc 'BlackJack' Rintsch <bj****@gmx.net >
wrote:
>>>On Sat, 24 Nov 2007 09:12:34 +0100, Ton van Vliet wrote:

Just bringing up something I sometimes miss from good-old Turbo-Pascal
here, which has the WITH statement to reduce the typing overhead with
(long) record/struct prefixes, used like:

with <prefixdo begin
a = ...
b = ...
end;

where all variables would be automatically prefixed with the <prefix>
(if present in the already available record definition!)

And here lies the problem: The compiler decides at compile time which
names are local to a function and there is no equivalent of a record
definition to make that decision.

The whole clause following 'using self:' could be seen as the record
definition: all attribute assignments/bindings in there should be
prefixed with 'self' (if not already existing in the self namespace?)
and thereby become instance attributes, which outside the 'using self'
clause still need 'self.' as the (namespace?) prefix.

So::

def meth(self):
using self:
tmp = raw_input('Ente r age: ')
age = int(tmp)

becomes::

def meth(self):
using self:
self.tmp = self.raw_input( 'Enter age: ')
self.age = self.int(tmp)

Binding `tmp` unnecessarily to the object and trying to get `raw_input()`
and `int()` from the object. Ouch. :-)
Absolutely.

However, I was more thinking in terms of attributes only, like this:

def meth(self):
using self:
self.tmp = raw_input('Ente r age: ')
self.age = int(self.tmp)

and for the methods check whether there *is* a self.<methoddef ined
in the class (or even within the 'using' clause), then use it, or else
leave it as it is.

It would require more 'lookup' work, but we're talking 'readability'
here (which would btw not bring much in the example you give ;-)

It would boil down to choice: explicit/speed vs implicit/readability

--
ci vediamo
Ton
Nov 24 '07 #40

This thread has been closed and replies have been disabled. Please start a new discussion.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.