python修改整个程序的__metaclass__
编辑:请注意,在生产代码中这是一个非常糟糕的主意。这对我来说只是一件有趣的事情。在家别做这些事!
是否可以在Python中修改整个程序(解释器)的 __metaclass__ 变量?
这个简单的例子是有效的:
class ChattyType(type):
def __init__(cls, name, bases, dct):
print "Class init", name
super(ChattyType, cls).__init__(name, bases, dct)
__metaclass__= ChattyType
class Data:
pass
data = Data() # prints "Class init Data"
print data
但我希望能够改变 __metaclass__ 甚至在子模块中也能工作。例如 (file m1.py):
class A:
pass
a=A()
print a
file main.py:
class ChattyType(type):
def __init__(cls, name, bases, dct):
print "Class init", name
super(ChattyType, cls).__init__(name, bases, dct)
__metaclass__= ChattyType
import m1 # and now print "Class init A"
class Data:
pass
data = Data() # print "Class init Data"
print data
我知道全局 __metaclass__ 不再在 Python 3.X 中工作,但这不是我关心的问题(如果是概念证明,我的代码)。那么在Python-2.x中有什么办法可以实现这一点呢?
EDIT: Note that this is a REALLY BAD idea to do in production code. This was just an interesting thing for me. Don't do this at home!
Is it possible to modify __metaclass__ variable for whole program (interpreter) in Python?
This simple example is working:
class ChattyType(type):
def __init__(cls, name, bases, dct):
print "Class init", name
super(ChattyType, cls).__init__(name, bases, dct)
__metaclass__= ChattyType
class Data:
pass
data = Data() # prints "Class init Data"
print data
but I would love to be able change of __metaclass__ to work even in submodules. So for example (file m1.py):
class A:
pass
a=A()
print a
file main.py:
class ChattyType(type):
def __init__(cls, name, bases, dct):
print "Class init", name
super(ChattyType, cls).__init__(name, bases, dct)
__metaclass__= ChattyType
import m1 # and now print "Class init A"
class Data:
pass
data = Data() # print "Class init Data"
print data
I understand that global __metaclass__ is no longer working in Python 3.X, but that is not my concern (my code if proof of concept). So is there any way to accomplish this in Python-2.x?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
Python 2 的“global
__metaclass__
”功能被设计为只能在每个模块上工作(想想它会造成什么严重破坏,否则,通过在所有库和第三方模块上强制使用您自己的元类,你从那一点开始导入——颤抖!)。如果“秘密”改变从某个点开始导入的所有模块的行为对您来说非常重要,无论出于什么隐秘的原因,您都可以使用导入钩子玩非常非常肮脏的把戏(最坏的情况是首先将源文件复制到临时位置,同时更改它们......)但是付出的努力将与行为的严重程度成正比,这似乎是合适的;-)The "global
__metaclass__
" feature of Python 2 is designed to work per-module, only (just think what havoc it would wreak, otherwise, by forcing your own metaclass on all library and third-party modules that you imported from that point onwards -- shudder!). If it's very important to you to "secretly" alter the behavior of all modules you're importing from a certain point onwards, for whatever cloak-and-dagger reason, you could play very very dirty tricks with an import hook (at worst by first copying the sources to a temporary location while altering them...) but the effort would be proportionate to the enormity of the deed, which seems appropriate;-)好的;在我看来,这是一种恶心、毛茸茸的黑魔法。也许永远不应该使用它,但尤其不应该在生产代码中使用它。然而,仅仅出于好奇心,这还是很有趣的。
您可以使用 PEP 302 中描述的机制编写自定义导入程序,并且Doug Hellmann 的 PyMOTW:模块和导入 中进一步讨论。这为您提供了完成您考虑的任务的工具。
我实现了这样一个导入器,只是因为我很好奇。本质上,对于您通过类变量
__chatty_for__
指定的模块,它将在导入模块的__dict__
中插入自定义类型作为__metaclass__
变量>,在代码被评估之前。如果相关代码定义了自己的__metaclass__
,它将替换导入器预先插入的代码。在仔细考虑它会对模块做什么之前,不建议将此导入器应用于任何模块。我没有写过很多导入程序,所以在写这个导入程序时我可能做了一件或多件愚蠢的事情。如果有人注意到我在实施中错过的缺陷/极端情况,请发表评论。
源文件 1:
源文件 2:
源文件 3:
以及主要事件:
Okay; IMO this is gross, hairy, dark magic. You shouldn't use it, perhaps ever, but especially not in production code. It is kind of interesting just for curiosity's sake, however.
You can write a custom importer using the mechanisms described in PEP 302, and further discussed in Doug Hellmann's PyMOTW: Modules and Imports. That gives you the tools to accomplish the task you contemplated.
I implemented such an importer, just because I was curious. Essentially, for the modules you specify by means of the class variable
__chatty_for__
, it will insert a custom type as a__metaclass__
variable in the imported module's__dict__
, before the code is evaluated. If the code in question defines its own__metaclass__
, that will replace the one pre-inserted by the importer. It would be inadvisable to apply this importer to any modules before carefully considering what it would do to them.I haven't written many importers, so I may have done one or more silly things while writing this one. If anyone notices flaws / corner cases I missed in the implementation, please leave a comment.
source file 1:
source file 2:
source file 3:
and the main event:
没有。 (这是一个功能!)
Nope. (This is a feature!)