Feature request: String-inferred names

Brad Harms FearsomeDragonfly at gmail.com
Mon Nov 30 05:04:37 CET 2009


On Sun, Nov 29, 2009 at 7:49 PM, Lie Ryan <lie.1296 at gmail.com> wrote:

> On 11/29/2009 12:22 PM, The Music Guy wrote:
>
>> When I first started seeing @ show up in Python code, I said "what the
>> heck is that? It looks so weird and _ugly_.I would never try to mess
>> with that." But I started seeing it more and more, so I asked #python
>> what it was. They told me about decorators, so I looked it up in the
>> docs, and I thought the idea was interesting. It took me a while to
>> figure out exactly how they worked--and judging from messages I've
>> seen in #python a number of people have the same trouble understanding
>> them.
>>
>
> And we don't want a second flood of users asking about foo.$bar.
>
>
>  My point is that any particular syntax would look ugly to you only
>> because you haven't seen it in use enough, and haven't used it enough
>> yourself.
>>
>
> You're absolutely right, and I have *never needed* to use the plain
> getattr/setattr/delattr enough to even bother considering a syntax that
> already looks ugly at first sight. For @decorators, everyone used it *often
> enough* BEFORE it turned into a syntax that the ugly syntax is justified and
> become "acceptable". If you can find a syntax that doesn't look ugly at
> first sight +0, fine by me; otherwise -1, I don't want to be forced to read
> an ugly syntax for a feature that I don't use often enough. It's not just
> the syntax, the necessity+syntax don't add up well.
>
>
> > But of course you haven't--it's not currently a valid
>
>> syntax. However, the ugliness would seem to go away after the syntax
>> had been in use for a while. And again, the EXACT syntax of the
>> feature can be adjusted until its "just right".
>>
>
> In so far, your definition of adjusting only means something around
> "[a-zA-Z0-9_]+\.[^a-zA-Z0-9_][<{(\[]?[a-zA-Z0-9_]+[>})\]]?"



> that class of syntax is ugly; some are more acceptable (e.g. obj.[arg]) the
> old thread have spawned better alternatives than that class of syntax.
>


>  As for my specific use case, it's somewhat difficult to explain.
>>
>
> You know that:
> If the implementation is hard to explain it's a bad idea.
>                                         -- Zen of Python --
>
> right?
>
>
> > The
>
>> general idea was to isolate a pattern that I spotted repeated in
>> several unrelated parts of my project. The pattern manifested itself
>> as a set of 4-5 methods and/or properties on a class whose objects
>> were designed to work in conjunction with other objects that fit a
>> particular behavior. These other objects had methods and properties
>> that were designed to interact with the first type of object in a
>> similar but--how should I say--"inverted" fashion.
>>
>
> Do you mean something like this?
>
> class A(object):
>    @property
>    def the_b(self):
>        return self._b
>    @the_b
>    def the_b(self, new_b):
>        self._b = new_b
>        self._b._a = self
>
> class B(object):
>    @property
>    def the_a(self):
>        return self._a
>    @the_a
>    def the_a(self, new_a):
>        self._a = new_a
>        self._a._b = self
>
> am I getting you right? If not, please elaborate and give an example of
> what you actually meant.
>
> --
> http://mail.python.org/mailman/listinfo/python-list
>


I understand that in all likelyhood this feature won't be added to Python
anytime soon, if at all. But I'd like to continue this discussion anyway;
it's been enlightening for me. Even though I don't agree with the views of
some of the people who've replied, I like the insight. And anyway, I think
that if the syntax were already present, people would feel a lot more
positively about it; it's the idea of adding it in so late in the game that
people seem to have a problem with for the most part.

It doesn't seem like anybody besides inhahe has actually realized that my
proposition is actually different than PEP 363 in a subtle but crucial way.
It's not _literally_ a shorthand for accessing the *attr functions; that's
just the way I originally assumed it would be used most often. However, I
have since realized that the syntax is more powerful than I originally
thought: ANYWHERE that a name appeared--this includes function names, class
names, function parameters, possibly even module names--could be replaced by
an expression that would be evaluated to the name. That makes the use of any
kind of brackets, except maybe <angle brackets>, bad options, as it would
conflict with [lists,] {dicts,} (tuples,) or generic parenthesized
(expressions). There must be a unique indicator of some kind, something that
isn't already in use by the interpreter. That way there is no possible way
that it could get confused with another syntactical construct.

So you could do something like this:


def class_factory(this, that)
    get_that = "get_"+that
    set_that = "set_"+that
    _that = "_" + that

    class $this (object):

        def __init__(self, $that = None):
            self.$_that = $that

        def $get_that (self):
            return self.$_that

        def $set_that (self, $that):
            self.$_that = $that

        $that = property($get_that, $set_that)

    return $this


Compare the code above with this approximation that uses the current syntax
rules:


def class_factory(this, that):
        get_that_name = "get_"+that
        set_that_name = "set_"+that
        _that = "_" + that

        class This(object):

            def __init__(self, that = None):
                setattr(self, _that, that)

        This.__name__ = this

        def get_that(self, that):
            return getattr(self, _that)
        get_that.__name__ = get_that_name
        setattr(This, get_that_name, get_that.__get__(None, This))

        def set_that(self, that):
            setattr(self, _that, that)
        set_that.__name__ = set_that_name
        setattr(This, set_that_name, set_that.__get__(None, This))

        setattr(This, that, property(get_that, set_that))

        return This


Given either of the two class factories above, the following can be done:


Spam = new_foo_class("Spam", "eggs")
Eggs = new_foo_class("Eggs", "spam")

myspam = Spam()
myeggs = Eggs()

myeggs.spam = myspam
myspam.set_eggs( myeggs )

print myspam.get_eggs()    # prints "<Eggs object at ...>"
print myeggs._spam     # prints "<Spam object at ...>"


However, the following can only be done using the first example:


myspam.set_eggs( eggs = myeggs )


For the second example, it would have to be this:


myspam.set_eggs( that = myeggs )


The reason is that the parameter names for the first example are determined
dynamically, which I don't think python allows you to do currently. The
closest thing is **kwargs, but that's less readable than an actual parameter
name.

That was a relatively simple example; classes as simple as the ones
generated by the  It is more likely that the class generation could would
appear in a metaclass's class constructor or decorator function, and there
would be more than just the three attributes given.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-list/attachments/20091129/0d0969d0/attachment.html>


More information about the Python-list mailing list