【问题标题】: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'

提前致谢。

【问题讨论】:

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

标签: python python-2.7


【解决方案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 pbzcyvpngrq.
Syng vf orggre guna arfgrq.
Fcnefr vf orggre guna qrafr.
Ernqnovyvgl pbhagf.
Fcrpvny pnfrf nera'g fcrpvny rabhtu gb oernx gur ehyrf.
Nygubhtu cenpgvpnyvgl 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()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-02-11
    • 1970-01-01
    • 1970-01-01
    • 2012-05-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多