python – __getattr__在一个模块

如何在类上,在模块上实现__getattr__的等价物?

当调用模块的静态定义属性中不存在的函数时,我希望在该模块中创建一个类的实例,并在模块上的属性查找中调用与该模块的名称相同的失败的方法。

class A(object):
    def salutation(self, accusative):
        print "hello", accusative

# note this function is intentionally on the module, and not the class above
def __getattr__(mod, name):
    return getattr(A(), name)

if __name__ == "__main__":
    # i hope here to have my __getattr__ function above invoked, since
    # salutation does not exist in the current namespace
    salutation("world")

这使:

matt@stanley:~/Desktop$ python getattrmod.py 
Traceback (most recent call last):
  File "getattrmod.py", line 9, in <module>
    salutation("world")
NameError: name 'salutation' is not defined
这里有两个基本问题:

> __xxx__方法只在类上查找
> TypeError:不能设置内置/扩展类型’module’的属性,

(1)意味着任何解决方案都必须跟踪哪个模块正在被检查,否则每个模块将具有实例替换行为;和(2)意味着(1)甚至不可能…至少不直接。

幸运的是,sys.modules不是那么挑剔的,所以一个包装器将工作,但只有模块访问(即导入somemodule; somemodule.salutation(‘世界’);对于同模块访问,你几乎不得不嘲笑方法从替换类,并将它们添加到全局()eiher与类上的自定义方法(我喜欢使用.export())或一个通用的函数(如那些已经列出的答案)。需要注意的一点:如果包装器每次都在创建一个新的实例,而全局解决方案不是,那么你会遇到微妙的不同行为哦,你不能同时使用这两者 – 它是一个或另一个。

更新

Guido van Rossum

There is actually a hack that is occasionally used and recommended: a
module can define a class with the desired functionality, and then at
the end, replace itself in sys.modules with an instance of that class
(or with the class, if you insist, but that’s generally less useful).
E.g.:

# module foo.py

import sys

class Foo:
    def funct1(self, <args>): <code>
    def funct2(self, <args>): <code>

sys.modules[__name__] = Foo()

This works because the import machinery is actively enabling this
hack, and as its final step pulls the actual module out of
sys.modules, after loading it. (This is no accident. The hack was
proposed long ago and we decided we liked enough to support it in the
import machinery.)

所以,完成你想要的方法是在模块中创建一个类,并且最后一个模块用你的类的实例替换sys.modules [__ name__] – 现在你可以使用__getattr __ / __setattr __ / __ getattribute__。

http://stackoverflow.com/questions/2447353/getattr-on-a-module

本站文章除注明转载外,均为本站原创或编译
转载请明显位置注明出处:python – __getattr__在一个模块