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
,那么变量仍然可以正常工作。但在输入是类的情况下,这并不重要。