Skip to main content
 首页 » 编程设计

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

2025年05月04日18Renyi-Fan

我正在尝试将魔术方法 __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 

提前致谢。

请您参考如下方法:

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

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

编辑:让我举一个简化的例子......:

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

当然,如果仅此而已,将此代码架构为“索引类”将是愚蠢的——一个类最好也有带有状态和方法的实例,否则你应该只编写一个模块代替;-)。为什么“正确的”访问应该通过索引整个类而不是特定实例等,还远不清楚。但我会恭维你,假设你有一个很好的设计理由想要以这种方式构建事物,并且只是向你展示如何实现这样的结构;-)。