Python 在创建类(而不是实例)时,是否有方法获取要调用的(静态)方法?

Python 在创建类(而不是实例)时,是否有方法获取要调用的(静态)方法?,python,class,methods,static,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 ):

再一次,有点惊讶没有找到这个问题的答案

我提问的现实原因是: 我有一本关于类中常量的字典

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

。。。在执行class definition语句后,将其设置为MySQLConstants的@static方法,并通过调用MySQLConstants.createDic()调用它将非常简单。。。但我只是想知道是否有任何方法可以在创建类(注意,我不是说创建这个类的实例!)时运行一个不可避免的@static方法…

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

>>> 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}

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

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'}

要直接回答问题,请选择“是”:

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

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

事实上,它比使用元类简单得多,而且不需要“classmethod”:

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() )

您也可以直接使用getattr(MySQLConstants,'TINY')进行查找,而不是创建dict。。。除了我想从提供的数字中获取常量的名称之外……首先将常量声明为字典,自动生成反向字典,然后使用
\uuuu getattr\uuuuu
使它们看起来像类成员。@Russellborogve抱歉,我不清楚。。。当你说“自动生成”。。。这可能必须发生在方法内部。。。那么,我们不是回到了创建类时调用的方法的原始问题了吗?@MikCorvent-我的建议与Ethan Furman的第二个示例类似。除了。。。然后,每当我想进行查找时,我都必须反转映射。。。每个人都需要时间time@mike啮齿类动物:是的,这需要几十纳秒。@JochenRitzel,但我没有几十纳秒的空闲时间。。。我有点疯狂,我喜欢用宝贵的纳秒来对堆栈溢出的postsum做出稍微偏离波束和文字的回答。。。我尝试了您的第一段代码,结果发现AttributeError:“stringmap”对象没有属性“dict”。然而,这似乎表明,通过将“cls”作为参数传递,确实有一种我正在寻找的方法。谢谢你给我看这个。将继续进行实验…至于你的第二个例子,我假设常数的编号不是完全任意的。。。例如,我们可能希望在一个特定的数字范围内分组不同的整数类型(尽管实际上,这些数字的MySQLdb赋值似乎没有提供太多合理的分组…(尽管有点…)稍后:对不起,啤酒太多了…当然是参数名称“cls”的选择跟这件事毫无关系……但你做了一件非常聪明的事……明天早上我会设法弄明白是什么!