Python 2和3之间“dir”的区别

时间:2016-02-10 19:53:14

标签: python

以下代码在Python 2和Python 3中的行为有所不同,我不确定原因。

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

a = Dataset()
a.Hello

Python 3中的结果:

> Hello

Python 2中的结果:

__members__
__members__
__methods__
...

无限制地直到达到递归上限。 “dir”的行为有什么不同?

编辑:有解决方法吗? self。 dict 是显而易见的选择,但它不包含在我的代码中成为问题的函数。

3 个答案:

答案 0 :(得分:6)

Python 2.7和3.5中dir的文档似乎相同 - 没有实现细节。但显然,Python 2中的dir()会调用__getattr__来导致无限递归。

但是,两个文档集都说

  

因为dir()主要是为了方便在交互式提示中使用而提供的,所以它试图提供一组有趣的名称而不是试图提供严格或一致定义的名称集,并且其详细行为可能会改变跨版本。例如,当参数是类时,元类属性不在结果列表中。

关于它是一种便利的说明非常重要。

如果您修改__getattr__以查看self.__dict__而非使用dir(),则问题就会消失。

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

答案 1 :(得分:3)

在不检查源代码的情况下,我不能说为什么会发生这种情况(尽管我有一些假设),但这是一个非常简单的解决方法:

class Dataset(object):
    def __getattr__(self, item):
        try:
            super(Dataset, self).__getattr__(item)
        except AttributeError:
            print(item)

答案 2 :(得分:1)

不需要检查if not item in dir(self)

中的def __getattr__ 如果项目在dir(自我)中列出,则

__getattr__不会被调用 您可以将代码设为

class Dataset(object):
    x = 12
    def __getattr__(self, item):
        print(item)

a = Dataset()
a.Hello  # print Hello
a.x      # return 12