Are decorators really that different from metaclasses...
Bengt Richter
bokr at oz.net
Fri Aug 27 23:03:39 EDT 2004
On Fri, 27 Aug 2004 18:39:51 -0400, Paul Morrow <pm_mon at yahoo.com> wrote:
>Anthony Baxter wrote:
>> On Thu, 26 Aug 2004 16:09:42 -0400, Paul Morrow <pm_mon at yahoo.com> wrote:
>>
>>>Yes, it doesn't seem all that complex, although I'm not sure that
>>>everyone reading this understands them and their subtleties. The
>>>following is an excerpt from
>>>http://docs.python.org/tut/node11.html#SECTION0011200000000000000000
>>>
>>>"A namespace is a mapping from names to objects. Most namespaces are
>>>currently implemented as Python dictionaries, but that's normally not
>>>noticeable in any way (except for performance), and it may change in the
>>>future. Examples of namespaces are: the set of built-in names (functions
>>>such as abs(), and built-in exception names); the global names in a
>>>module; and the local names in a function invocation. In a sense the set
>>>of attributes of an object also form a namespace."
>>
>>
>>>When I talk about namespaces, I include all of the above, including the
>>>sense mentioned in the last line. So an object's attributes constitute
>>>a namespace too. Therefore __doc__, being an attribute of the function
>>>object, is in the function object's /namespace/. And note that this is
>>>*not* a new namespace; it's been there all along.
>>
>>
>> "In a sense" is the bit you're missing here. You can't just hand-wave
>> and say that it's a namespace. It's *not* a namespace. If it was, you
>> could do any of these:
>>
>
>No I didn't miss it (I read that bit). In a sense, every object has
>it's own namespace. So that means that every class, every module, every
>function has a namespace (in a sense). The namespace (the mapping from
>names to objects) is stored in each object's special __dict__ attribute.
>
>Ok, and this is certainly apparent with classes.
>
> >>> class Foo:
> ... """docstring for Foo"""
> ...
> >>> Foo.__doc__
> 'docstring for Foo'
> >>> Foo.__dict__.keys()
> ['__module__', '__doc__']
> >>>
>
>And because of the parallels between the above class definition of Foo
>and the following function definition of baz, I would expect the same
>behavior.
>
> >>> def baz():
> ... """docstring of baz"""
> ...
> >>> baz.__doc__
> 'docstring of baz'
> >>> baz.__dict__.keys()
> []
>
>Say what? Why didn't the Python system put baz's docstring into it's
>namespace (__dict__)? And where did it put it?
>
>I would like to understand the answers to these questions. Can you
>answer them (will you)? If not, can you please point me at something
>that documents what's going on here?
>
>Thanks.
>
It looks to me like __doc__ is a descriptor (or c-code that acts like one)
(i.e., like a property) of the function class:
>>> def foo():
... 'foo doc string'
...
Find __doc__ in the class dict:
>>> type(foo).__dict__['__doc__']
<member '__doc__' of 'function' objects>
Check on its nature a little:
>>> type(type(foo).__dict__['__doc__'])
<type 'member_descriptor'>
It should have a __get__ method
>>> type(foo).__dict__['__doc__'].__get__
<method-wrapper object at 0x00901410>
Call that with foo as object instance:
>>> type(foo).__dict__['__doc__'].__get__(foo,None)
'foo doc string'
Try writing the __doc__ property (check for __set__ first):
>>> type(foo).__dict__['__doc__'].__set__
<method-wrapper object at 0x00901490>
Do long version of foo.__doc__ = 'new docstring'
>>> type(foo).__dict__['__doc__'].__set__(foo, 'new docstring') # foo.__doc__ = ...
Look at it using the short spelling:
>>> foo.__doc__
'new docstring'
And the long:
>>> type(foo).__dict__['__doc__'].__get__(foo,None)
'new docstring'
foo.func_doc seems to be implemented in a similar way:
>>> type(foo).__dict__['func_doc'].__get__(foo,None)
'new docstring'
>>> foo.func_doc
'new docstring'
Even the dict of a function instance appears to be implemented as a property:
>>> type(type(foo).__dict__['__dict__'])
<type 'getset_descriptor'>
>>> type(foo).__dict__['__dict__'].__get__(foo,None)
{}
>>> foo.x=123
>>> type(foo).__dict__['__dict__'].__get__(foo,None)
{'x': 123}
Short spelling:
>>> foo.__dict__
{'x': 123}
I haven't been into the implementation code, but this interpretation
of surface appearances seems to fit.
Regards,
Bengt Richter
More information about the Python-list
mailing list