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