Python 是否有可能找出类的实例是否有一个dict?

Python 是否有可能找出类的实例是否有一个dict?,python,python-3.x,Python,Python 3.x,给定一个任意类X作为输入,是否可以确定X的实例是否具有\uuuuuuuu dict\uuuuu 我尝试了hasattr(X,'.\uuu dict'.',但这不起作用,因为它检查类对象是否具有\uu dict\uu: >>> hasattr(int, '__dict__') True >>> vars(5) Traceback (most recent call last): File "<stdin>", line 1, in <mo

给定一个任意类
X
作为输入,是否可以确定
X
的实例是否具有
\uuuuuuuu dict\uuuuu


我尝试了
hasattr(X,'.\uuu dict'.'
,但这不起作用,因为它检查类对象是否具有
\uu dict\uu

>>> hasattr(int, '__dict__')
True
>>> vars(5)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: vars() argument must have __dict__ attribute
>>> hasattr(int, '__slots__')
False
>>> vars(5)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: vars() argument must have __dict__ attribute
我还考虑使用
对象创建
X
的实例。\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu(X)
(绕过
X.\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu

>>> hasattr(object.__new__(int), '__dict__')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: object.__new__(int) is not safe, use int.__new__()
hasattr(object.\uuuuuu new\uuuuuuuuuu(int),“\uuuuu dict\uuuuuuuuuuuu”) 回溯(最近一次呼叫最后一次): 文件“”,第1行,在 TypeError:object.\uuuuuuuuuuuuuuuuuuuuuuuu(int)不安全,请使用int.\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
是否可以在不调用任何未知/不受信任的代码(如
X
的构造函数)的情况下执行此操作?

dir()

>>> class MyInt(int):
...     pass
...
>>> '__dict__' in dir(int)
False
>>> '__dict__' in dir(MyInt)
True
>>>
您可以使用模块获取实例的所有非方法属性

>>> import inspect
>>> from operator import itemgetter

>>> b = 5
>>> inspect.getmembers(b, lambda a:not(inspect.isroutine(a)))
将生成
b
的所有属性及其小说明的长列表

我做了一些测试,看看它是如何工作的,以下是我的发现

>>> def get_attrs(x):
       return list(map(itemgetter(0), inspect.getmembers(x, lambda a:not(inspect.isroutine(a)))))

>>> "__dict__" in get_attrs(type(b))
>>> False

>>> l = [1,2,3]
>>> "__dict__" in get_attr(type(l))
>>> False

>>> class A:
       pass

>>> a = A()
>>> "__dict__" in get_attr(type(a))
>>> True

我只是想说清楚。您希望能够预测某个类的实例
X
是否将包含
\uuuu dict\uuuu
?理论上,不可能创建一个C级扩展类型,而该扩展类型不具有
\uuu dict\uuu
作为预先命名的属性,但在执行
\uuuuu init\uuuu
期间,它总是变异
\uuuu init\uuuu
内部的实例,以将某些内容分配给属性名
\uuuuuuu dict\uuuu
?如果是这样,这意味着在不检查源代码的情况下不可能提前知道,因为实例严格地接收
\uuuu dict\uuuu
作为
\uuu init\uuu
的副作用。它甚至可能是有条件的,例如,如果
datetime.datetime.now()
大于下午3点,则添加
\uuuu dict\uuuu
。类的
\uu new\uuuuu()
也可以根据提供的参数在两个子类之间进行选择,其中一个使用
\uu slots\uuu
,另一个具有
\uu dict\uuu>,这样就使得答案不确定了。@Laszlowaty这是正确的,是的。@Aran Fey那么它就可以在创建实例的过程中动态地修改类对象,使其具有
\uu dict\uuu
。我知道这些都是小案子,很像。但问题是,它们说明了你不能用一般的方法来确定答案。你能做的最好的事情就是对某些内置类型和用户定义类型做出假设。这对我来说已经足够好了,但我仍然会挑剔(因为我明确要求一个不执行未知代码的解决方案):
dir(X)
将调用
X
的元类
\uu dir\ucode>方法(如果它存在的话)。也就是说,我不介意执行
\uuuu dir\uuuu
方法-我想避免调用
X
的构造函数,因为构造函数有时会有副作用,但我不认为有人会疯狂到在
\uu dir\uuu
方法中产生副作用。它不是在调用
X
的构造函数吗?:)@Laszlowaty是的,但仅用于演示目的。在dir(X)
中调用
“\uuuuu dict\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。但是,如果没有对实例进行所有的
dir
调用,这个答案确实可以变得更加清晰——毕竟,我甚至没有一个
X
实例可以调用
dir
,那么显示
dir(实例)
的输出有什么意义呢?如果稍加润色,这个答案会受益匪浅。我正在准备回答你的问题,但我需要做更多的研究。简短回答:这是不可能的。您在这里看到的唯一原因是继承。如果您在python2中将类定义为
类A:…
您将收到
[''''''''''''''''''.''.''.'初始化'.''.''.'模块'.''.'.'.''.'.'.''.'.''.'.'.''.''.'.'代码>>作为
目录(A)
的输出。当然,在python3中,您将在输出中收到
\uuuu dict\uuuu
,但您仍然不知道它是内置的
dict
方法还是其他方法。现在更好了!这似乎是可行的,但它远不如
dir
解决方案那样优雅、快速和可读。另外,由于问题表明您获得了一个类作为输入,我不明白您为什么在
5
[1,2,3]
a
等实例上调用
get\u attrs
。你应该在
int
list
A
上调用它。@Aran Fey是的,我同意你的看法。我在考虑输入将是类的一个实例。在这种情况下,如果一个类重写了
\uuuuu dir\uuuuu
,那么您可能无法获得该类的所有属性,但是只要定义了
\uuu dict\uuuu
,那么
变量仍然可以正常工作。但在输入是类的情况下,这并不重要。