问题
如何在整个程序的生命周期中唯一标识Python中的类?我对内置类型和用户定义类型都感兴趣。 id
不合适,因为:
[
id
] returns the “identity” of an object. This is an integer (or long integer) which is guaranteed to be unique and constant for this object during its lifetime. Two objects with non-overlapping lifetimes may have the same id() value.
可能吗?
具体用例
我有一个字典,其中字符串作为键,Python 的类型/类作为值。例如:
{'tid': int, 'name': str, 'color': str}
问题是唯一标识字符串和类型的组合并将其用作比较的基础。因此,字典 {'tid': int, 'name': str, 'color': str}
和字典 {'tid': float, 'name': str, 'color' : str}
应该被判定为不相等。类似地, {'tid': int, 'name': str, 'color': str}
和 {'tid': int, 'name': str, 'colour': str }
.
陷阱
此外,如果名称和类型经过哈希处理并存储结果,则比较应该有效(因为比较整数比比较字典更快)。例如:
def hash_heading(dct):
s = ''
for k, v in OrderedDict(dct).items():
s += k + str(id(v))
return hash(s)
这会带来这样的风险:两个具有不相交生命周期的类 A 和 B 会被分配相同的 id
(以防 A 在声明 B 之前被销毁),因此检查会通过。
最佳答案
首先:内置类型和自定义 Python 类型都只是 Python 对象。就 id()
而言,您无需担心任何差异。
您确实想使用id()
来跟踪类(class)。因为如果 id()
已更改,则意味着您不再拥有相同的类。反之亦然,因为 id()
值可以重复用于生命周期不重叠的对象,因此具有相同的 id()
值并不意味着您可以仍然有相同的对象。
类应该是单例的。类很少被重新定义,因为大多数代码会在模块级别定义它们,并且模块也是单例(它们位于 sys.modules 中并且仅加载一次)。
此外,具有不同 ID 的类不是同一个类。它可能具有相同的名称,也可能位于同一模块中,但您不能使用其中一个来断言另一个的实例属于同一类型。您不应该尝试在 Python 的整个生命周期中跟踪类并忽略它们的 id()
值。
一个快速演示来说明为什么不能:
>>> import types
>>> module.Foo = type('Foo', (), {'__module__': module.__name__})
>>> module.Foo
<class 'foo.Foo'>
>>> id(module.Foo)
140646171069480
>>> foo_instance = module.Foo()
>>> isinstance(foo_instance, module.Foo)
True
>>> module.Foo = type('Foo', (), {'__module__': module.__name__}) # new class, same name, same location!
>>> id(module.Foo)
140646170684440
>>> isinstance(foo_instance, module.Foo)
False
>>> type(foo_instance)
<class 'foo.Foo'>
>>> type(foo_instance) is not module.Foo
True
foo_instance
实例是类 Foo
的实例,但它是它的第一个 Foo
类是一个实例。通过创建一个新的 Foo
类,id()
随之改变,但它告诉您我们现在有一个不同的对象,一个独特的新类对象。
如果您只跟踪 id()
,如果要删除对原始 Foo
的所有引用,则该对象会从内存中删除,然后新的 Foo
已创建,它可以具有相同的 id()
值,因为 id()
值可以是重新使用。因此,您可以拥有一个具有相同 id()
的新 Foo
。这并不重要,因为如果没有更多引用,旧的 Foo
只能从内存中删除。实例保存对其类的引用,因此如果存在类的实例,则该类将继续保留在内存中。
如果您所做的只是比较字典中包含的类,那么您根本不需要诉诸 id()
测试,因为仅进行类相等性测试对于相同的对象,永远返回 true。仅当两个引用都指向同一个类对象时,reference_to_class == other_reference_to_class
才为True
;该测试本质上与 reference_to_class is other_reference_to_class
相同。字典保存了对其所有内容的引用,使这些内容保持活力。通过将类型存储在字典中,您可以确保它们的 id()
值也不会更改。
您链接到的帖子并未询问类的id()
。他们正在讨论实例的id()
值;它讨论了诸如具有不同 id()
值的多个实例之类的问题,并且快速连续创建和丢弃实例并不能保证第一个实例的 id()
被重用第二个。
关于python - 如何在整个程序的生命周期中唯一标识Python中的类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51503591/