Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference in "dir" between Python 2 and 3

Tags:

python

The following code behaves differently in Python 2 and Python 3, and I'm not sure why.

class Dataset(object):
    def __getattr__(self, item):
        if not item in dir(self):
            print(item)

a = Dataset()
a.Hello

The result in Python 3:

> Hello

The result in Python 2:

__members__
__members__
__methods__
...

ad infinitum until a recursion ceiling is reached. What is the difference in the behavior of "dir"?

Edit: And is there a workaround? self.dict is the obvious choice but it doesn't include functions which turns out to be a problem in my code.

like image 681
triphook Avatar asked Feb 10 '16 19:02

triphook


People also ask

Is python 2 and Python 3 same?

Python 3 has an easier syntax compared to Python 2. A lot of libraries of Python 2 are not forward compatible. A lot of libraries are created in Python 3 to be strictly used with Python 3. Python 2 is no longer in use since 2020.

What does dir () mean in python?

Python dir() Function The dir() function returns all properties and methods of the specified object, without the values. This function will return all the properties and methods, even built-in properties which are default for all object.

What is __ DIR __ in python?

Python dir() The function dir python is responsible for returning the valid list of the attributes for the objects in the current local scope. For example: If an object of a method called is named as __dir__(), the function must return a list of attributes that are associated with that function.

What is the difference between print in python 2 and 3?

In Python 2, print is a statement that does not need a parenthesis. In Python 3, print is a function and the values need to be written in parenthesis.


2 Answers

The documentation for dir in Python 2.7 and 3.5 seems identical - there are no implementation details. But clearly, dir() in Python 2 invokes __getattr__ causing the infinite recursion.

However, both documentation sets do say that

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.

That note about it being a convenience is significant.

If you modify your __getattr__ to look at self.__dict__ instead of using dir(),the problem goes away.

In [5]: class Dataset(object):
          def __getattr__(self, item):
            if not item in self.__dict__:
              print(item)
   ...:             

In [6]: a = Dataset()

In [7]: a.Hello
Hello
like image 108
kdopen Avatar answered Oct 23 '22 02:10

kdopen


Without examining the source code, I can't say why this happens (although I have some hypotheses), but here is a pretty simple workaround:

class Dataset(object):
    def __getattr__(self, item):
        try:
            super(Dataset, self).__getattr__(item)
        except AttributeError:
            print(item)
like image 36
mipadi Avatar answered Oct 23 '22 02:10

mipadi