蟒蛇:在基类中定义注册表 [英] python: defining registry in base class

查看:258
本文介绍了蟒蛇:在基类中定义注册表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用一个基类,定义了多种方法实现枚举。实际的枚举是子类,没有额外的方法或属性。 (每个子类中填充使用基类中定义的构造自己的价值观)。

我使用注册表(它存储类的所有实例的类属性)。理想情况下,我想,以避免在每个子类定义它。不幸的是,如果我在基类中定义它,所有的子类最终将共享相同的注册表。

什么是好办法吗?

下面是情况下,实施有利于(它是基于在<一@jchl评论href=\"http://stackoverflow.com/questions/3588996/python-enumeration-class-for-orm-purposes\">http://stackoverflow.com/questions/3588996/python-enumeration-class-for-orm-purposes).

 类IterRegistry(类型):
    高清__iter __(CLS):
        返回ITER(cls._registry.values​​())类EnumType(元类= IterRegistry):
    _registry = {}
    _frozen =假
    高清__init __(个体经营,令牌):
        如果hasattr(个体经营,'令牌'):
            返回
        self.token =令牌
        self.id = LEN(类型(个体经营)._注册表)
        类型(个体经营)._注册表[令牌] =自    高清__new __(CLS,令牌):
        如果cls._registry令牌:
            返回cls._registry [令牌]
        其他:
            如果cls._frozen:
                提高类型错误(没有更多的情况下,允许)
            其他:
                返回对象.__新__(CLS)    @classmethod
    高清冻结(CLS):
        cls._frozen = TRUE    高清__repr __(个体经营):
        回报self.token    @classmethod
    DEF实例(CLS,令牌):
        返回cls._registry [令牌]类Enum1(EnumType):通
Enum1('A')
Enum1(B)
因为我在Enum1:
  打印(一)#不会正常工作,因为_registry共享
类Enum2(EnumType):通


解决方案

当你已经有一个元类,你还不如用它来把添加一个单独的 _registry 属性自动每个子类。

 类IterRegistry(类型):
    高清__new __(CLS,名称,基地,ATTR):
        ATTR ['_注册表'] = {}#现在每个班级都有自己的_registry
        返回类型.__新__(CLS,名称,基地,ATTR)

I'm implementing enumeration using a base class that defines a variety of methods. The actual enumerations are subclasses of that, with no additional methods or attributes. (Each subclass is populated with its own values using the constructor defined in the base class).

I use a registry (a class attribute that stores all the instances of that class). Ideally, I'd like to avoid defining it in each subclass. Unfortunately, if I define it in the base class, all the subclasses will end up sharing the same registry.

What's a good approach here?

Below is the implementation in case it helps (it's based on @jchl comment in http://stackoverflow.com/questions/3588996/python-enumeration-class-for-orm-purposes).

class IterRegistry(type):
    def __iter__(cls):
        return iter(cls._registry.values())

class EnumType(metaclass = IterRegistry):
    _registry = {}
    _frozen = False
    def __init__(self, token):
        if hasattr(self, 'token'):
            return
        self.token = token
        self.id = len(type(self)._registry)
        type(self)._registry[token] = self

    def __new__(cls, token):
        if token in cls._registry:
            return cls._registry[token]
        else:
            if cls._frozen:
                raise TypeError('No more instances allowed')
            else:
                return object.__new__(cls)

    @classmethod
    def freeze(cls):
        cls._frozen = True

    def __repr__(self):
        return self.token

    @classmethod
    def instance(cls, token):
        return cls._registry[token]

class Enum1(EnumType): pass
Enum1('a')
Enum1('b')
for i in Enum1:
  print(i)

# not going to work properly because _registry is shared
class Enum2(EnumType): pass

解决方案

As you already have a metaclass you might as well use it to put a add a separate _registry attribute to each subclass automatically.

class IterRegistry(type):
    def __new__(cls, name, bases, attr):
        attr['_registry'] = {} # now every class has it's own _registry
        return type.__new__(cls, name, bases, attr)

这篇关于蟒蛇:在基类中定义注册表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆