Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.python > #10998 > unrolled thread
| Started by | Eric Snow <ericsnowcurrently@gmail.com> |
|---|---|
| First post | 2011-08-06 21:06 -0600 |
| Last post | 2011-08-10 10:54 -0600 |
| Articles | 7 — 4 participants |
Back to article view | Back to comp.lang.python
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
| From | Eric Snow <ericsnowcurrently@gmail.com> |
|---|---|
| Date | 2011-08-06 21:06 -0600 |
| Subject | how 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]
| From | Steven D'Aprano <steve+comp.lang.python@pearwood.info> |
|---|---|
| Date | 2011-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]
| From | Eric Snow <ericsnowcurrently@gmail.com> |
|---|---|
| Date | 2011-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]
| From | Fuzzyman <fuzzyman@gmail.com> |
|---|---|
| Date | 2011-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]
| From | Ian Kelly <ian.g.kelly@gmail.com> |
|---|---|
| Date | 2011-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]
| From | Fuzzyman <fuzzyman@gmail.com> |
|---|---|
| Date | 2011-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]
| From | Eric Snow <ericsnowcurrently@gmail.com> |
|---|---|
| Date | 2011-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