Some language proposals.

Paul Prescod paul at prescod.net
Wed Feb 25 18:24:35 CET 2004


While I'm thinking about it, let me refute your Sapir-Wharf claim (BTW, 
its been pretty widly debunked in linguistics)

Before Python had nested scopes at all, it was VERY common to fake them 
using a linguistic trick: default arguments. This idiom was very common 
in Python's source base. Python didn't have a proper way to do the 
nesting but people figured out how to do it anyway and did it a LOT. 
(similarly people often emulate OO in C)

The "wrap your mutables" feature is by comparison _much less intrusive_ 
but I don't ever see it in real Python code. This suggests to me that 
people don't need the feature that badly.

Jacek Generowicz wrote:

>...
> And using objects (err ... instances of classes) to fake stateful
> functions sucks just as much.

Let's step above the words "function" and "object" for a second. 
Sometimes you need to combine mutable state and code into a single unit. 
Python has a first-class feature for doing that: the object. That's the 
implementation of the requirement.

But you are expressing an _implementation_ as a _requirement_. "I need a 
combination of state and data and it must be a function." Why?

> Sure. I have some stateful methods of classes (which I create
> dynamically and stick onto the class as the information about the
> existence of the method becomes available). 

Why are the METHODS stateful rather than keeping their state in the 
class? If I had to maintain your code I would much rather that you keep 
state in the same place all the other Python programmers do.

But if you must do this then use the well-known mutable closure hack. 
It'll take you just a few extra characters of code. When we start seeing 
dozens or hundreds of people making use of it then we'll know the 
community really needs it (and isn't just trying to turn Python into 
Lisp for its own sake).

> ... By implementing them as
> closures I can just stick them on to the class. If I were to implement
> them as instances then I'd have to reimplement all the descriptors
> that take care of turning functions into bound or unbound methods.

Or you could wrap them in functions.

inst = Class()

someclass.method = lambda x, *args, **kwargs: inst(*args, **kwargs)

You've cleverly found one of the very few places where Python 
distinguishes between "true" functions and callable objects. If one is 
looking at the overall Python system, the bug is in the way functions 
are bound. In general, Python very seldom distinguishes between objects 
based on type (rather than behaviour) and in particular, seldom 
distinguishes between functions and callable objects.

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

But now we're talking about a pretty subtle bug that has been in Python 
for over ten years and it so seldom bites anyone that it is probably nto 
worth fixing. (if I were to fix it I would add an add_method method to 
classes)

> Another example. I make quite heavy use of a trivial memoizer. The
> closure verison is much shorter, clearer and faster.

Well it boils down to a question of who would believe it is clearer. 
Lisp programmers think mutable closures are clearer. Perl programmers 
think having a variety of different ways to spell "if" is clearer than 
having just one. Part of the Zen of Python is try to encourage different 
camps towards common spellings of idioms.

bash-2.05a$ python -c "import this" | grep way
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.

> In short, whenever I want a _function_ which happens to have some
> internal state, I'd much rather use a closure than an instance of a class.

Barring the one ancient design misfeature above, callable instances are 
almost always good replacements for functions.

>>>all of which is irrelevant to my original point, which was to note
>>>out that saying "people don't use it much" is not a very convincing
>>>argument for not fixing something that is broken ... 
>>
>>OK, how about the argument above?
 > ...

OK, how about the argument at the top? If people needed it they would 
fake it as they do many other missing feature (in Python and other 
languages). That they don't fake it despite how easy it is to do so 
indicates that they don't need it.

  Paul Prescod






More information about the Python-list mailing list