You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Python中以值而非类型作为泛型参数实现多纪元Snowflake?

如何在Python中以值作为泛型参数实现Snowflake纪元配置

你想要用Snowflake[DISCORD_EPOCH]这种类似泛型的语法,创建绑定不同纪元的雪花算法类——Python本身的泛型系统主要针对类型参数,但可以通过重载类的__class_getitem__方法实现这个需求,因为Cls[X]的语法本质是调用Cls.__class_getitem__(X)。

下面提供两种实用的实现方式:

方法一:利用类方法__class_getitem__实现类绑定

先定义纪元常量:

DISCORD_EPOCH = 1420070400000  # Discord官方纪元(毫秒级)
MY_EPOCH = 1609459200000      # 自定义纪元(比如2021年元旦)

然后实现Snowflake类,通过__class_getitem__返回绑定特定纪元的子类:

import time

class Snowflake:
    # 缓存已创建的绑定类,避免重复生成
    _bound_cache = {}

    def __init__(self, epoch):
        self.epoch = epoch

    @classmethod
    def __class_getitem__(cls, epoch):
        # 先检查缓存,存在则直接返回
        if epoch not in cls._bound_cache:
            # 创建绑定纪元的子类
            class BoundSnowflake(cls):
                _FIXED_EPOCH = epoch

                def __init__(self):
                    super().__init__(self._FIXED_EPOCH)

            # 给子类设置有意义的名字,方便调试
            BoundSnowflake.__name__ = f"{cls.__name__}[{epoch}]"
            cls._bound_cache[epoch] = BoundSnowflake
        return cls._bound_cache[epoch]

    # 简化的雪花ID生成方法
    def generate(self, worker_id: int, sequence: int) -> int:
        current_ts = int(time.time() * 1000)
        timestamp = current_ts - self.epoch
        return (timestamp << 22) | (worker_id << 12) | sequence

    # 雪花ID解析方法
    def parse(self, snowflake_id: int) -> dict:
        timestamp = (snowflake_id >> 22) + self.epoch
        worker_id = (snowflake_id >> 12) & 0x3FF
        sequence = snowflake_id & 0xFFF
        return {
            "timestamp": timestamp,
            "worker_id": worker_id,
            "sequence": sequence
        }

使用方式完全符合你的需求:

# 创建绑定不同纪元的类
DiscordSnowflake = Snowflake[DISCORD_EPOCH]
MySnowflake = Snowflake[MY_EPOCH]

# 实例化并使用
discord_snow = DiscordSnowflake()
print(discord_snow.generate(worker_id=1, sequence=0))
print(discord_snow.parse(1234567890123456789))

my_snow = MySnowflake()
print(my_snow.generate(worker_id=2, sequence=1))

方法二:用元类实现更简洁的逻辑

如果想把绑定逻辑和业务逻辑分离,可以用元类来处理:

import time

class SnowflakeMeta(type):
    _bound_cache = {}

    def __getitem__(cls, epoch):
        if epoch not in cls._bound_cache:
            class BoundSnowflake(metaclass=SnowflakeMeta):
                _FIXED_EPOCH = epoch

                def generate(self, worker_id: int, sequence: int) -> int:
                    current_ts = int(time.time() * 1000)
                    timestamp = current_ts - self._FIXED_EPOCH
                    return (timestamp << 22) | (worker_id << 12) | sequence

                def parse(self, snowflake_id: int) -> dict:
                    timestamp = (snowflake_id >> 22) + self._FIXED_EPOCH
                    worker_id = (snowflake_id >> 12) & 0x3FF
                    sequence = snowflake_id & 0xFFF
                    return {
                        "timestamp": timestamp,
                        "worker_id": worker_id,
                        "sequence": sequence
                    }

            BoundSnowflake.__name__ = f"{cls.__name__}[{epoch}]"
            cls._bound_cache[epoch] = BoundSnowflake
        return cls._bound_cache[epoch]

class Snowflake(metaclass=SnowflakeMeta):
    pass

使用方式和之前完全一致:

DiscordSnowflake = Snowflake[DISCORD_EPOCH]
MySnowflake = Snowflake[MY_EPOCH]

核心原理

两种方法的本质都是:当你调用Snowflake[epoch]时,Python会触发对应的__class_getitem__(类方法)或元类的__getitem__方法,返回一个预先绑定了指定纪元的子类。缓存机制则避免了重复创建相同纪元的类,提升性能。

内容的提问来源于stack exchange,提问作者anton

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 06:36:59