Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #10998 > unrolled thread

how to dynamically generate __name__ for an object?

Started byEric Snow <ericsnowcurrently@gmail.com>
First post2011-08-06 21:06 -0600
Last post2011-08-10 10:54 -0600
Articles 7 — 4 participants

Back to article view | Back to comp.lang.python


Contents

  how to dynamically generate __name__ for an object? Eric Snow <ericsnowcurrently@gmail.com> - 2011-08-06 21:06 -0600
    Re: how to dynamically generate __name__ for an object? Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2011-08-07 14:47 +1000
      Re: how to dynamically generate __name__ for an object? Eric Snow <ericsnowcurrently@gmail.com> - 2011-08-07 02:05 -0600
    Re: how to dynamically generate __name__ for an object? Fuzzyman <fuzzyman@gmail.com> - 2011-08-10 07:48 -0700
      Re: how to dynamically generate __name__ for an object? Ian Kelly <ian.g.kelly@gmail.com> - 2011-08-10 09:25 -0600
        Re: how to dynamically generate __name__ for an object? Fuzzyman <fuzzyman@gmail.com> - 2011-08-10 09:38 -0700
      Re: how to dynamically generate __name__ for an object? Eric Snow <ericsnowcurrently@gmail.com> - 2011-08-10 10:54 -0600

#10998 — how to dynamically generate __name__ for an object?

FromEric Snow <ericsnowcurrently@gmail.com>
Date2011-08-06 21:06 -0600
Subjecthow to dynamically generate __name__ for an object?
Message-ID<mailman.2004.1312686417.1164.python-list@python.org>
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?

-eric


[1] http://hg.python.org/cpython/file/default/Objects/typeobject.c#l244

[toc] | [next] | [standalone]


#10999

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2011-08-07 14:47 +1000
Message-ID<4e3e18ee$0$29985$c3e8da3$5496439d@news.astraweb.com>
In reply to#10998
Eric Snow 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:

Perhaps you should explain what you are trying to do. If you want to give
instances their own name, why not just give them an instance
attribute "name"? Double-leading-and-trailing-underscore attributes are
reserved for Python, and have special semantics.


-- 
Steven

[toc] | [prev] | [next] | [standalone]


#11002

FromEric Snow <ericsnowcurrently@gmail.com>
Date2011-08-07 02:05 -0600
Message-ID<mailman.2007.1312704349.1164.python-list@python.org>
In reply to#10999
On Sat, Aug 6, 2011 at 10:47 PM, Steven D'Aprano
<steve+comp.lang.python@pearwood.info> wrote:
> Eric Snow 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:
>
> Perhaps you should explain what you are trying to do. If you want to give
> instances their own name, why not just give them an instance
> attribute "name"? Double-leading-and-trailing-underscore attributes are
> reserved for Python, and have special semantics.

Again useful information failed to make it from my head to the
keyboard. :)  Currently I am looking at objects, regardless of their
types, and keying off their name.  If it is a module, class, or
function object, the name should be stored in __name__ already.  If it
is an instance of the Base class I demonstrated, I would like to
maintain that convention.

However, you may have a good point.  In other code I can simply check
for the name attribute I choose for my objects and also check for
__name__.  I suppose I just liked the idea of having a single
attribute to check.

-eric

>
>
> --
> Steven
>
> --
> http://mail.python.org/mailman/listinfo/python-list
>

[toc] | [prev] | [next] | [standalone]


#11132

FromFuzzyman <fuzzyman@gmail.com>
Date2011-08-10 07:48 -0700
Message-ID<afb6fca6-126a-44cf-8ef6-ba29c8f2ef93@r12g2000vbe.googlegroups.com>
In reply to#10998
On Aug 7, 4:06 am, Eric Snow <ericsnowcurren...@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'

Michael
--
http://voidspace.org.uk/

[toc] | [prev] | [next] | [standalone]


#11135

FromIan Kelly <ian.g.kelly@gmail.com>
Date2011-08-10 09:25 -0600
Message-ID<mailman.2117.1312989942.1164.python-list@python.org>
In reply to#11132
On Wed, Aug 10, 2011 at 8:48 AM, Fuzzyman <fuzzyman@gmail.com> wrote:
> __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'

But:

>>> Foo.__name__
'Foo'
>>> repr(Foo())
'<__main__.Foo object at 0x00CAFFD0>'
>>> Foo.__dict__['__name__']
<property object at 0x00CBA6F0>

It seems that Foo.__name__ and Foo.__dict__['__name__'] are not the
same thing, and Python itself only uses the former.

[toc] | [prev] | [next] | [standalone]


#11142

FromFuzzyman <fuzzyman@gmail.com>
Date2011-08-10 09:38 -0700
Message-ID<1419d2bf-d71a-4f85-afc1-215274bd4b9a@w11g2000vbp.googlegroups.com>
In reply to#11135
On Aug 10, 4:25 pm, Ian Kelly <ian.g.ke...@gmail.com> wrote:
> On Wed, Aug 10, 2011 at 8:48 AM, Fuzzyman <fuzzy...@gmail.com> wrote:
> > __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'
>
> But:
>
> >>> Foo.__name__
> 'Foo'

That's why I said "you just need to _write_ a descriptor that can be
fetched from classes as well as instances". The example with property
was to show that it *could* be a descriptor. You can write descriptors
with custom behaviour when fetched from a class.

However it turns out that you're right and I'm wrong; __name__ is
special:

>>> class descriptor(object):
...  def __get__(*args):
...   return 'bar'
...
>>> class Foo(object):
...  __name__ = descriptor()
...
>>> Foo.__name__
'Foo'
>>> Foo().__name__
'bar'
>>> class Foo(object):
...  name = descriptor()
...
>>> Foo.name
'bar'

As Eric points out in his original slot, types have their __name__
slot filled in with a string in typeobject.c

All the best,

Michael
--
http://voidspace.org.uk/

[toc] | [prev] | [next] | [standalone]


#11144

FromEric Snow <ericsnowcurrently@gmail.com>
Date2011-08-10 10:54 -0600
Message-ID<mailman.2122.1312995302.1164.python-list@python.org>
In reply to#11132
On Wed, Aug 10, 2011 at 8:48 AM, Fuzzyman <fuzzyman@gmail.com> wrote:
> On Aug 7, 4:06 am, Eric Snow <ericsnowcurren...@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
>

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.python


csiph-web