On Thu, Jan 2, 2014 at 11:21 AM, spir <denis.s...@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' _______________________________________________ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor