将这个复活节彩蛋分配给一个变量

Posted

技术标签:

【中文标题】将这个复活节彩蛋分配给一个变量【英文标题】:Assigning the easter egg this to a variable 【发布时间】:2014-09-15 20:27:20 【问题描述】:

是否可以将 Python 复活节彩蛋 this 分配给变量?

理想情况下,我想做的是在文本上尝试各种字符串方法,比如“the”这个词出现了多少次。

我尝试了以下方法:

import this

long_text = this

print long_text.count('the')

这会打印出 Zen 消息,但我在使用 count 方法时看到错误:

...    
Namespaces are one honking great idea -- let's do more of those!
Traceback (most recent call last):
  File "count.py", line 5, in <module>
    print long_text.count('the')
AttributeError: 'module' object has no attribute 'count'

提前致谢。

【问题讨论】:

也许这个问题(以及这个模块的来源)可以提供帮助:***.com/questions/5855758/… @everyone:天哪!感谢您的快速响应,正如您所说,我对 Python 还很陌生,我需要一段时间才能正确消化所有这些信息。谢谢 - 真的很感激。 【参考方案1】:

this 模块中的代码是故意混淆的代码,开个玩笑,* 所以字符串原样不会直接出现在任何地方。

但是,如果您查看源代码(例如 print inspect.getsource(this),或查看 in the source repo),您会看到最后一行是:

print "".join([d.get(c, c) for c in s])

……这意味着答案是:

text = "".join([this.d.get(c, c) for c in this.s])

当然,这依赖于未记录的、特定于实现的细节,但 this 模块本身是未记录的、特定于实现的细节,如查看 the library reference 所见。


但是,如果您想要与任何具有 this 模块的 Python 实现一起使用的东西,即使它的实现方式不同(据我所知,这不会是一个单一的 Python 实现......) ,你总是可以这样做:

old_stdout = sys.stdout
sys.stdout = StringIO.StringIO()
try:
    import this
    text = sys.stdout.getvalue()
finally:
    sys.stdout = old_stdout

但是,请记住,import 仅在第一次导入时运行代码,因此如果您在同一会话中执行此操作两次,您将在第二次得到''


另一个有趣的选择是下载 PEP 20 并使用您最喜欢的 html 解析器对其进行解析以提取文本。但我会将其作为exercise 留给读者。


* 如果你想知道,笑话是混淆源代码,从头开始重新实现 rot13,即使它内置在标准库中,使用嵌套循环,循环 65 到 97 而不是字符,循环遍历range(26),原因是你必须多次阅读代码才能理解......所有这些都尽可能地违反了禅宗。请参阅Barry Warsaw's post,了解更多关于他们在实施时的心态的背景信息。

【讨论】:

您还可以检查this.__file__ 的值,它将引导您进入系统中可以找到this.py 的目录。 this.ithis.c 等是什么? @PadraicCunningham 在 for 循环中创建的变量。 @PadraicCunningham: this.ithis.c 基本没用;它们是模块中使用的循环中的最后两个值。另一方面,this.dthis.s 是您需要的模块的实际导出值。 @chepner:但是,为什么当inspect.getsourcefileinspect.source 为您执行此操作时,更健壮(例如,当您的stdlib 被塞进压缩文件时)并且更简单?【参考方案2】:

只是因为还没有人提到它:

from codecs import decode
from this import s

zen = decode(s, "rot13")

【讨论】:

你不需要import 任何东西;就做s.decode('rot13') @abarnert 这个版本可以在 Python 2 和 3 上运行,但 :-) 你确定吗?我很确定rot13 是 3.0 中删除的编解码器之一,添加回 3.2 或 3.3 但没有别名(所以你不能称它为rot13,你必须知道真实姓名),并且仅在 3.4 中完全恢复? 啊……可能;我只在 2.7 和 3.4 中测试过。但是,对于这种微不足道的事情没有必要过分,为了不必编辑,我将考虑您为 3.0-3.3 描述的情况是一个错误 ;-) 只是在 3.3 计划的后期才开始,让编写在 2.7 和 3.latest 中运行的单代码库应用程序变得更容易甚至是一个目标……但令人惊讶的是有多少小事情发生了从u前缀到编解码器别名再到bytes.__mod__,添加回来是无害且有用的。如果这在几年前是显而易见的……【参考方案3】:

您当前正在将long_text 分配给模块this,以获取您可以执行的文本:

>>> import this
>>> text = "".join([this.d.get(c, c) for c in this.s])
>>> print text.count('the')
5

实际源码:

>>> this.__file__
'/usr/lib/python2.7/this.py'
>>> !cat /usr/lib/python2.7/this.py
s = """Gur Mra bs Clguba, ol Gvz Crgref

Ornhgvshy vf orggre guna htyl.
Rkcyvpvg vf orggre guna vzcyvpvg.
Fvzcyr vf orggre guna pbzcyrk.
Pbzcyrk vf orggre guna pbzcy***grq.
Syng vf orggre guna arfgrq.
Fcnefr vf orggre guna qrafr.
Ernqnovyvgl pbhagf.
Fcrpvny pnfrf nera'g fcrpvny rabhtu gb oernx gur ehyrf.
Nygubhtu cenpg***yvgl orngf chevgl.
Reebef fubhyq arire cnff fvyragyl.
Hayrff rkcyvpvgyl fvyraprq.
Va gur snpr bs nzovthvgl, ershfr gur grzcgngvba gb thrff.
Gurer fubhyq or bar-- naq cersrenoyl bayl bar --boivbhf jnl gb qb vg.
Nygubhtu gung jnl znl abg or boivbhf ng svefg hayrff lbh'er Qhgpu.
Abj vf orggre guna arire.
Nygubhtu arire vf bsgra orggre guna *evtug* abj.
Vs gur vzcyrzragngvba vf uneq gb rkcynva, vg'f n onq vqrn.
Vs gur vzcyrzragngvba vf rnfl gb rkcynva, vg znl or n tbbq vqrn.
Anzrfcnprf ner bar ubaxvat terng vqrn -- yrg'f qb zber bs gubfr!"""

d = 
for c in (65, 97):
    for i in range(26):
        d[chr(i+c)] = chr((i+13) % 26 + c)

print "".join([d.get(c, c) for c in s])

【讨论】:

您不需要创建d 对象,因为它已经作为this.d 提供。 @abarnert 是的!我怎么错过了。 :// 另外,2.x 系列有一个.encode('rot13') - 比使用手动翻译循环更好 @JonClements:我喜欢你使用encode 而不是decode 的事实;符合模块的精神。 :) s.encode('rot13') 非常适合 OP,但当然,Real Programmers™ 可以在没有解码器的情况下读取 Rot13。 :)【参考方案4】:

我本来不打算写的,但是……什么鬼。这可能是获得 Zen 的唯一官方记录方法——它适用于任何 Python 实现,即使没有彩蛋:

#!/usr/bin/env python

import HTMLParser
import urllib2

class ZenParser(HTMLParser.HTMLParser):
    def __init__(self, *args, **kwargs):
        HTMLParser.HTMLParser.__init__(self, *args, **kwargs)
        self.state = 'START'
    def handle_data(self, data):
        if self.state == 'CHECKING HEADER':
            if data.strip() == 'The Zen of Python':
                self.state = 'AWAITING ZEN'
            else:
                self.state = 'START'
        elif self.state == 'GATHERING ZEN':
            self.zen = data
            self.state = 'ENLIGHTENED BODDHISATVA'
    def handle_starttag(self, tag, attrs):
        if self.state == 'START' and tag == 'h3':
            self.state = 'CHECKING HEADER'
        elif self.state == 'AWAITING ZEN' and tag == 'pre':
            self.state = 'GATHERING ZEN'

def zen():
    r = urllib2.urlopen('http://legacy.python.org/dev/peps/pep-0020/')
    parser = ZenParser()
    parser.feed(r.read())
    return '\n'.join(line.lstrip() for line in parser.zen.splitlines())

print zen()

或者,如果您愿意使用第三方库,BeautifulSoup(和往常一样)会更容易:

import urllib2
import bs4

def zen():
    r = urllib2.urlopen('http://legacy.python.org/dev/peps/pep-0020/')
    soup = bs4.BeautifulSoup(r.read())
    zen = soup.find('h3', text='The Zen of Python').find_next_sibling('pre').string
    return '\n'.join(line.lstrip() for line in parser.zen.splitlines())

print zen()

【讨论】:

以上是关于将这个复活节彩蛋分配给一个变量的主要内容,如果未能解决你的问题,请参考以下文章

帮助有趣的项目:复活节彩蛋 jQuery DJ [关闭]

在线复活节彩蛋搜寻中揭示了Microsoft Edge浏览器的新图标

javascript 复活节彩蛋企鹅

javascript CK的未来复活节彩蛋

对象复活的用法

上古卷轴如何给npc下命令