python - 为每个类类型自动生成唯一 ID
问题描述
我有一个有趣的问题。我想编写一个类,它在继承时为所有子类提供以下行为:
- 将其 self.id 属性设置为 UUID 值——如果这是第一次实例化类,则生成一个新的 UUID——当它被多次实例化时,该 UUID 值被重用于同一个类
现在,有趣的部分是:我希望上面的机制能够工作,而不管用于实例化此类的路径如何。让我们假设以下内容:
from .Package.Class1 import Class1
from TopPackage.Package.Class1 import Class1
from .Package.Class2 import Class2
from TopPackage.Package.Class2 import Class2
在这两种情况下,我都希望 Class1 在两种导入样式中生成相同的 self.id 值。我还希望 Class2 从 Class1 生成不同的 self.id 值,但在它自己的导入样式之间是相同的。
到目前为止,我为类 1 和 2 将继承自的类编写了以下代码:
class ClassWithId(ABC):
_EXISTING_OBJECT_IDS = dict()
def __init__(self):
if self in ClassWithId._EXISTING_OBJECT_IDS.keys():
self.id = ClassWithId._EXISTING_OBJECT_IDS[self]
else:
self.id = uuid.uuid4()
ClassWithId[self] = self.id
但是,我在这里有一些问题:
- ClassWithId 必须从类 ABC 继承,因为它也是类 1 和 2 的接口
- 试图将 self 作为 dict() 中的键导致 TypeError: 'ABCMeta' object does not support item assignment
- 我通常不确定这种方法是否会抵抗不同的导入样式,因为从 Python 的角度来看,类类型.Package.Class1.Class1和TopPackage.Package.Class1.Class1是两个不同的对象
有任何想法吗?
更新:我已将 Elrond 的建议集成到我的代码中,但是不同的导入级别(按包)会为同一类产生不同的 UUID 值:
<class 'StageTwo.Steps.SsTestHandler1.SsTestHandler1'> 3583c89c-5ba8-4b28-a909-31cc27628370
<class 'tests.TestStages.StageTwo.Steps.SsTestHandler1.SsTestHandler1'> f4ead4a0-f5f7-4d95-8252-0de47104cb2f
<class 'StageTwo.Steps.SsTestHandler2.SsTestHandler2'> 8bd9a774-0110-4eee-a30c-a4263ad546cf
<class 'tests.TestStages.StageTwo.Steps.SsTestHandler2.SsTestHandler2'> 773d84c4-82a3-4684-92b5-51509e6db545
也许我忘了提,但是我的 ClassWithId 是由 ClassX 和 ClassY 继承的,而且是这两个类,预计可以抵抗我上面显示的情况(以不同的路径导入,但仍然保留相同的 UUID)。
解决方案
为此,您需要使用 a metaclass
:
import uuid
import abc
class BaseMeta(abc.ABCMeta):
def __new__(mcs, name, bases, attrs):
attrs['_class_uuid'] = uuid.uuid4()
return super().__new__(mcs, name, bases, attrs)
class Base(metaclass=BaseMeta):
def __init__(self):
print(self.__class__.__name__, self._class_uuid)
现在,所有继承自的类都Base
将通过该_class_uuid
属性分配一个 uuid,每个子类一次:
from package1.class1 import Class1
from package2.class2 import Class2
Class1() # 6e0852c8-61c9-4f8b-9817-eeeda4b49d56
Class1() # 6e0852c8-61c9-4f8b-9817-eeeda4b49d56
Class2() # 73012f1a-a984-4f76-96f1-ef5225a38fbe
Class2() # 73012f1a-a984-4f76-96f1-ef5225a38fbe
在任何一种情况下,使用绝对/相对导入都不应该有所作为。
推荐阅读
- apache - firestore/google api get_document 偶尔与 apache 挂起
- angular - 如何从 vs-code 中导入的角度模块读取代码?
- node.js - OffSet + Limit 查询返回错误的结果与adonis / node.js
- r - 自动识别字符串中包含的有效 JSON 对象的函数?
- android - getLifecycle() 的 kotlin 版本是什么?
- google-cloud-platform - 启用身份感知代理可以控制对您的 openAPI 的访问吗?
- spring-data - 记录来自响应式沙发库存储库的 Spring Data 查询
- mysql - 如何查询mysql以选择具有非唯一两列组合的行
- php - 检测用户是否访问了来自同一站点的页面
- javascript - 数组中什么是空的?例如 [空 X 5]