469,282 Members | 2,123 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 469,282 developers. It's quick & easy.

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 6080
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
Nov 25 '07 #51
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.
>
Nov 25 '07 #52
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.
>
Nov 25 '07 #53
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
Nov 25 '07 #54
On Nov 24, 1:10 pm, "Patrick Mullen" <saluk64...@gmail.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(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
Nov 25 '07 #55
"Colin J. Williams" <cj*@sympatico.cawrote in message
news:ma***************************************@pyt hon.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?
Nov 25 '07 #56
Andrew Koenig wrote:
"Colin J. Williams" <cj*@sympatico.cawrote in message
news:ma***************************************@pyt hon.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?

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.
Nov 25 '07 #57
Andrew Koenig wrote:
"Colin J. Williams" <cj*@sympatico.cawrote in message
news:ma***************************************@pyt hon.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?

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.

Nov 25 '07 #58
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"
Nov 25 '07 #59
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
Nov 25 '07 #60
MonkeeSage wrote:
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
Does this address your concerns?

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.
Nov 25 '07 #61
MonkeeSage wrote:
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
Does this address your concerns?

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.

Nov 25 '07 #62
On Nov 24, 10:55 am, jakub silar <jakub.si...@volny.czwrote:
BJrn Lindqvist wrote:
On Nov 22, 2007 2:08 PM, Colin J. Williams <c...@sympatico.cawrote:
>bearophileH...@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
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

Nov 25 '07 #63
On Nov 24, 2007 11:55 AM, jakub silar <ja*********@volny.czwrote:
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.
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 Bjrn
Nov 26 '07 #64
Ton van Vliet a crit :
On 24 Nov 2007 13:56:37 GMT, Marc 'BlackJack' Rintsch <bj****@gmx.net>
wrote:
(snip)
>>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. :-)


Absolutely.

However, I was more thinking in terms of attributes only
Too bad : in Python, everything's an object, so 'methods' are attributes
too.
Nov 26 '07 #65
samwyse a crit :
(snip)
>
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. ;-)
FWIW, Javascript has it too - and it's considered a BadPractice(tm) to
use it...
Nov 26 '07 #66
Ton van Vliet a crit :
On 24 Nov 2007 16:07:18 GMT, Duncan Booth
<du**********@invalid.invalidwrote:

>>Ton van Vliet <sh***********@green.meadowwrote:

>>>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.

In which case explicitely making local aliases is not too much work, and
way more readable.
Nov 26 '07 #67
Patrick Mullen a écrit :
(snip)
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
self.__dict__.update(dict(var1=5, var2="a value", var3 = stuff, <etc>))

Someone else ? Or are we done with this DeadHorse ?
Nov 26 '07 #68
samwyse a crit :
(snip)
>
Actually, the chained dots are solving a completely different problem,
that of refactoring a collection of functions that use global vars
into a class.
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.
Nov 26 '07 #69
On Mon, 26 Nov 2007 20:14:50 +0100, Bruno Desthuilliers
<bd*****************@free.quelquepart.frwrote:
>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
Nov 26 '07 #70
Bruno Desthuilliers wrote:
[snip]>
Too bad : in Python, everything's an object, so 'methods' are attributes
too.
What do you see as a problem here?
Surely it gives useful flexibility.

Colin W.

Nov 26 '07 #71
On Mon, 26 Nov 2007 21:48:36 +0100, Ton van Vliet wrote:
On Mon, 26 Nov 2007 20:14:50 +0100, Bruno Desthuilliers
<bd*****************@free.quelquepart.frwrote:
>>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 ;-)
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
Nov 27 '07 #72
Steven D'Aprano a écrit :
On Mon, 26 Nov 2007 21:48:36 +0100, Ton van Vliet wrote:
>On Mon, 26 Nov 2007 20:14:50 +0100, Bruno Desthuilliers
<bd*****************@free.quelquepart.frwrote:
>>>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
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.


Nov 27 '07 #73
In article <47***********************@news.free.fr>,
Bruno Desthuilliers <br********************@wtf.websiteburo.oops.com >
wrote:
Steven D'Aprano a écrit :
On Mon, 26 Nov 2007 21:48:36 +0100, Ton van Vliet wrote:
On Mon, 26 Nov 2007 20:14:50 +0100, Bruno Desthuilliers
<bd*****************@free.quelquepart.frwrote:

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

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()
Nov 27 '07 #74
On Nov 27, 3:20 am, Roy Smith <r...@panix.comwrote:
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
Nov 27 '07 #75
Colin J. Williams a crit :
Bruno Desthuilliers wrote:
[snip]>
>Too bad : in Python, everything's an object, so 'methods' are
attributes too.

What do you see as a problem here?
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.
Nov 27 '07 #76
MonkeeSage a crit :
On Nov 27, 3:20 am, Roy Smith <r...@panix.comwrote:
>If you want to have a little fun:

class peverse:
def __call__(self):
raise AttributeError ("peverse instance has no __call__ method")

x = peverse()
x()
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.
Nov 27 '07 #77
On Nov 27, 4:22 am, Bruno Desthuilliers
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
Nov 27 '07 #78
On Nov 27, 9:20 am, Roy Smith <r...@panix.comwrote:
In article <474bdf4f$0$19226$426a7...@news.free.fr>,
Bruno Desthuilliers <bruno.42.desthuilli...@wtf.websiteburo.oops.com >

wrote:
Steven D'Aprano a crit :
On Mon, 26 Nov 2007 21:48:36 +0100, Ton van Vliet wrote:
>On Mon, 26 Nov 2007 20:14:50 +0100, Bruno Desthuilliers
><bdesth.quelquech...@free.quelquepart.frwrote:
>>>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
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()

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
Nov 27 '07 #79
MonkeeSage a crit :
On Nov 27, 4:22 am, Bruno Desthuilliers
>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.
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 ?

Nov 27 '07 #80
Iain King <ia******@gmail.comwrote:
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.

:)
Nov 27 '07 #81
On Nov 27, 12:03 pm, Duncan Booth <duncan.bo...@invalid.invalid>
wrote:
Iain King <iaink...@gmail.comwrote:
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

Nov 27 '07 #82
On 2007-11-26, Bruno Desthuilliers <bd*****************@free.quelquepart.frwrote:
Patrick Mullen a crit :
(snip)
>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

self.__dict__.update(dict(var1=5, var2="a value", var3 = stuff, <etc>))

Someone else ? Or are we done with this DeadHorse ?
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__SubClassOfIt Instead_arg0_'.

--
Neil Cerutti
Sermon Outline: I. Delineate your fear II. Disown your fear III. Displace your
rear --Church Bulletin Blooper
Nov 27 '07 #83
On Tue, 27 Nov 2007 10:11:48 +0100, Bruno Desthuilliers wrote:
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.
Nov 28 '07 #84
Steven D'Aprano a écrit :
On Tue, 27 Nov 2007 10:11:48 +0100, Bruno Desthuilliers wrote:
>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 :)
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
Nov 28 '07 #85

This discussion thread is closed

Replies have been disabled for this discussion.

By using this site, you agree to our Privacy Policy and Terms of Use.