将这个复活节彩蛋分配给一个变量
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.i
、this.c
等是什么?
@PadraicCunningham 在 for 循环中创建的变量。
@PadraicCunningham: this.i
和this.c
基本没用;它们是模块中使用的循环中的最后两个值。另一方面,this.d
和 this.s
是您需要的模块的实际导出值。
@chepner:但是,为什么当inspect.getsourcefile
或inspect.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()
【讨论】:
以上是关于将这个复活节彩蛋分配给一个变量的主要内容,如果未能解决你的问题,请参考以下文章