Making classes from Metaclasses globally available

Peter Otten __peter__ at web.de
Wed Jun 16 12:47:14 EDT 2004


Jacek Generowicz wrote:

> Peter Otten <__peter__ at web.de> writes:
> 
>> Jacek Generowicz wrote:
>> 
>> > Peter Otten <__peter__ at web.de> writes:
>> > 
>> >> Note, however, that dynamically inserting variables is not the best
>> >> programming practice. When you don't know the variable name in
>> >> advance, what would be the benefit of being able to access the
>> >> object via its identifier?
>> > 
>> > When _who_ doesn't know the variable name in advance of _what_ ?
>> 
>> I may be fighting with the english language here - and lose...
> 
> Don't think so; I was merely trying to point out that "you" can have
> different meanings in this context (program author, program client),
> and that the same is true of "in advance" (before the program is
> written, before the program is run).

OK, I missed that point the first time.

>> - but why can't your function_with_a_long_name() just return the root
>> *object* and let the user decide about the appropriate name
> 
> This only works if your objects share a single common root.

For everything else, there are tuples or the Bunch class.

> Still, what you are doing is programatically adding attributes to some
> namespace ... and maybe the user should have the option of dumping

Stop, no further from here...

> those attributes in the global namespace, just like he does with
> "import".

Too late :-)

>> The recommendation to avoid dynamic manipulations of the global namespace
>> was not meant as a rule carved in stone, but rather a means to write
>> cleaner code and avoid errors that may be hard to reproduce.
> 
> You asked
> 
>   When you don't know the variable name in advance, what would be the
>   benefit of being able to access the object via its identifier?
> 
> I merely took your question literally (even though it was probably
> rhetorical) and offered examples of such use cases (probably
> rhetorically :-).

You also slightly broadened the context. I may have been too sure about how
the OP would answer it, but the above question may as well serve as the
criterion whether to stick with the original dictionary or use a class
(including modules created on the fly, I tried that just now and it seems
to work). I'm still convinced that the generation code, the generated code,
and the client code should each have its own namespace.

> In summary, the answer is:
> 
>   Just because the author of the code does not know the the name at
>   the time he writes the code, does not mean that the code's client
>   cannot know the name before he runs the code.

D'accord. Again, a class offers benefits over a module here, as you can
lazily create the objects, when the client accesses them. E. g.:

class Lift(list):
    _globals = {}
    def __getattr__(self, name):
        exec """
def lift(self):
    for item in self:
        yield item.%s
""" % name in Lift._globals
        lift = Lift._globals["lift"]
        setattr(Lift, name, property(lift))
        return lift(self)

if __name__ == "__main__":
    class Person:
        def __init__(self, name):
            self.name = name
    people = Lift(map(Person, "Peter Paul Mary".split()))
    print list(people.name)

Across all Lift instances, __getattr__() will only be called once for every
name. 
Or maybe I just prefer AttributeError over NameError...

Peter




More information about the Python-list mailing list