【问题标题】:is there a way to get a (static) method to be called when a class (not an instance) is created?有没有办法在创建类(不是实例)时调用(静态)方法?
【发布时间】:2011-12-11 05:12:08
【问题描述】:

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

我问的真实原因是: 我有一个类中的常量字典

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,在创建类时运行(注意,我不是谈论创建此类的实例!)...

【问题讨论】:

  • 除了创建字典外,您还可以直接使用 getattr(MySQLConstants, 'TINY') 进行查找
  • ...除了我想从提供的数字中获取常量的名称...
  • 首先将常量声明为字典,自动生成反向字典,并使用__getattr__ 使它们看起来像类成员。
  • @RussellBorogove 抱歉,我不清楚...当您说“自动生成”时...这可能必须在方法内部发生...所以我们不是回到原来的关于创建类时调用的方法的问题?
  • @mikerodent - 我的建议与 Ethan Furman 的第二个示例类似。

标签: python class methods static


【解决方案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}

【讨论】:

  • 除了...然后每次我想进行查找时都必须反转映射...每次都需要时间
  • @mike rodent:是的,这需要几十纳秒。
  • @JochenRitzel 但我没有几十纳秒的空闲时间......我有点疯狂,喜欢花我宝贵的纳秒时间对 Stack Overflow 帖子做出略微偏离和字面意思的答案
【解决方案2】:

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

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

【讨论】:

    【解决方案3】:

    直接回答问题,是的:

    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 的重写,特别是在类创建期间调用它之后将其分配为类方法

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

    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
    

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

    【讨论】:

    • 嗯...我尝试了你的第一个代码,它提出了 AttributeError: 'stringmap' object has no attribute 'dict'。尽管如此,这似乎表明通过将“cls”作为参数传递,确实有一种我正在寻找的方法。谢谢你给我看这个。将进行实验...
    • 至于你的第二个例子,我假设给常量的编号并不完全是任意的......所以我们可能希望,例如,在特定范围内分组不同的整数类型数字(尽管实际上这些数字的 MySQLdb 分配似乎并没有提供太多合理的分组......(虽然它有点......)
    • 后来:对不起,啤酒太多了...当然参数名称“cls”的选择与它无关...但是您做了一些非常聪明的事情...明天早上我会试着理解它是什么!
    【解决方案4】:

    事实上,它比使用元类要简单得多,而且结果证明不需要“类方法”:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-01
      • 1970-01-01
      • 2013-11-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多