GLHF GLHF - 6 months ago 20
Python Question

Why does ' dir(1) is dir(True) ' return False

From this quieston's answer


is will return True if two variables point to the same object, == if the objects referred to by the variables are equal.


Aren't
dir(1)
and
dir(True)
point to the same object? Both of them prints a list of the same methods. Am I missing something about object here?

>>> dir(1) == dir(True)
True
>>> dir(1) is dir(True)
False
>>>

Answer

First of all, True is not 1:

>>> True is not 1
True

Second, as the documentation says

dir([object])

[...] With an argument, attempt to return a list of valid attributes for that object.

If the object has a method named __dir__(), this method will be called and must return the list of attributes. This allows objects that implement a custom __getattr__() or __getattribute__() function to customize the way dir() reports their attributes.

If the object does not provide __dir__(), the function tries its best to gather information from the object’s __dict__ attribute, if defined, and from its type object. The resulting list is not necessarily complete, and may be inaccurate when the object has a custom __getattr__().

The resulting list is sorted alphabetically. [...]


Now, int and bool both have the __dir__ slot filled from object.__dir__:

>>> int.__dir__
<method '__dir__' of 'object' objects>
>>> bool.__dir__
<method '__dir__' of 'object' objects>

And the documentation for object.__dir__ adds this one extra bit of information:

object.__dir__(self)

Called when dir() is called on the object. A sequence must be returned. dir() converts the returned sequence to a list and sorts it.

As the documentation says, dir constructs a new list for each invocation and then sorts it. (We could also look into the code for _dir_object which calls PySequence_List on the return value of __dir__; PySequence_List takes a sequence as an argument, and returns a new list with the same elements as the original sequence; this newly created list is then sorted and returned)

>>> a = 1
>>> dir(a) is dir(a)
False

Third, True is an instance of type bool, which is a subclass of int.

 >>> isinstance(True, bool)
 True
 >>> isinstance(1, int)
 True
 >>> issubclass(bool, int)
 True
 >>> isinstance(True, int)
 True

Additionally, bool does not add any methods that are not already present in int. And because the resulting list is sorted alphabetically,

>>> dir(1) == dir(True)
True