有没有办法在创建类(而不是实例)时调用(静态)方法?

时间:2011-10-19 19:00:36

标签: python class methods static

再一次,有点惊讶没有找到这个答案......

我要求的现实原因是: 我有一个类中的常量字典

class MySQLConstants():

  DECIMAL = 0
  TINY = 1
  SHORT = 2
  LONG = 3
  FLOAT = 4
  DOUBLE = 5

  ... etc.

我想要一本字典,所以我可以找到常数,如果给出数字......很容易:

fieldTypeDic = {}
for fieldType in dir( MySQLConstants ):
   value = getattr( MySQLConstants, fieldType )
   fieldTypeDic[ value ] = fieldType

...在类定义语句执行完之后,将MySQLConstants作为@static方法并通过执行MySQLConstants.createDic()来调用它会很容易...但我只是想知道是否有任何方法得到一个方法,不可避免地@static,当一个类(NB我谈论创建这个类的实例!)被创建时运行...

4 个答案:

答案 0 :(得分:3)

这是一个使用元类的解决方案:

class ConstantDictMeta(type):
    def __new__(cls, name, bases, dct):
        fieldTypeDic = dict((v, k) for k, v in dct.items() if k.isupper())
        dct["fieldTypeDic"] = fieldTypeDic
        return type.__new__(cls, name, bases, dct)

class MySQLConstants():
    __metaclass__ = ConstantDictMeta
    DECIMAL = 0
    TINY = 1
    SHORT = 2
    LONG = 3
    FLOAT = 4
    DOUBLE = 5

>>> MySQLConstants.fieldTypeDic
{0: 'DECIMAL', 1: 'TINY', 2: 'SHORT', 3: 'LONG', 4: 'FLOAT', 5: 'DOUBLE'}

答案 1 :(得分:2)

事实上,它比使用元类更简单,并且不需要“类方法”:

class MySQLConstants():
  DECIMAL = 0
  TINY = 1
  SHORT = 2
  LONG = 3
  FLOAT = 4
  DOUBLE = 5

  def create_dict( dicForReversing ):
    fieldTypeDic = {}
    for key, value in dicForReversing.items():
      if isinstance(value, int):
        fieldTypeDic[ value ] = key
    return fieldTypeDic
  fieldTypeDic = create_dict( vars() )

但感谢Ethan Furman特别表明在创建课程期间可以做的事情

请注意,如果您预计密钥有多个值(MySQLdb常量就是这种情况),处理此问题的最佳方法可能如下:

ENUM = 247

CHAR = TINY
INTERVAL = ENUM  

def create_dict( dicForReversing ):
  fieldTypeDic = {}
  for key, value in dicForReversing.items():
    if isinstance(value, int):
      if not value in fieldTypeDic: 
        fieldTypeDic[ value ] = set()
      fieldTypeDic[ value ].add( key )
  return fieldTypeDic
fieldTypeDic = create_dict( vars() )

答案 2 :(得分:1)

您可以创建一个在创建类时添加行为的元类,但您的用例非常简单,只需在需要时直接提取字典:

>>> class MySQLConstants:
  DECIMAL = 0
  TINY = 1
  SHORT = 2
  LONG = 3
  FLOAT = 4
  DOUBLE = 5

>>> vars(MySQLConstants)
{'__module__': '__main__', 'SHORT': 2, 'DOUBLE': 5, 'DECIMAL': 0, 'FLOAT': 4, 'LONG': 3, 'TINY': 1, '__doc__': None}

答案 3 :(得分:1)

直接回答这个问题,是的:

class MySQLConstants():

    DECIMAL = 0
    TINY = 1
    SHORT = 2
    LONG = 3
    FLOAT = 4
    DOUBLE = 5

    def create_dict(cls):
        fieldTypeDic = {}
        if not isinstance(cls, dict):
            cls = cls.__dict__
        for key, value in cls.items():
            if isinstance(value, int):
                fieldTypeDic[ value ] = key
        cls['fieldTypeDic'] = fieldTypeDic
    create_dict(vars())
    create_dict = classmethod(create_dict)

注意create_dict的重写,特别是在类创建过程中调用它之后将其指定为classmethod

如果这是一次性使用方法,我倾向于这样做:

class MySQLConstants():
    lookup = {}
    local = vars()
    for i, name in enumerate('DECIMAL TINY SHORT LONG FLOAT DOUBLE'.split()):
        local[name] = i
        lookup[i] = name
    del local, i, name

这将创建所有名称,并在一个漂亮整洁的包中创建反向查找字典。