[Tutor] what's your name? (to a class)
eryksun
eryksun at gmail.com
Thu Jan 2 18:40:24 CET 2014
On Thu, Jan 2, 2014 at 11:21 AM, spir <denis.spir at gmail.com> wrote:
> dir(C.__dir__) # here is __name__ :
It's good that you've brought up the special method __dir__, because
that's at the heart of the issue. In 3.3, objects use object.__dir__
unless the type overrides it:
>>> vars(object)['__dir__']
<method '__dir__' of 'object' objects>
>>> vars(type)['__dir__']
<method '__dir__' of 'type' objects>
Your class C is an instance of `type`. Here's the comment for
`type_dir` in typeobject.c:
__dir__ for type objects: returns __dict__ and __bases__.
We deliberately don't suck up its __class__, as methods
belonging to the metaclass would probably be more
confusing than helpful.
Also, there's a note about this in the docs:
http://docs.python.org/3/library/functions.html#dir
Because dir() is supplied primarily as a convenience for
use at an interactive prompt, it tries to supply an
interesting set of names more than it tries to supply a
rigorously or consistently defined set of names, and
its detailed behavior may change across releases. For
example, metaclass attributes are not in the result
list when the argument is a class.
Prior to 3.3 (see issue 12166), there's no type.__dir__ or
object.__dir__ built-in methods, so this behavior is baked in.
http://bugs.python.org/issue12166
Back to __name__, for a built-in type the getter decodes the UTF-8
byte string in the `tp_name` slot. It's an example of why you should
rarely depend on identity checks as opposed to equality. You might be
lulled into complacency by how it works for heap types:
>>> name1 = C.__name__
>>> name2 = C.__name__
>>> name1 is name2
True
But there's a built-in surprise:
>>> name1 = type.__name__
>>> name2 = type.__name__
>>> name1 is name2
False
For non-class objects, the rules vary with the type. For a built-in
method, the name is created on the fly from the `ml_name` field of its
`PyMethodDef`. There's no setter, so it's readonly. For a function
object, you can only set the name to a string and you can't delete it.
But you can set it to a name with a null in it since it doesn't need
compatibility with a C null-terminated string:
>>> f = lambda:0
>>> f.__name__ = '\x00'
>>> f.__name__
'\x00'
More information about the Tutor
mailing list