Some language proposals.

J

Josiah Carlson

Paul,

Your outputs were all incorrect.
a = 5
def b():
a = 6
print a
b()
print a

What will this print?

5
6
.... a = 6
.... print a
....
5


Okay, then.

a = 5
def b():
a = 6
def c():
a = 7
print a
print a
c()

print b()()
print a

What does this print?

7
6
5

What you give doesn't work, here's a slight modification:
.... a = 6
.... def c():
.... a = 7
.... print a
.... print a
.... return c
....
5


I don't know what you were trying to prove, but next time, test it out.

- Josiah
 
J

Jacek Generowicz

Why not use callable instances?

Errrrr ...

Reading the paragraph you quoted and trying to understand it is left
as an exercise to you. (Hint: it's the last sentence.)
 
J

Jacek Generowicz

Michael Hudson said:
OK, you really hadn't seen this argument before. You must be new here
:) (or at least, new to this particular dispute).

Yes, I usually switch off rather early in the "Python purity vs
whatever" threads, and the "The current state of Python is programming
language Nirvana" threads. You see, I use Python because it lets me
gets certain jobs done easily and enjoyably, and don't really much
care for language patriotism. I will fiercely defend Python on its
merits (which are legion), but that does not preclude me from
sometimes noting that it would be handy if something were different
than it is right now.

My contribution to this thread started with a question: I paraphrase
"why are Python closures read only?". Paul gave me an answer which has
some merit and I am satisfied with that answer. Frankly, I have no
time for, or interest in discussing how often I should on should not be
using closures in Python. When they are convenient for me, I will use
them, and when callable instances are more convenient, I will use
those, regardless of what you and Paul might say, so there,
na-na-na-naaa-naaah !
(trivially, you never *need* closures, just the same as you don't
*need* objects, there's a rather dull and unhelpful isomorphism
between the two concepts).

Yes, and we all know about Turing equivalence too. So we don't need
Python at all.
Which isn't that hard...

It's not hard, but it's pointless, when there are ways of getting it
for free.
I think a code example might lend a bit more clarity.

What's unclear about it? I get the impression that you understand
exactly what the point is.
.... def __call__(self): print self
....
meth behaves like a Python method, instance does not.
[At this point I'd love someone to step up and show me how to re-use
the existing FunctionType descriptors in my own classes.]

Post some code, and I'll have a go.

Find some way of making callable [from above] use
types.FunctionType.__get__. I don't see what code examples could
possibly help in specifying the problem more clearly (unless the code
is the solution, of course).

But please don't bother unless you really want to do it for your own
entertainment. My not having found a way to do it, is in no way
stopping me from achieving my goals. (Which is more than can be said
for contributing to this thread :) There being perfectly viable
alternatives to doing it, means that I haven't invested much time in
finding an answer, so it may well be that there is as simple solution.
I'll grant you this: I've done the same.

That's my point. Closures are there, sometimes they are more
appropriate than instances, so use them. No point in discussing the
merits and demerits of the two alternatives and pontificating on what
is Pythonic or not.
Um, here, unless I misunderstand you, you don't want to mutate the
closed over binding (which is what Python currently doesn't let you
do) but mutate the object the closed over binding is bound to. In
this respect, Python is no different from anything else, you need to
arrange some way to expose said object outside the closure.

What am I missing?

Nothing. It was an inappropriate example.
Maybe, once you've been assimilated into the Python Borg mindset, you
don't, actually.

Aaah, this thread is an attempt to assimilate me :) Now I understand.
There are sort of two extreme possibilities here:

1) I am so blinded by the fact that I know Python as of 2.3 FAR better
than any other language that I don't see how wonderful Python would
be if "full closures" were added.

2) Full closures just aren't that appropriate to Pythonic programming.

The truth, almost certainly, is somewhere in between these points.

An excellent summary, which, in my opinion says all that remains to be
said in this thread.

And, with that, I take my leave. I bid you a good day, gentlemen.
 
J

Jacek Generowicz

Paul Prescod said:
But the more important point is that people do not NEED it much. Guido
writes hundreds of lines of Python code per week. If he often ran into
situations where a mutable closure would make a big difference then he
would presumably find some way of doing it. The people who want this
seem most often to be people trying to import their coding styles from
another language.

Methinks that your image of just how much Guido drives new additions to
the language, is a little dated.
 
J

Jacek Generowicz

Paul Prescod said:
You've cleverly found one of the very few places where Python
distinguishes between "true" functions and callable objects.

What bothers me more (I think, though I can't remember the exact
reasons why, right now, so maybe it's not that important), is that
Python distinguishes between "true" functions and "builtin" functions.
I would argue that classes should distinguish between
attributes-to-be-treated-as-methods and
attributes-to-be-treated-as-just-attributes using something other than
type.

Look again. They do. [Hint: descriptors]
Consider the following program:


class a:
pass

def func():
pass

lst = [1, 2, 3, "a", "b", "c", object(), lambda x:x ]

for x in lst:
a.b = x
assert a.b is x, "What???? %s"% x
print "Okay", x

Frankly I think it is unpythonic that a second after assignment to a.b
the thing I get back is different than the thing I put in.

I do wish you'd run your examples through a Python interpreter before
posting them. The little bugs you include, really interfere with
trying to understand what your point is.

I suspect that what you are trying to demonstrate is this:
.... a.b = x
.... print a.b is x
....
1
1
1
1
1
1
1
0

Though why you need 3 integers, and 3 strings, and a whole lot of line
noise to do it, escapes me.

[An I've stated in my followup to Michael, I have nothing else to say
about closures in Python.]
 
P

Paul Prescod

Jacek said:
I do wish you'd run your examples through a Python interpreter before
posting them. The little bugs you include, really interfere with
trying to understand what your point is.

Sorry. Don't know what else I can do:

bash-2.05a$ cat foo.py
class a:
pass

def func():
pass

lst = [1, 2, 3, "a", "b", "c", object(), lambda x:x ]

for x in lst:
a.b = x
assert a.b is x, "What???? %s"% x
print "Okay", x

bash-2.05a$ python foo.py
Okay 1
Okay 2
Okay 3
Okay a
Okay b
Okay c
Okay <object object at 0x116e20>
Traceback (most recent call last):
File "foo.py", line 11, in ?
assert a.b is x, "What???? %s"% x
AssertionError: What???? <function <lambda> at 0x122190>
bash-2.05a$

And this is after cutting and pasting the program from your reply back
into a file.

Given that I was trying to demonstrate an inconsistency in behaviour I
felt it helpful to show examples of logical behaviour.

Paul Prescod
 
M

Michael Hudson

Jacek Generowicz said:
Yes, I usually switch off rather early in the "Python purity vs
whatever" threads,

Me too. I wonder why we're both still in this one?

[...]
Yes, and we all know about Turing equivalence too. So we don't need
Python at all.

Indeed. Break out the infinitely long tapes. But it does make "need"
a difficult word, is all.
It's not hard, but it's pointless, when there are ways of getting it
for free.


What's unclear about it? I get the impression that you understand
exactly what the point is.

Well, now we're even on assuming too much about the other's
comprehension front :)
... def __call__(self): print self
...

meth behaves like a Python method, instance does not.

Ah, ok. To make it behave like a method, you need to make it a
descriptor, i.e. implement __get__ (and make everything in sight
new-style classes, of course).
[At this point I'd love someone to step up and show me how to re-use
the existing FunctionType descriptors in my own classes.]

Post some code, and I'll have a go.

Find some way of making callable [from above] use
types.FunctionType.__get__.

I don't think I can do *that*:
import types

class foo(object):
pass

class Callable(object):
__get__ = types.FunctionType.__get__

foo.inst = Callable()

print foo.inst

yields:

Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "/usr/tmp/python-10511jfs.py", line 11, in ?
print foo.inst
TypeError: descriptor '__get__' requires a 'function' object but received a 'Callable'

but you can do something nearly equivalent:

import types

class foo(object):
pass

class Callable(object):
def __init__(self): # wonder why this is needed:
self.__name__ = 'Callable'
def __call__(self, ob):
return ob
def __get__(self, ob, cls=None):
return types.UnboundMethodType(self, ob, cls)

foo.inst = Callable()

print foo.inst
print foo().inst()

(needs 2.3, for 2.2 use new.instancemethod instead).
I don't see what code examples could possibly help in specifying the
problem more clearly (unless the code is the solution, of course).

But please don't bother unless you really want to do it for your own
entertainment.

Well, I've signed up to give a talk on new-style classes at Python-UK,
so I'd hope not to have to work too hard for this :)

[...]
Aaah, this thread is an attempt to assimilate me :) Now I understand.

Damn, you noticed.
An excellent summary, which, in my opinion says all that remains to be
said in this thread.

And, with that, I take my leave. I bid you a good day, gentlemen.

And to you!

Cheers,
mwh
 
A

Aahz

Errrrr ...

Reading the paragraph you quoted and trying to understand it is left
as an exercise to you. (Hint: it's the last sentence.)

Nope. Got nothing to do with my point:

class Callable:
def __call__(self):
print "!"

class C:
def __init__(self):
self.foo = Callable()

C().foo()

Now tell me why this doesn't do what you want.
 
T

Terry Reedy

Jacek Generowicz said:
language Nirvana" threads. You see, I use Python because it lets me
gets certain jobs done easily and enjoyably, and don't really much
care for language patriotism. I will fiercely defend Python on its
merits (which are legion), but that does not preclude me from
sometimes noting that it would be handy if something were different
than it is right now.

Sounds sensible.
My contribution to this thread started with a question: I paraphrase
"why are Python closures read only?".

As I said before, because Python has a 'write locally unless directed
otherwise' rule, which is not going to change, and because no one has yet
come up with a convincingly good syntax or method to replace or extend the
global directive for directing otherwise -- where convincely good mean
enough better than mutable wrapping to be worth the bother. And because no
one has yet cared enough to effectively push the issue further.

On the aesthetics of wrapping: with a C background, the notion of rebind
vars in something else's strikes me as 'odder' that mutating a mutable. So
I do not see n = [n] as being that ugly, while understanding that someone
with a 'full-closure' language background well might. On the other hand,
the non-uniformity of write local, write global, but not in between, is
bothersome enough to enough developers that there was serious discussion of
how to do it.

Terry J. Reedy
 
J

Jacek Generowicz

class Callable:
def __call__(self):
print "!"

class C:
def __init__(self):
self.foo = Callable()

C().foo()

Now tell me why this doesn't do what you want.
Because
Traceback (most recent call last):
File "<stdin>", line 1, in ?
AttributeError: class C has no attribute 'foo'

for a start.
 
J

Jacek Generowicz

Ah, ok. To make it behave like a method, you need to make it a
descriptor, i.e. implement __get__ (and make everything in sight
new-style classes, of course).


(although I did misplace the terminology a little, I realize.)
import types

class foo(object):
pass

class Callable(object):
def __init__(self): # wonder why this is needed:
self.__name__ = 'Callable'
def __call__(self, ob):
return ob
def __get__(self, ob, cls=None):
return types.UnboundMethodType(self, ob, cls)

foo.inst = Callable()

print foo.inst
print foo().inst()

(needs 2.3, for 2.2 use new.instancemethod instead).

Aha !

I was doing this stuff way back in 2.2[*], where you get
Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "<stdin>", line 7, in __get__
TypeError: cannot create 'instance method' instances

but it does indeed work in 2.3. Thanks for pointing that out.
Damn, you noticed.

I'm well on the ball, I am.

Cheers,


[*] Actually, I'm still forced to use 2.2 in production for now.
 
A

Antoon Pardon

Op 2004-02-25 said:
If you want a function with its own namespace, that is already
possible as you showed yourself in an earlier post. On the other hand,
if a function has its own namespace what is the difference between a
function and a class? Why not use a class in the first place?

Maybe because somtimes it is more easy or natural to think
of a problems in terms of a function and sometimes in terms
of a
Remember that "global" is just a way for a function to tell the
interpreter that this variable belongs to the global namespace.

There is some inconsistency if one has a function inside a function
and that function has a global 'x' but the outer function doesn't have
a global 'x'. Modifications of 'x' from the deepest function do not
reach the global namespace, in fact they do not even reach the
namespace of the containing function.

Only if both functions have a global 'x' the name is visible at the
global and intermediate level.

Well that looks like either poor design or poor implementation to
me.
However there is already a mechanism to solve these kind of problems:
namespaces! Why not use them?

Maybe because that solution can sometimes seem forced onto the
problem. Like if all you have is carpenting tools you only
can provide carpenting solutions.

Aaargh!!!!, A dreadfull type on my part that completly changed the
meaning of what I wanteds to say. "not" should read "now"
 
A

Antoon Pardon

Op 2004-02-25 said:
In Python functions are objects but objects are not functions. In (e.g.)
Scheme the opposite is true.


But the more important point is that people do not NEED it much. Guido
writes hundreds of lines of Python code per week. If he often ran into
situations where a mutable closure would make a big difference then he
would presumably find some way of doing it. The people who want this
seem most often to be people trying to import their coding styles from
another language.

I think this can be turned around. People who don't want this included
are people who want python to be used in a "pythonic" style.

My idea is that there is nothing wrong with a laguage that supports
different coding styles. Personnaly I switch styles according to
how view the solution to the problems I have to solve. Sometimes
I view such a solution in a very object oriented way, sometimes
I don't. So when I envision a particular solution, that is best
implemented in a particular style, why shouldn't I use that style
just because I program in python.
 
M

Michael Hudson

Jacek Generowicz said:

Glad to be of service...
I was doing this stuff way back in 2.2[*], where you get
Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "<stdin>", line 7, in __get__
TypeError: cannot create 'instance method' instances

but it does indeed work in 2.3. Thanks for pointing that out.

This is one of the many little ways -- particularly in the area of
new-style classes -- in which Python 2.3 is just Python 2.2 done
right.

Cheers,
mwh
 
J

Josiah Carlson

class Callable:
Traceback (most recent call last):
File "<stdin>", line 1, in ?
AttributeError: class C has no attribute 'foo'

for a start.

Perhaps you want the below. You seem to be interested in doing things
with classes and not instances.

class Callable:
def __call__(self):
print "!"

class C:
foo = Callable()

- Josiah
 
J

Josiah Carlson

[snip classes not behaving like class instances]

I see. You are not happy with the fact that instances of some other
class, with a __call__ method are not considered a bound instance
method. I'm sure you have thought of it, but I would wrap it. It may
take another function call, but really, what other functionality do you
need that the below does not provide?

Give the below a shot.

- Josiah

class callee:
def __call__(s, self, *args):
print self

def instance(self, *args):
print self

def wrapper(self, *args):
print self
self._c(self, *args)

class caller:
pass

caller.instance_method = instance
caller.instance_method2 = wrapper
foo = caller()
caller._c = callee()

foo.instance_method()
foo.instance_method2()
foo.instance_method
foo.instance_method2
 
J

Jacek Generowicz

Josiah Carlson said:
[snip classes not behaving like class instances]

I see. You are not happy with the fact that instances of some other
class, with a __call__ method are not considered a bound instance
method. I'm sure you have thought of it, but I would wrap it.

Or, I could just use a closure as I advocated in the first place. It
would be shorter, clearer, less error-prone and (much) more efficient.
take another function call, but really, what other functionality do
you need that the below does not provide?


Give the below a shot.

- Josiah

class callee:
def __call__(s, self, *args):
print self

def instance(self, *args):
print self

def wrapper(self, *args):
print self
self._c(self, *args)

class caller:
pass

caller.instance_method = instance
caller.instance_method2 = wrapper
foo = caller()
caller._c = callee()

Which is just a very long-winded and run-time inefficient way of
achieving the following

class caller: pass

def method2(self, *args):
print self

caller.method2 = method2


Please remember that this all started because of a suggestion that
instances with __call__ are better alternatives to closures in just
about any situation in Python. (Please remember that _I_ disagree with
this.)

In other words, yes, I _could_ do this, but why would I want to, given
that much better alternatives exist ... even ones which do not use
closures (see Michael Hudson's suggestions upthread on how to do this
in Python 2.3 using types.UnboungMethodType and new.instancemethod,
for example).
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,767
Messages
2,569,572
Members
45,046
Latest member
Gavizuho

Latest Threads

Top