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 7242
For these localized initialization blocks, I don't see anything wrong
with:
_ = self
_.var1 = 5
_.var2 = "a value"
_.var3 = stuff
_.var4 = [2,54,7,7]
_.var5 = "dingaling"
_.var6 = 6.4
_.var7 = 1
_.var8 = False
_.var9 = True
Or if you wanted to simulate something like using or with:
for _ in [self]:
_.var1 = 5
_.var2 = "a value"
_.var3 = stuff
_.var4 = [2,54,7,7]
_.var5 = "dingaling"
_.var6 = 6.4
_.var7 = 1
_.var8 = False
_.var9 = True
-- Paul
-- Paul
Steven D'Aprano wrote:
On Fri, 23 Nov 2007 23:38:24 +0000, BJÃ¶rn Lindqvist
wrote:
>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.
-2 Readability counts, and your example is a lot less readable.
For your example to be even *slightly* readable, you have to fill the
expression with excessive whitespace. A little bit of whitespace is good.
Too much breaks the flow of the expression and hurts readability.
Or perhaps I should say:
T o o m u c h b r e a k s t h e f l o w . . .
You write: math.sqrt(.x * .x + .y * .y + .z * .z)
which to my eyes has too much whitespace, but the alternative is worse:
math.sqrt(.x*.x + .y*.y + .z*.z)
and this is positively painful to try to read, it looks like line-noise:
math.sqrt(.x*.x +.y*.y+.z*.z)
The correct solution to your example is to get rid of the attribute
lookups from the expression completely:
def abs(self):
x, y, z = self.x, self.y, self.z
return math.sqrt(x**2 + y**2 + z**2)
It's probably also faster, because it looks up the attributes only once
each, instead of twice.
Alternatively, as someone else
suggested, an analogue of the Pascal "with"
could be used:
def abs(self):
with self:
return math.sqrt(x**2 + y**2 + z**2)
As has already been pointed out, "with"
has been pre-empted (unfortunately,
in my view) for another purpose.
This form could be generalized to "with
aa" where aa is any object with
attributes accessible with the z= aa.z
or aa.z.= z style.
This should not apply to special names,
such as __add__ etc.
Colin W.
>
Steven D'Aprano wrote:
On Fri, 23 Nov 2007 23:38:24 +0000, BJÃ¶rn Lindqvist
wrote:
>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.
-2 Readability counts, and your example is a lot less readable.
For your example to be even *slightly* readable, you have to fill the
expression with excessive whitespace. A little bit of whitespace is good.
Too much breaks the flow of the expression and hurts readability.
Or perhaps I should say:
T o o m u c h b r e a k s t h e f l o w . . .
You write: math.sqrt(.x * .x + .y * .y + .z * .z)
which to my eyes has too much whitespace, but the alternative is worse:
math.sqrt(.x*.x + .y*.y + .z*.z)
and this is positively painful to try to read, it looks like line-noise:
math.sqrt(.x*.x +.y*.y+.z*.z)
The correct solution to your example is to get rid of the attribute
lookups from the expression completely:
def abs(self):
x, y, z = self.x, self.y, self.z
return math.sqrt(x**2 + y**2 + z**2)
It's probably also faster, because it looks up the attributes only once
each, instead of twice.
Alternatively, as someone else
suggested, an analogue of the Pascal "with"
could be used:
def abs(self):
with self:
return math.sqrt(x**2 + y**2 + z**2)
As has already been pointed out, "with"
has been pre-empted (unfortunately,
in my view) for another purpose.
This form could be generalized to "with
aa" where aa is any object with
attributes accessible with the z= aa.z
or aa.z.= z style.
This should not apply to special names,
such as __add__ etc.
Colin W.
>
I like the explicit "self", personally. It helps distinguish class
methods from functions. When I see a "self" I think "A-ha, a class
method". Of course, I could tell that from just the indentation and
following that back to the class declaration, but as a quick reference
I find it helpful. Besides, none of the proposals have sufficinetly
dealt with lexical scope without introducing a lot of costly checks
which would also hide the complexity of the process (and thereby, most
likely, lead to abuse and bad practices).
Regards,
Jordan
On Nov 24, 1:10 pm, "Patrick Mullen" <saluk64...@gma il.comwrote:
If there were a "using" or if the with statement would handle
something like this, I wouldn't use it. "s." is only 2 characters. I
saw chained dots mentioned. Chained dots are 2 characters. Why are
we still discussing this? "s." is the answer, or pulling the
attributes into local vars if you are going to use them many times, to
save lookup. This is not a band-aid, this is an actual valid
programming technique. There is more to programming than typing...
Actually, the chained dots are solving a completely different problem,
that of refactoring a collection of functions that use global vars
into a class.
Although I'm now wondering if I could jigger something together using
globals() to make a top-level self-like object. Hmmm, maybe someting
like this:
>>class GlobalSelf(obje ct):
def __init__(self):
self.__dict__ = globals()
>>x = 42 def myfunc(*args):
"something that I may want to refactor later"
s = GlobalSelf()
s.x += 1
>>x
42
>>myfunc() x
43
"Colin J. Williams" <cj*@sympatico. cawrote in message
news:ma******** *************** *************** *@python.org...
Alternatively, as someone else suggested, an analogue of the Pascal "with"
could be used:
def abs(self):
with self:
return math.sqrt(x**2 + y**2 + z**2)
How does your suggested "with" statement know to transform x into self.x but
not transform math.sqrt into self.math.sqrt?
Andrew Koenig wrote:
"Colin J. Williams" <cj*@sympatico. cawrote in message
news:ma******** *************** *************** *@python.org...
>Alternativel y, as someone else suggested, an analogue of the Pascal "with" could be used:
def abs(self): with self: return math.sqrt(x**2 + y**2 + z**2)
How does your suggested "with" statement know to transform x into self.x but
not transform math.sqrt into self.math.sqrt?
I am not advocating this, but this could be:
def abs(self):
with self:
with math:
return sqrt(x**2 + y**2 + z**2)
The idea being that "with self" use
creates a new namespace:
newGlobal= oldGlobal + oldLocal
newLocal= names from self
Similarly, "with math" creates a newer
namespace:
newerGlobal= newGlobal + newLocal
newerLocal= names from math
My guess is that there would be little
use for nesting the
"with".
Colin W.
Andrew Koenig wrote:
"Colin J. Williams" <cj*@sympatico. cawrote in message
news:ma******** *************** *************** *@python.org...
>Alternativel y, as someone else suggested, an analogue of the Pascal "with" could be used:
def abs(self): with self: return math.sqrt(x**2 + y**2 + z**2)
How does your suggested "with" statement know to transform x into self.x but
not transform math.sqrt into self.math.sqrt?
I am not advocating this, but this could be:
def abs(self):
with self:
with math:
return sqrt(x**2 + y**2 + z**2)
The idea being that "with self" use
creates a new namespace:
newGlobal= oldGlobal + oldLocal
newLocal= names from self
Similarly, "with math" creates a newer
namespace:
newerGlobal= newGlobal + newLocal
newerLocal= names from math
My guess is that there would be little
use for nesting the
"with".
Colin W.
I am not advocating this, but this could be:
def abs(self):
with self:
with math:
return sqrt(x**2 + y**2 + z**2)
The idea being that "with self" use
creates a new namespace:
newGlobal= oldGlobal + oldLocal
newLocal= names from self
You don't know what those names are until runtime. Suppose, for example,
that self happens to have acquired an attribute named "math"? Then
with self:
with math:
return sqrt(x**2 + y**2 + z**2)
doesn't do what you expected, because "with math" turns out to have meant
"with self.math"
The issue of lexical scope still looms large on the horizon. How does
one distinguish between attributes (as scoped by the "with" clause),
local/global variables, and function/method calls? There doesn't seem
to be an easy way. You'd need multiple passes over the data to
determine various scopes -- and for what, to save typing a few
characters? And even if implemented, it would mean hiding the
complexity of the resolution, which is not a good thing.
Regards,
Jordan This thread has been closed and replies have been disabled. Please start a new discussion. | |