[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