如何在不明确接受的情况下让 self 进入 Python 方法
我正在开发一个文档测试框架——基本上是 PDF 的单元测试。测试是框架定义的类实例的(修饰的)方法,这些方法在运行时定位并实例化,并调用这些方法来执行测试。
我的目标是减少编写测试的人需要关心的奇怪的 Python 语法的数量,因为这些人可能是也可能不是 Python 程序员,甚至根本就是程序员。所以我希望他们能够为方法编写“def foo():”而不是“def foo(self):”,但仍然能够使用“self”来访问成员。
在普通程序中,我会认为这是一个可怕的想法,但在像这样的特定于领域的语言类型的程序中,似乎值得一试。
我已经通过使用装饰器成功地从方法签名中消除了 self(实际上,因为我已经在测试用例中使用了装饰器,所以我只是将其卷入其中),但是“self”并没有引用方法签名中的任何内容。测试用例方法。
我考虑过使用全局的 self,甚至想出了一个或多或少有效的实现,但我宁愿污染尽可能小的命名空间,这就是为什么我更愿意将变量直接注入到测试用例方法的本地命名空间。有什么想法吗?
I'm developing a documentation testing framework -- basically unit tests for PDFs. Tests are (decorated) methods of instances of classes defined by the framework, and these are located and instantiated at runtime and the methods are invoked to execute the tests.
My goal is to cut down on the amount of quirky Python syntax that the people who will write tests need to be concerned about, as these people may or may not be Python programmers, or even very much programmers at all. So I would like them to be able to write "def foo():" instead of "def foo(self):" for methods, but still be able to use "self" to access members.
In an ordinary program I would consider this a horrible idea, but in a domain-specific-languagey kind of program like this one, it seems worth a try.
I have successfully eliminated the self from the method signature by using a decorator (actually, since I am using a decorator already for the test cases, I would just roll it into that), but "self" does not then refer to anything in the test case method.
I have considered using a global for self, and even come up with an implementation that more or less works, but I'd rather pollute the smallest namespace possible, which is why I would prefer to inject the variable directly into the test case method's local namespace. Any thoughts?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
我对这个问题的接受答案非常愚蠢,但我才刚刚开始。这是一个更好的方法。虽然这只是经过了很少的测试,但它有助于演示执行不正确操作的正确方法。它肯定可以在 2.6.5 上运行。我没有测试任何其他版本,但没有硬编码到其中的操作码,因此它应该与大多数其他 2.x 代码一样可移植。
add_self
可以用作装饰器,但这会达不到目的(为什么不直接输入“self”?)很容易从我的其他答案中调整元类来应用此函数。My accepted answer to this question was pretty dumb but I was just starting out. Here's a much better way. This is only scantily tested but it's good for a demonstration of the proper way to do this thing which is improper to do. It works on 2.6.5 for sure. I haven't tested any other versions but no opcodes are hardcoded into it so it should be about as portable as most other 2.x code.
add_self
can be applied as a decorator but that would defeat the purpose (why not just type 'self'?) It would be easy to adapt the metaclass from my other answer to apply this function instead.这是一个单行方法装饰器,它似乎可以在不修改任何 可调用类型的特殊属性*标记为只读:
请注意,除非您采取预防措施来防止它,否则 副作用 可能是它添加了一些条目 - 例如对
的引用>__builtin__
模块下的键__builtins__
-- 自动传递给传递给它的dict
。@kendall:根据您关于如何将其与容器类中的方法一起使用的评论(但暂时忽略其他变量的注入)——以下内容是否类似于您正在做的事情?我很难理解框架和用户编写的内容之间是如何划分的。对我来说,这听起来是一个有趣的设计模式。
Here's a one line method decorator that seems to do the job without modifying any Special attributes of Callable types* marked Read-only:
Note that unless you take precautions to prevent it, a side-effect of the
eval()
function may be it adding a few entries -- such as a reference to the__builtin__
module under the key__builtins__
-- automatically to thedict
passed to it.@kendall: Per your comment about how you're using this with methods being in container classes (but ignoring the injection of additional variables for the moment) -- is the following something like what you're doing? It's difficult for me to understand how things are split up between the framework and what the users write. It sounds like an interesting design pattern to me.
aaronasterling 的解决方案几乎没有升级(我没有足够的声誉来评论它):
但是如果 f 函数将针对不同的实例递归调用,那么这两个解决方案都将工作不可预测,因此您必须像这样克隆它:
little upgrade for aaronasterling's solution( i haven't enough reputation to comment it ):
but both this solutions will work unpredictable if f function will be called recursively for different instance, so you have to clone it like this:
诀窍是将“self”添加到
f.func_globals
。这适用于 python2.6。我真的应该抽出时间安装其他版本来测试这样的东西。抱歉,代码墙很长,但我介绍了两种情况:使用元类执行和使用装饰器执行。对于您的用例,我认为元类更好,因为本练习的全部目的是保护用户免受语法影响。The trick is to add 'self' to
f.func_globals
. This works in python2.6. I really should get around to installing other versions to test stuff like this on. Sorry for the wall of code but I cover two cases: doing it with a metaclass and doing it with a decorator. For your usecase, I think the metaclass is better since the whole point of this exercise is to shield users from syntax.这可能是 装饰器 的一个用例 - 你给他们一个小的一组用来构建函数的乐高积木,复杂的框架内容通过 @testcase 或类似的东西通过管道传输。
编辑:您没有发布任何代码,因此这将是粗略的,但他们不需要编写方法。他们可以编写没有“self”的普通函数,并且您可以使用装饰器,就像我链接的文章中的示例一样:
This might be a use case for decorators - you give them a small set of lego bricks to build functions with, and the complicated framework stuff is piped in via
@testcase
or somesuch.Edit: You didn't post any code, so this is going to be sketchy, but they don't need to write methods. They can write ordinary functions without "self", and you could use decorators like in this example from the article I linked: