But things grow -- is there any metaprogramming tricks or whatnot we
can throw on the self?
Cheers,
Alexy
The most common answer you are going to get is that explicit is better
than implicit, which I tend to agree with. Some people use 's' instead
of 'self'. This shortens the number of characters you have to type, and
is only one character more than the Ruby '@' prefix.
Here is a metaprogramming technique that removes self, but I don't
recommend these sorts of things, especially if other people are going to
be looking at your code in the future. So use it at your own risk!
http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/362305
-Farshid
def foo( self ):
becomes
def foo( s ):
Otherwise, if you happen to be using self.something a lot, just
assign it to a variable, and use that. But be careful as that
can become a lot more difficult to read/maintain than simply
leaving self along to begin with.
ss = self.something
ss.foo()
To me, using 'self' in Python is no different than using some other
variable pointing to a class instance in a static C++ class function.
-James
> Is there any trick to get rid of having to type the annoying,
> character-eating "self." prefix everywhere in a class?
Oh I know! It' uch a pain. Sinc writing a hug cla lat wk, I'v had a
trribl hortag o lowrca S E L and F charactr. It mak writing vry annoying.
> Sometimes I avoid OO just not to deal with its verbosity.
There are other values than brevity. In fact, brevity is one of the less
important values.
> In fact, I try to use
> Ruby anywhere speed is not crucial especially for @ prefix is better-
> looking than self.
Well, it takes all sorts I suppose. Who would those with good taste mock
if everybody liked the same things?
> But things grow -- is there any metaprogramming tricks or whatnot we can
> throw on the self?
Oh yeah, that's just what I like to see! Complicated, brittle, hard to
debug, difficult to understand metaprogramming tricks in preference to a
simple, easy-to-read naming convention.
--
Steven.
You got this highly flexible language, very good for rapid programming, no more
clutter from block brackets and variable declarations, and now this 'self' pops
up.
So much overhead....
Can the computer not decide by itself what I want stored in the object? It can
read my code too!
> Oh I know! It' uch a pain. Sinc writing a hug cla lat wk, I'v had a
> trribl hortag o lowrca S E L and F charactr. It mak writing vry annoying.
Yes annoying isn't it?
Last week I was programming in C++ again, and now I have this terrible sur-plus
of lowercase T H I and S letters. I don't understand how they do it (I used to,
but not any more).
Maybe we should setup an exchange program so everybody can trade letters with
each other.
>> Sometimes I avoid OO just not to deal with its verbosity.
>
> There are other values than brevity. In fact, brevity is one of the less
> important values.
NO! You got it all wrong here! It is not about brevity, it is about SPEED.
With less letters, there is less to read, so it can be read faster, so it must
be better!
Just like "if x:" is MUCH BETTER than "if x != 0:"
The thing that should be fixed imho, is that the brain of some of us tries to
deduce higher levels of abstractions from what is essentially a very long line
of simple instructions.
>> But things grow -- is there any metaprogramming tricks or whatnot we can
>> throw on the self?
>
> Oh yeah, that's just what I like to see! Complicated, brittle, hard to
> debug, difficult to understand metaprogramming tricks in preference to a
> simple, easy-to-read naming convention.
Maybe we should state first which variables we want to store in self, and then
have a meta-programming hook that automatically puts assignments to those
variables into the object.
And while we are at it, maybe we should also state the type of data we want to
put in it. That should help too.
Now that would be progress.
Ah well, I guess we will have to wait a while before that happens.....
Albert
Ruby speed will increase, don't worry, as more people will use it.
Bye,
bearophile
> But things grow -- is there any metaprogramming tricks or whatnot we
> can throw on the self?
Indeed. Well, my current solution is to bow to the collective wisdom
and retain the self, but type it with just one symbol
.->
... in TextMate, with the Python bundle! (If only TextMate Python
bundle woulldn't indent everything it pastes.... And that's how Ruby
helps Python -- at the code's very inception TextMate!)
Cheers,
Alexy
You're tilting against windmills. This has been gone over many times. There are very valid reasons for the explicit self, which I understood well enough when I read about them to stop complaining about self, but not well enough to be able to justify to someone else. Sorry for that. But since Alexy likes finding old threads that address his concerns, maybe he'll hunt them down, himself.
> You got this highly flexible language, very good for rapid programming, no more
> clutter from block brackets and variable declarations, and now this 'self' pops
> up.
>
> So much overhead....
>
> Can the computer not decide by itself what I want stored in the object? It can
> read my code too!
>
But not every variable declared inside a class needs to be assigned to self. Make judicious use of non-self variables, if you don't want to see self everywhere.
>
> > Oh I know! It' uch a pain. Sinc writing a hug cla lat wk, I'v had a
> > trribl hortag o lowrca S E L and F charactr. It mak writing vry annoying.
>
> Yes annoying isn't it?
>
> Last week I was programming in C++ again, and now I have this terrible sur-plus
> of lowercase T H I and S letters. I don't understand how they do it (I used to,
> but not any more).
>
> Maybe we should setup an exchange program so everybody can trade letters with
> each other.
>
>
> >> Sometimes I avoid OO just not to deal with its verbosity.
> >
> > There are other values than brevity. In fact, brevity is one of the less
> > important values.
>
> NO! You got it all wrong here! It is not about brevity, it is about SPEED.
>
if you're looking for speed of typing, just type a one character self equivalent, like:
class q(object):
def method(;, arg):
;.var = 3
Then when you're done coding: :%s/;/self/g
> With less letters, there is less to read, so it can be read faster, so it must
> be better!
>
Ah. Speed of reading. In fact, speed of reading is connected to clarity, not brevity. If you have to keep looking back to some declaration section to remember if a given variable is tied to self, it's going to slow down your comprehension speed. the written chinese language is far more concise than japansese, but it's faster to skim japanese, because of the three alphabet system. Most of the meaning is contained in kanji, while the hiragana supplies disambiguation and grammatical specifiers, so you know you can skip past the hiragana and still retain the basic meaning. Having self used by convention means that once you get used to seeing it, you don't need to read it any more. It would really mess with python coders, though, if each person made up their own self-equivalent. You write "s", I write "self", Larry Wall starts coding python and uses "my". Then we'd all have to actually pay attention, and reading really would slow down. That's probably why self seems to be the most consistently held convention in python. Occasionally, someone will use cls, but that's for a different context, where you really do want people to slow down and realise that something different is going on.
> Just like "if x:" is MUCH BETTER than "if x != 0:"
>
Only when "if x:" is what you mean. The semantics are different:
py>>> x = ''
py>>> if x: print "x"
py>>> if x != 0: print "x != 0"
x != 0
>
> The thing that should be fixed imho, is that the brain of some of us tries to
> deduce higher levels of abstractions from what is essentially a very long line
> of simple instructions.
>
Sorry, no entiendo. What needs to be fixed here?
>
> >> But things grow -- is there any metaprogramming tricks or whatnot we can
> >> throw on the self?
> >
> > Oh yeah, that's just what I like to see! Complicated, brittle, hard to
> > debug, difficult to understand metaprogramming tricks in preference to a
> > simple, easy-to-read naming convention.
>
> Maybe we should state first which variables we want to store in self, and then
> have a meta-programming hook that automatically puts assignments to those
> variables into the object.
> And while we are at it, maybe we should also state the type of data we want to
> put in it. That should help too.
>
> Now that would be progress.
>
I hope you are taking the piss.
>
> Ah well, I guess we will have to wait a while before that happens.....
> Albert
Oh God. You are taking the piss. IHBT.
<sigh>
I don't see this as a big deal, but
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?
References to the instance itself would
continue to use "self". A lonely
dot would get lost on the page.
Initially, this form could be treated as
an alternative, usage would
determine its fate. Thus "self.name" or
".name" would identify the same
object.
Colin W.
I don't see this as a big deal, but
> 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.
I've never really understood why some people find that annoying to do. I
make it a point to use, for example, the `this` operator when writing C++
code to avoid implicilty calling/accessing attributes of objects as much
as possible.
--
Ayaz Ahmed Khan
<dead-horse-beaten-to-hell-and-back>
Python's "methods" are thin wrapper around functions, created at lookup
time (by the __get__ method of the function type). What you define in a
class statement are plain functions, period. So there's just no way to
do what you're suggesting.
</dead-horse-beaten-to-hell-and-back>
The object model is irrelevant here. The substitution is purely
syntactical and gets resolved at compile time:
def foo(first, ...):
.bar = ...
is always equivalent with:
def foo(first, ...):
first.bar = ...
and generates the same bytecode.
Whether this is helpfull, beautifull or necessary is another issue.
Kay
Precisely. One wonders whether the people complaining so vehemently
about self have ever encountered coding style guides.
Paul
Point taken. But:
> Whether this is helpfull, beautifull or necessary is another issue.
indeed.
Like the one mandating to prefix "member variables" with 'm_' ?-)
Dude, I'm also programming in Ada, 83 to 95 to 2005. Beautiful
language, a living style guide. I love typing names dozens of
charactares long -- in Ada. Ada has scope control, separate
compilation, renames, overloading, types, etc... However, in
scripting languages, it's not cool, and I'd just love to see self hide
for a bit of a change -- it's a nuisance after Ruby, 's all. Nothing
eternal or worth assembling a NASA panel or Python foundation meeting,
just a li'l respite to make a tiny script more lucid, OK?
Peace,
Alexy
It's not often that I get called "dude". ;-)
> Beautiful language, a living style guide.
Beautiful plumage! [*]
> I love typing names dozens of
> charactares long -- in Ada. Ada has scope control, separate
> compilation, renames, overloading, types, etc... However, in
> scripting languages, it's not cool, and I'd just love to see self hide
> for a bit of a change -- it's a nuisance after Ruby, 's all. Nothing
> eternal or worth assembling a NASA panel or Python foundation meeting,
> just a li'l respite to make a tiny script more lucid, OK?
Well, it's just a pragmatic decision which exposes the mechanism of
passing the instance, which is typically hidden in most of the other
object-oriented languages. The issue is how you resolve names without
having specific details of which names exist on an object. Consider
this:
class X:
def f(value): # in "Selfless Python"!
attr = value
What is attr? A local, a class attribute or an instance attribute?
Sure, we could deduce that f is an instance method of X, and that attr
could really be "self.attr" or even "X.attr". Languages like Java
remove such uncertainty by forcing the declaration of locals and class
and instance attributes, but Python has no such restrictions - an
instance attribute called attr might be introduced later in such a
program, outside any function or method clearly related to the class,
and we'd need to know about that to make an informed decision in cases
like the one shown above.
Paul
[*] Sorry, but such an exclamation is almost obligatory under the
circumstances.
Sure. Since you cite the grammar let me say that I find it somewhat
confusing that the grammar in the Python documentation doesn't
correspond to the grammar used by the CPython parser. For the following
I will use the notations of the Grammar file used by the CPython parser.
In order to adapt the syntax take a look at
atom: ('(' [yield_expr|testlist_gexp] ')' |
'[' [listmaker] ']' |
'{' [dictmaker] '}' |
'`' testlist1 '`' |
NAME | NUMBER | STRING+)
The last row must be changed to
['.'] NAME | NUMBER | STRING+)
~~~~~
But then you run into conflict with the definition of the ellipsis in rule
subscript: '.' '.' '.' | test | [test] ':' [test] [sliceop]
because you need two token of lookahead. Pythons LL(1) parser might not
manage this.
This problem vanishes with Python 3.0 which defines an own ellipsis literal:
atom: ('(' [yield_expr|testlist_comp] ')' |
'[' [testlist_comp] ']' |
'{' [dictorsetmaker] '}' |
NAME | NUMBER | STRING+ | '...' | 'None' | 'True' | 'False')
Kay
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.
--
mvh Björn
> The big deal is that "self." occupies important horizontal screen real
> estate. That is, it is usually not self in itself that is problematic,
Exactly. I understand and appreciate all the scoping qualification
and explicit"ation" needs, but I still want my code to look good and
uncluttered after all is said and done. Using indentation saves us
from all those end's or {}, no less annoying than self, -- then the
self comes along and defeats the purpose of conciseness.
> but the overflowing lines is. Take this silly vector class for
> > 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.
Hear, hear! Dear G-ds of Python, pls give us a --dotself option!
Cheers,
Alexy
> 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.
--
Steven.
This is merely your personal preference and as such, it is not
possible to argue or put in absolute terms.
> and this is positively painful to try to read, it looks like line-noise:
> math.sqrt(.x*.x+.y*.y+.z*.z)
At least it is 12 characters less line-noise than
math.sqrt(self.x*self.y+self.y*self.y+self.z*self.z).
> The correct solution to your example is to get rid of the attribute
> lookups from the expression completely:
No it is not. The "solution" is nothing more than a silly band-aid
thrown out by people who cannot comprehend that Python may not be
perfect in every little detail.
> 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.
timeit
--
mvh Björn
[snip]
>
> The correct solution to your example is to get rid of the attribute
> lookups from the expression completely:
"correct" in what sense?
>
> 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.
Faster still is possible, without any cruft:
>>> def abs1(self):
... x, y, z = self.x, self.y, self.z
... return math.sqrt(x**2 + y**2 + z**2)
...
>>> def abs2(self):
... return math.sqrt(self.x**2 + self.y**2 + self.z**2)
...
>>> import dis
>>> dis.dis(abs1)
2 0 LOAD_FAST 0 (self)
3 LOAD_ATTR 0 (x)
6 LOAD_FAST 0 (self)
9 LOAD_ATTR 1 (y)
12 LOAD_FAST 0 (self)
15 LOAD_ATTR 2 (z)
18 ROT_THREE
19 ROT_TWO
20 STORE_FAST 1 (x)
23 STORE_FAST 2 (y)
26 STORE_FAST 3 (z)
3 29 LOAD_GLOBAL 3 (math)
32 LOAD_ATTR 4 (sqrt)
35 LOAD_FAST 1 (x)
38 LOAD_CONST 1 (2)
41 BINARY_POWER
42 LOAD_FAST 2 (y)
45 LOAD_CONST 1 (2)
48 BINARY_POWER
49 BINARY_ADD
50 LOAD_FAST 3 (z)
53 LOAD_CONST 1 (2)
56 BINARY_POWER
57 BINARY_ADD
58 CALL_FUNCTION 1
61 RETURN_VALUE
>>> dis.dis(abs2)
2 0 LOAD_GLOBAL 0 (math)
3 LOAD_ATTR 1 (sqrt)
6 LOAD_FAST 0 (self)
9 LOAD_ATTR 2 (x)
12 LOAD_CONST 1 (2)
15 BINARY_POWER
16 LOAD_FAST 0 (self)
19 LOAD_ATTR 3 (y)
22 LOAD_CONST 1 (2)
25 BINARY_POWER
26 BINARY_ADD
27 LOAD_FAST 0 (self)
30 LOAD_ATTR 4 (z)
33 LOAD_CONST 1 (2)
36 BINARY_POWER
37 BINARY_ADD
38 CALL_FUNCTION 1
41 RETURN_VALUE
>>>
HTH,
John
-1 Refactoring is a more expedient response than language
redesign.
def sum_of_squares(*args):
return sum(arg*args for arg in args)
--
Neil Cerutti
Python uses "self" (and textual notation when possible) because its
designers consider that symbols reduce readability. Self won't go
away. :-P
The issue is related to the first and seventh lines in The Zen of
Python,
1. "Beautiful is better than ugly"
7. "Readability counts."
My opinion is that "self" is a minor issue in python that we can all
live with.
On Nov 21, 9:51 pm, braver <delivera...@gmail.com> wrote:
> 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
In other cases it's not a big deal. When I program in java I write
"this." on everything anyway, as my Java teacher recommended. So for
me it's not different than java, the way I write it.
I don't particularly like too much use of special characters, such as
the @ in ruby. I actually don't like the @ in python for decorators
either. So ugly :( I would not like to see a special character or
leading dot used for attributes for this reason. Human readable text
is nice, because even if you haven't programmed in the language for a
while, you don't have to remember as many special symbols.
I think using s. is your best bet, but for me, s is then just another
special character that needs to be memorized, whereas self. is self
descriptive.
One persons trash is another person's treasure.
> On Nov 23, 2007 11:54 PM, Steven D'Aprano
> > The correct solution to your example is to get rid of the attribute
> > lookups from the expression completely:
>
> No it is not. The "solution" is nothing more than a silly band-aid
> thrown out by people who cannot comprehend that Python may not be
> perfect in every little detail.
It sure isn't, but what would the best alternative be in this case?
Ruby's "@"? That's only one character less than "s." if "self." is too
long (as a compromise I sometimes use "my."). Also, static languages
can get away with implicit self (or "this") because (1) all attributes
are statically defined in the class body and (2) local variables must
be declared before used; neither of these is true for Python. I
certainly wouldn't consider better a solution that required declaring
local variables (e.g. "local x = 0").
George
> 6 def abs(self):
> 7 return math.sqrt(self.x * self.x + self.y * self.y +
> self.z * self.z)
I would write that as
def abs(self):
x = self.x
y = self.y
z = self.z
return math.sqrt(x * x + y * y + z * z)
Not only is it easier to read, it's also more efficient,
because it avoids looking up instance variables more than
once.
--
Greg
> 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.
>
> --
> Steven.
I like this pattern but less much I like the boilerplate. What about
an explicit unpacking protocol and appropriate syntax?
def abs(self):
x, y, z by self
return math.sqrt(x**2 + y**2 + z**2)
expands to
def abs(self):
x, y, z = self.__unpack__("x","y","z")
return math.sqrt(x**2 + y**2 + z**2)
This would have another nice effect on expression oriented programming
where people use to create small "domain specific languages" using
operator overloading:
x,y,z by Expr
class Expr(object):
def __init__(self, name):
self.name = name
self._sexpr = ()
def __unpack__(self, *names):
if len(names)>1:
return [Expr(name) for name in names]
elif len(names) == 1:
return Expr(names[0])
else:
raise ValueError("Nothing to unpack")
def __add__(self, other):
e = Expr("")
e._sub = ('+',(self, other))
return e
def __repr__(self):
if self._sexpr:
return self._sexpr[0].join(str(x) for x in self._sexpr[1])
return self.name
>>> x,y by Expr
>>> x+y
x+y
>>> 4+x
4+x
> I like this pattern but less much I like the boilerplate. What about
> an explicit unpacking protocol and appropriate syntax?
>
> def abs(self):
> x, y, z by self
> return math.sqrt(x**2 + y**2 + z**2)
>
> expands to
>
> def abs(self):
> x, y, z = self.__unpack__("x","y","z")
> return math.sqrt(x**2 + y**2 + z**2)
What about ``from`` instead of ``by``? That's already a keyword so we
don't have to add a new one.
Ciao,
Marc 'BlackJack' Rintsch
I'm rather passionless about keyword selection. I selected a new one
because I didn't want to discuss possible syntactical conflicts or
confusions that might arise by reusing an existing keyword. I think
'from' is fine when it works for the majority of those who are
interested in the proposed statement semantics.
Ciao, Kay
>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.
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 <prefix> do begin
a = ...
b = ...
end;
where all variables would be automatically prefixed with the <prefix>
(if present in the already available record definition!)
In your case where you have something like:
def somefunction(...):
a = ...
b = ...
...
c = a + b
could (simply :-) become something like:
def somefunction(self, ...):
using self:
a = ...
b = ...
...
c = a + b
so only one line extra and an indentation shift.
Of course the interpreter would have to be (much) smarter here, since
the <prefix> (in this case just a simple 'self', but it could be more
complex, e.g. some module.levels.deep) is not necessarily defined in
advance.
Since 'with' is already in use, another keyword (e.g. 'using') would
be needed
I guess speed would also be a major issue, but readibility would gain
from it (IHMO :-)
--
Ton
> 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 <prefix> do 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
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(self, ...):
using self:
a = ...
b = ...
...
c = a + b
The biggest issue is, what if you need to do more:
def somefunction(self, ...):
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.parentclass.__getattr__(math)? 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.
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.cat, 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(factiod):
def decorator(func):
def wrapper(*args, **kwds):
if ..factoid == None:
return .func(*args, **kwds)
else:
return ..factoid + global.warming
return wrapper
return decorator
> 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
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#49>", line 1, in <module>
leaderboard(7, 'samwyse')
File "<pyshell#47>", line 2, in leaderboard
if my_score > top_score:
UnboundLocalError: local variable 'top_score' referenced before
assignment
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
>On Sat, 24 Nov 2007 09:12:34 +0100, Ton van Vliet wrote:
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
Colin W.
>
>
> 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
> 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 <prefix> do 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('Enter 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
Absolutely.
However, I was more thinking in terms of attributes only, like this:
def meth(self):
using self:
self.tmp = raw_input('Enter age: ')
self.age = int(self.tmp)
and for the methods check whether there *is* a self.<method> defined
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
> It would boil down to choice: explicit/speed vs implicit/readability
No, it would boil down to explicit+speed+readability+maintainability vs
implicit+error prone.
It would mean that as well as the interpreter having to search the
instance to work out whether each name referenced an attribute or a global
the reader would also have to perform the same search. It would mean that
adding a new attribute to an instance would change the meaning of the
methods which is a recipe for disaster.
The whole point of this sub-thread is the difficulty of turning global
vars and functions into class vars and functions, and that is
something that is usually done precisely because the code and data
flow has become harder to follow and understand.
Then don't use "global variables". If you don't put anything except
constants, classes and functions in the module's namespace there's no
problem "lifting" them into a class later.
Ciao,
Marc 'BlackJack' Rintsch
Besides Pascal, Visual Basic also offers a 'with' statement that
behaves almost in this way. That in itself should be an indication
that the whole thing is a bad idea. ;-)
The way it works, however, is that you do have to prefix members with
a '.' and the interpreter tries to bind with each nested 'with'
variable in turn. It's tolerable with one 'with' statment, but once
you start nesting them it becomes dangerous.
My idea in a parallel thread is to treat a '.' prefix like '../' in
file paths; each one moves you up a level in the symbol table. In a
top-level function, it means a global name; in a class method it means
a member. The @classmethod and @staticmethod decorators would need to
fix things so that '.' refers to the appropriate things. There's no
reason why a 'using' statement couldn't perform nesting as well: '.'
refers to the 'using' variable, '..' refers to what '.' previously
referred to, etc.
OTOH, the point of 'using' is to reduce typing, so you might instead
add 'as' clauses as an alternate way to reduce confusion:
>>> using myclass.new() as p:
p.do_something()
p.something_else()
Of course, now its starting to look more like a Python 'with'
statement, and I think there's a way to do basically this already.
>Ton van Vliet <sheep....@green.meadow> wrote:
>
>> It would boil down to choice: explicit/speed vs implicit/readability
>
>No, it would boil down to explicit+speed+readability+maintainability vs
>implicit+error prone.
It would not be a full fledged *implicit*, but only used in small
areas where many self's are coming together, and possibly clutter
readability (a subjective classification anyhow) and even could
degrade (code) maintainability.
>It would mean that as well as the interpreter having to search the
>instance to work out whether each name referenced an attribute or a global
>the reader would also have to perform the same search.
IMHO if it is limited to small overviewable sections I think it could
make life of the reader/coder/maintainer even easier and less error
prone.
I cannot judge for the interpreter part (*if* at all doable, it would
probably be the coder's choice between speed and readability)
>It would mean that adding a new attribute to an instance would change
>the meaning of the methods which is a recipe for disaster.
I don't see what you have in mind here?
As stated some message levels back: 'bear with me', I'm not an expert,
just a beginning user ;-)
I have no problems with the explicit self at all, but just brought up
Pascal's 'with' statement, invented to improve readability only (and
saving some typing as well) and 'transposed' it to python, just as my
2 cents.
I don't want to defend or formally propose an implementation, just
giving comments where *I* do not fully understand the counter
arguments.
So let's not 'beat it to death', ok ;-)
--
Ton
> So::
>
> def meth(self):
> using self:
> tmp = raw_input('Enter 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. :-)
Yes, that's no good. So you would write it like so:
def meth(self,*args):
tmp = int(raw_input('Enter age:'))
using self:
age = tmp
Still an unnecessary lookup on tmp though :) And it would be useless
to use it for one assignment, the idea is to eliminate all the typing
with this:
self.var1 = 5
self.var2 = "a value"
self.var3 = stuff
self.var4 = [2,54,7,7]
self.var5 = "dingaling"
self.var6 = 6.4
self.var7 = 1
self.var8 = False
self.var9 = True
Of course that "self.var3 = stuff" under the using would result in a
bad lookup for "stuff", but the programmer who wanted to use this
would have to realize this and try to avoid it.
I have been known from time to time, for long assignments such as
this, to turn a string with keys and values into a dictionary, and
then update __dict__ with that dictionary, hehe. "var1,5;var2,"a
value";var3,stuff" Not the best practice but the fastest to type.
Sometimes I actually use a dictionary, but typing all of the quotes
for the keys gets old.
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...
Self is never going away, most python programmers generally like or
aren't bothered by it, if you are new to the language try to get used
to it, if it's too bothersome you can use one of the hacks or try
other languages. I don't mean to be snobby either, one language does
not fit all.
Indeed. As has been mentioned, it's all about resolving names and how
much of that work gets done at run-time (and whether the magic
confuses the human reader further).
> And it would be useless
> to use it for one assignment, the idea is to eliminate all the typing
> with this:
>
> self.var1 = 5
> self.var2 = "a value"
> self.var3 = stuff
> self.var4 = [2,54,7,7]
> self.var5 = "dingaling"
> self.var6 = 6.4
> self.var7 = 1
> self.var8 = False
> self.var9 = True
>
> Of course that "self.var3 = stuff" under the using would result in a
> bad lookup for "stuff", but the programmer who wanted to use this
> would have to realize this and try to avoid it.
I think the remedy is worse than the ailment, especially since the
Pascal "with" construct can make use of declared information about
structure attributes, while the absence of such declarations leaves
more work to be done in Python (and more detective work for future
maintainers of code). Of course, for cases like the above, assuming
that one doesn't feel that lists or dictionaries are acceptable
alternatives to large numbers of instance attributes (which might not
have such regular naming), one might suggest a useful extension of the
attribute access syntax. Taking part of the above example and
rewriting...
self.(var1, var2, var3, var4) = 5, "a value", stuff, [2,54,7,7]
I'm sure Mr Schluehr can provide a working demonstration of this with
very little effort. ;-)
Paul
P.S. There were some proposals for generalisations of the attribute
access mechanisms using not completely different syntax, but I don't
recall them addressing the issue of accessing multiple attributes at
the same time, and the use of arbitrary expressions in place of the
attribute name (where a tuple is used above) gave a distinct feeling
of writing something similar to a combination of the worst aspects of
some shell language with some of the nastier parts of microcomputer
assembly language. Let us, therefore, not get too enthusiastic about
such ideas!
or even
p = myclass.new()
p.do_something()
p.something_else()
Doesn't even need any new syntax. :-)
--
Greg
If the keys are all identifiers, you can use keyword
args to the dict constructor. So you could write
self.__dict__.update(dict(var1 = 5,
var2 = "a value", var3 = stuff))
if you really wanted to. (Don't be surprised if
everyone else refuses to maintain your code, though!)
--
Greg
You'd be better off changing your design habits to make
things into classes from the beginning if you suspect
you may want it that way later.
--
Greg
_ = 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
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.
>
Regards,
Jordan
Could you please elaborate "This problem
vanishes with Python 3.0 which
defines an own ellipsis literal"?
It seems that ellipsis remains "..." -
I've never found a use for it.
See
http://docs.python.org/dev/3.0/library/constants.html#Ellipsis
Colin W.
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(object):
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
> 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?
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.
> 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"
Regards,
Jordan
Does this address your concerns?
Does this address your concerns?
The idea being that "with self" use
Well you're not the laziest. Here's mine:
class Vector:
def __init__(self, *data):
self.data = data
def abs(self):
return math.sqrt(sum(x*x for x in self.data))
Hey I'm so lazy it's untested :)
However I've got standards: I wouldn't swap 'self' for 's'.
--
Arnaud
Yes, indeed. A self-reference prefix like "s", "T", "_" or even "my"
would be enough characters shorter than "self." But self *is* the
convention and just because the language allows you to break it
doesn't mean that it is not horribly wrong to do so. :)
--
mvh Björn
Too bad : in Python, everything's an object, so 'methods' are attributes
too.
FWIW, Javascript has it too - and it's considered a BadPractice(tm) to
use it...
self.__dict__.update(dict(var1=5, var2="a value", var3 = stuff, <etc>))
Someone else ? Or are we done with this DeadHorse ?
Using globals to maintain state between functions being bad practice in
most cases, I don't see any reason to encourage it by providing some
builtin support.
>> However, I was more thinking in terms of attributes only
>
>Too bad : in Python, everything's an object, so 'methods' are attributes
>too.
Right, but I'm sure *you* know a way to distinguish between them (I'm
just a beginner ;-)
--
Ton
What do you see as a problem here?
Surely it gives useful flexibility.
Colin W.
All methods are attributes. Not all attributes are methods. The usual way
to see if something is a method is to try calling it and see what
happens, but if you want a less informal test, try type():
>>> type(''.join)
<type 'builtin_function_or_method'>
>>> type(Foo().foo) # with the obvious definition of Foo
<type 'instancemethod'>
--
Steven
Yes : reading the doc. But that's something the compiler will have hard
time doing.
>> (I'm
>> just a beginner ;-)
>
> All methods are attributes. Not all attributes are methods. The usual way
> to see if something is a method is to try calling it and see what
> happens, but if you want a less informal test, try type():
>
>
>>>> type(''.join)
> <type 'builtin_function_or_method'>
>>>> type(Foo().foo) # with the obvious definition of Foo
> <type 'instancemethod'>
>
Fine. Now since Python let you define your own callable types and your
own descriptors, you can as well have an attribute that behave just like
a method without being an instance of any of the method types - so the
above test defeats duck typing. And since you can have callable
attributes that are definitively not methods, you can't rely on the fact
that an attribute is callable neither.
If you want to have a little fun:
class peverse:
def __call__(self):
raise AttributeError ("peverse instance has no __call__ method")
x = peverse()
x()
> If you want to have a little fun:
>
> class peverse:
> def __call__(self):
> raise AttributeError ("peverse instance has no __call__ method")
>
> x = peverse()
> x()
That is "peverse", but still...
from types import FunctionType
type(x) == FunctionType # False
And you can't (easily?) subclass FunctionType:
Error when calling the metaclass bases
type 'function' is not an acceptable base type
;)
Regards,
Jordan
You snipped too much... Tony wrote "However, I was more thinking in
terms of attributes only" (implying: attributes != methods). So the "too
bad" meant "won't work here".
> Surely it gives useful flexibility.
Indeed. But that's not the problem here.
print callable(x)
=> True
> That is "peverse", but still...
>
> from types import FunctionType
> type(x) == FunctionType # False
>
> And you can't (easily?) subclass FunctionType:
>
> Error when calling the metaclass bases
> type 'function' is not an acceptable base type
>
> ;)
You don't have to subclass function to define a callable type that
implements the descriptor protocol so it behaves just like a function in
the context of an attribute lookup.
> You don't have to subclass function to define a callable type that
> implements the descriptor protocol so it behaves just like a function in
> the context of an attribute lookup.
I'm aware, and I understand that python's types (as with other duck-
typed languages) are basically just an object's capabilities; I was
just pointing out that, if needed (though I can't think of why
offhand...mabye some kind of sandbox?), you can detect built-in
functions. Hmm...but then again, it seems that shadowing a built-in
function still reports as it's type as FunctionType...
In [1]: from types import FunctionType
In [2]: def len(x):
...: # mischief
...: pass
...:
In [3]: type(len) == FunctionType
Out[3]: True
Regards,
Jordan
Horrific cluge:
--
def noself(func):
def t(*args, **kwargs):
self = args[0]
g = globals()
delete = []
for varname in dir(self):
if not varname.startswith("__") and varname not in g:
g[varname] = self.__getattribute__(varname)
delete.append(varname)
func(*args, **kwargs)
for varname in delete:
del(g[varname])
return t
class Test(object):
x = 1
@noself
def test(self):
print x
>>> foo = Test()
>>> foo.test()
1
--
FTR, I won't be using this :) I do like this syntax though:
class Vector:
def __init__(self, x, y, z):
self.x = x
self.y = y
self.z = z
def abs(self):
using self:
return math.sqrt(.x*.x + .y*.y + .z*.z)
Iain
Ok.
> Hmm...but then again, it seems that shadowing a built-in
> function still reports as it's type as FunctionType...
Of course (at least as long as you sahdow it with another function) -
Why would it be otherwise ?
> FTR, I won't be using this :) I do like this syntax though:
>
> class Vector:
> def __init__(self, x, y, z):
> self.x = x
> self.y = y
> self.z = z
> def abs(self):
> using self:
> return math.sqrt(.x*.x + .y*.y + .z*.z)
It is a bit verbose though. This variant is shorter on my system[*]:
class Vector:
def __init__(self, x, y, z):
self.x = x
self.y = y
self.z = z
def abs(self):
return math.sqrt(self.x*self.x + self.y*self.y + self.z*self.z)
[*] Windows, they are the same length on Linux.
:)
Yeah, in this example. Another would be
using NetworkConnection:
.address = "127.0.0.1"
.port = "8080"
.connect()
using .connection
while .read():
do something
.disconnect()
I doubt anything like this will take though, since you can write
similar code with 'with' and assigning a long name to a short one.
Iain
I was really upset about having to type 'self' all the time,
until I learned that in ABC, one of Python's precursors, you had
to use '__anInstanceOf_This_TYPE_or_Maybe_A__SubClassOfItInstead_arg0_'.
--
Neil Cerutti
Sermon Outline: I. Delineate your fear II. Disown your fear III. Displace your
rear --Church Bulletin Blooper
> Fine. Now since Python let you define your own callable types and your
> own descriptors, you can as well have an attribute that behave just like
> a method without being an instance of any of the method types - so the
> above test defeats duck typing. And since you can have callable
> attributes that are definitively not methods, you can't rely on the fact
> that an attribute is callable neither.
I did say the usual way was to call it and see what happens :)
(In Python3, I understand that is what callable() will do. Let's hope
that the function called has no side-effects.)
I also didn't mention classmethods, staticmethods or functions assigned
to attributes. As Ton van Vliet is a beginner, I didn't think he needed
to be flooded with too many complications all at once. It's quite
possible to program in Python for years and never come across a callable
attribute that isn't an ordinary method.
Also, I wasn't actually thinking about testing for methods before calling
them. Given the context, I was thinking more about manual experimentation
at the interpreter. Perhaps I should have said.
--
Steven.
It's certainly *not* "the usual way" to test if some object is callable
- it's only ok if you really intented to call it, and even then it might
be better to test before calling so you distinguish exceptions raised
from within the called code from exceptions due the the call itself.
> (In Python3, I understand that is what callable() will do.
IIRC, there's no callable() function at all in Python 3.
>
> I also didn't mention classmethods, staticmethods or functions assigned
> to attributes. As Ton van Vliet is a beginner, I didn't think he needed
> to be flooded with too many complications all at once.
Understanding the object model of a (mostly) OO langage is not what I'd
call "too many complications". But I may be a bit biased !-)
> It's quite
> possible to program in Python for years and never come across a callable
> attribute that isn't an ordinary method.
You loose !-)
callable(object.__class__)
=> True