[Python-ideas] Assignment decorators (Re: The Descriptor Protocol...)

Ben Rudiak-Gould benrudiak at googlemail.com
Thu Mar 10 07:28:06 CET 2011


(This will probably be unthreaded, because I don't have the original
thread root in my mailbox and I didn't want to reply to a random
deeply nested message.)

All syntax aside, I'm unhappy with the semantics of this idea, and I'd
like some clarification. Specifically, I'd like to know what a name
is.

First, namedtuple:

 >>> import collections
 >>> def f():
        foo = collections.namedtuple('foo', 'a b')
        return foo, foo(a=1, b=2)

 >>> f()
 (<class '__main__.foo'>, foo(a=1, b=2))
 >>>

The namedtuple I defined is not __main__.foo; there's no such symbol.
And it's not foo either, by the time it's asked for its repr(). The
name argument to namedtuple has never been more than a hack that
kinda-sorta works in the obvious cases. It's useful for debugging, not
so much for production code. The same is true of class and function
names, and they do have special syntax, but even so, this is not the
sort of thing I'd want to enshrine in new syntax. If there's going to
be new syntax, it should be part of a new general facility for runtime
introspection of assignment targets, not a hacky way of passing a
stringified identifier that has no meaning outside of the context of
the caller.

In Python right now, you can do this:

 def deftuple(name, fields):
    globals()[name] = collections.namedtuple(name, fields)

 deftuple('foo', 'a b')

or this:

 def namedtupleclass(name, args, body):
    fields = body.pop('fields')
    module = body.pop('__module__')
    assert not args and not body
    return collections.namedtuple(name, fields)

 class foo(metaclass=namedtupleclass): fields = 'a b'

I like these better than new syntax, because their level of hackiness
roughly matches the intrinsic hackiness of the thing that they are
doing. (By the way, I first wrote my metaclass to pass (module + '.' +
name) as the first argument to namedtuple, but discovered that
namedtuple doesn't support dotted tuple names. So much for that
pathetic attempt at proper scoping.)

overridable_property seems quite different, if I understand it
correctly. In this case no string representation of the name is ever
leaked to the outside world, and there's no problem of scope naming.
Instead, the issue is that you want to create several related
attributes that can refer to each other, from a common base name.

It seems to me that the most straightforward way of doing this is:

 def def_overridable_property(name, classdict):
    classdict['get_' + name] = ...
    classdict['set_' + name] = ...
    classdict[name] = ...

 class Foo:
    def_overridable_property('foo', locals())

I realize that this is illegal by the current documentation of
locals(), but there's no reason that it couldn't be legal and
documented, is there? It might slow down the execution of class
definitions; do those need to be fast? I wouldn't propose such a thing
for function locals, but class locals get turned into a dictionary in
the end anyway. Again, I like this solution because it seems roughly
as hacky as the thing that it's designed to do.

-- Ben



More information about the Python-ideas mailing list