首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >print('Hello World!')在使用python的代码中不使用'e‘或'p’

print('Hello World!')在使用python的代码中不使用'e‘或'p’
EN

Stack Overflow用户
提问于 2018-07-20 08:16:16
回答 1查看 102关注 0票数 1

这个问题可能看起来很愚蠢。这是一个简单而无用的任务,但我相信这是一个学习东西的好方法(我在做这类技巧时确实学到了很多东西)。

所以,idea在标题中: no 'e‘allowed => No eval() or exec() no 'p’allowed => No print() or import

我尝试的是从以下位置获取打印函数:

代码语言:javascript
复制
dir(__builtins__)[133]

但它是以字符串的形式返回的,我发现没有办法将其作为可调用的函数来获取。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-07-20 08:25:45

由于内建字典的顺序是随机的,所以这不是一件非常有用的事情,除非你像调用print一样喜欢调用staticmethod

但是知道如何从那里进入你想要的下一步可能是值得的。

模块就是对象,就像任何其他对象一样。因此,您可以使用getattr获取它们的属性。好吧,这违反了你的规则。但大多数对象-包括模块-将其属性存储在字典中。所以:

代码语言:javascript
复制
>>> dir(__builtins__)[133]
'staticmethod'
>>> __builtins__.__dict__[_]
<type 'staticmethod'>

有没有什么办法能让我们真的找到print?好吧,也许不能保证,但很接近:

代码语言:javascript
复制
>>> [v for k, v in __builtins__.__dict__.items() if 'rint' in k]
[('print', <function print>)]

哦,我对那个items用的是e,对吧?很好:

代码语言:javascript
复制
>>> [__builtins__.__dict__[k] for k in __builtins__.__dict__ if 'rint' in k]
[<function print>)]
>>> [__builtins__.__dict__[k] for k in __builtins__.__dict__ if 'rint' in k][0]('zzz')
zzz

但同时,您计划如何在没有e的情况下构建字符串'Hello World!'?有很多选择-\x\u转义,或者像rot13这样非常愚蠢的东西。所有这些选项都可以让您轻松地获得字符串'print'。所以,我不明白为什么你一开始就想把print从模块的名字中去掉。

代码语言:javascript
复制
>>> __builtins__.__dict__['\x70rint']
<function print>

正如John Anderson在评论中指出的那样,使用inspect模块比使用__dict__更好。首先,它适用于在其他地方存储属性的对象-甚至是使用自定义__dir____getattr__动态生成属性的对象。

代码语言:javascript
复制
>>> [v for k, v in inspect.getmembers(__builtins__) if k == 'print'][0]
<function print>

问题是,我们如何获得inspect模块?我们可以使用相同的反斜杠/等技巧轻松地获得名称'inspect',但是(除非我们可以假设它已经导入到sys.modules-and中,那么sys也已经导入),我们需要import__import__,或者使用importlib或…它们都有一个p。然后,为了获得getmembers,我们需要查看inspect模块的字典来按名称查找它。

但是,也许这样做一次比每次都做更好:

代码语言:javascript
复制
>>> i = __builtins__.__dict__['__im\x70ort__']
>>> ins = i('ins\x70\x65ct')
>>> gm = ins.__dict__['g\x65tm\x65mb\x65rs']
>>> builty = lambda nam: dict(gm(__builtins__))[nam]
>>> builty('\x70rint')
<function print>
>>> builty('\x65val')
<function eval>

当然,使用lambda在语句中创建命名函数,而不是在表达式中创建匿名函数,这是一种反模式,但这整篇文章都是一堆反模式。我在这里这样做是为了避免对defreturn的需要,它们都有es (正如Elliot Frisch所指出的那样)。(很难注意到您输入的所有e;即使是Gadsby

我确信有人希望我能展示如何通过使用已编译的字节码文字来解决这个问题,对吧?

不幸的是,运行代码对象只有两种方法:要么将其包装在一个函数对象中-这需要获取FunctionType,这需要一个import或对type-or you execeval it的调用-这些方法已经出来了。

另外,在Python3中,您所要做的就是将常量"print""Hello, World"塞进co_namesco_consts中,然后它只是一个LOAD_NAMELOAD_CONSTCALL_FUNCTIONRETURN_VALUE (巧合的是,它恰好以e:<代码>D53开头)。

另一方面,在Python2中,print是一个语句,并且有一个特殊的PRINT_ITEM字节码,所以它可能更有趣:

代码语言:javascript
复制
>>> ty = builty('typ\x65')
>>> gattr = builty('g\x65tattr')
>>> f = lambda: None
>>> c = gattr(f, 'func_cod\x65')
>>> ct = ty(c)
>>> cc = ct(0, 0, 1, 0x43, 'd\x00\x00\x04GS', ('H\x65llo World!',),
...         (), (), '', 'h\x65llo', 0, '')
>>> xval = builty('\x65val')
>>> xval(cc)
Hello World!
'Hello World!'

(末尾额外加引号的输出是因为我太懒而不去挖掘None,所以返回了"Hello World!"。代码为LOAD_CONST 0; DUP_TOP; PRINT_ITEM; RETURN_VALUE。)

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51433423

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档