首页 文章

魔术方法上的@StaticMethod或@ClassMethod装饰

提问于
浏览
1

我试图将魔术方法 __getitem__ 装饰成课堂上的一种类方法 . 这是我尝试的样本 . 我不介意使用classmethod或staticmethod装饰,但我不太清楚如何做到这一点 . 这是我尝试过的:

import ConfigParser

class Settings(object):
   _env = None
   _config = None

   def __init__(self, env='dev'):
    _env = env
    # find the file
    filePath = "C:\\temp\\app.config"

    #load the file
    _config = ConfigParser.ConfigParser()
    _config.read(filePath)

   @classmethod
   def __getitem__(cls, key): 
    return cls._config.get(cls._env, key)

   @classmethod
   def loadEnv(cls, env): 
    cls._env = env

但是,当我尝试调用 Settings['database'] 时,我收到以下错误 .

Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: expected Array[Type], got str

任何人都可以告诉我我做错了什么 . 此外,有人可能会建议是否有更好的方法来做到这一点?我甚至尝试过使用MetaClasses,但收效甚微(因为我不太了解python) .

class Meta(type):
  def __getitem__(*args):
   return type.__getitem__(*args)

 class Settings(object):
  __metaclass__ = Meta

提前致谢 .

2 回答

  • 1

    除了亚历克斯's (entirely correct) answer, it isn'清楚你在这里真正想做什么 . 现在,您正在尝试在实例化类时加载配置 . 如果你要将_config分配给类对象,那就意味着该类的所有实例共享相同的配置(并且创建另一个实例会将所有现有实例更改为指向最新的配置 . )为什么要尝试使用该类要访问此配置,而不是类的特定实例?即使您只有一个配置,如果您愿意,也可以's much more convenient (and understandable!) to use an instance of the class. You can even store this instance in a module-global and call it '设置':

    class _Settings(object):
        def __init__(self, fname):
            self._config = ...
        ...
    
    Settings = _Settings('/path/to/config.ini')
    
  • 4

    Python总是在类上查找 __getitem__ 和其他魔术方法,而不是在实例上查找 . 因此,例如,在元类中定义 __getitem__ 意味着您可以索引 the class (但是您无法通过委托 type 中不存在的 __getitem__ 来定义它 - 就像您永远不能通过委托给其他非定义任何东西一样来定义它当然存在的方法;-) .

    因此,如果您需要索引一个类,如 Settings ,您的自定义元类必须确定 __getitem__ ,但它必须使用显式代码定义它,以执行您想要的操作 - 您想要的 return cls._config.get .

    Edit :让我举一个简单的例子......:

    >>> class MyMeta(type):
    ...   def __getitem__(cls, k):
    ...     return cls._config.get(k)
    ... 
    >>> class Settings:
    ...   __metaclass__ = MyMeta
    ...   _config = dict(foo=23, bar=45)
    ... 
    >>> print Settings['foo']
    23
    

    当然,如果就是这样的话,那么将这段代码构建为"indexing a class"就是愚蠢的 - 一个类最好也有状态和方法的实例,否则你应该只编写一个模块代码;-) . 为什么"proper"访问应该通过索引整个类而不是特定的实例等,这一点远非明确 . 但是我会恭维你假设你有一个很好的设计理由想要用这种方式构建东西,并告诉你如何实现这样的结构;-) .

相关问题