how to dynamically generate __name__ for an object?
Eric Snow
ericsnowcurrently at gmail.com
Wed Aug 10 12:54:54 EDT 2011
On Wed, Aug 10, 2011 at 8:48 AM, Fuzzyman <fuzzyman at gmail.com> wrote:
> On Aug 7, 4:06 am, Eric Snow <ericsnowcurren... at gmail.com> wrote:
>> Thought I knew how to provide a dynamic __name__ on instances of a
>> class. My first try was to use a non-data descriptor:
>>
>> # module base.py
>>
>> class _NameProxy(object):
>> def __init__(self, oldname):
>> self.oldname = oldname
>> def __get__(self, obj, cls):
>> if obj is None:
>> return self.oldname
>> if "__name__" not in obj.__dict__:
>> return str(obj.__context__)
>> return obj.__name__
>>
>> class _BaseMeta(type):
>> def __init__(cls, name, bases, namespace):
>> cls.__name__ = _NameProxy(name)
>>
>> class Base(object):
>> __metaclass__ = _BaseMeta
>>
>> $ python _base.py
>> Traceback (most recent call last):
>> ...
>> File "/usr/local/lib/python2.4/site-packages/base.py", line xx, in __init__
>> cls.__name__ = _NameProxy(name)
>> TypeError: Error when calling the metaclass bases
>> can only assign string to Base.__name__, not '_NameProxy'
>>
>> Needless to say I was surprised. After looking in typeobject.c, I
>> believe that __name__ must be a string where classes are concerned[1].
>> So if I want all my instances to have a __name__ attribute, and for
>> it to be dynamically provided if it isn't set on the instance, what
>> are my options? Or maybe I did something wrong and it should work as
>> I expected?
>>
>
> __name__ can be a descriptor, so you just need to write a descriptor
> that can be fetched from classes as well as instances.
>
> Here's an example with a property (instance only):
>
>>>> class Foo(object):
> ... @property
> ... def __name__(self):
> ... return 'bar'
> ...
>>>> Foo().__name__
> 'bar'
Thanks! Your example is exactly what I didn't try in the first place,
but should have. I was thinking of __name__ on a class as a simple
data attribute. My original worry was that by adding a descriptor for
__name__ on my class, I would overwrite the name of the class, hence
the elaborate descriptor.
However, for type objects (classes) __name__ is a data descriptor and
the actual name isn't stored in __name__. I was staring that right in
the face (the link I provided is for the setter method of the __name__
"property" for type objects). I guess it was a "forest for the trees"
moment.
Because of attribute lookup in Python, "Base.__name__" uses the
equivalent of "Base.__class__.__name__.__get__(..., Base,
Base.__class__)".
Anyway, thanks for making me see how dumb I am! <wink>
-eric
>
> Michael
> --
> http://voidspace.org.uk/
> --
> http://mail.python.org/mailman/listinfo/python-list
>
More information about the Python-list
mailing list