Python神秘剧场 - 第2集:AsíFue [英] Python Mystery Theatre -- Episode 2: Así Fue

查看:49
本文介绍了Python神秘剧场 - 第2集:AsíFue的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下是另外四款迷你神秘游戏

和启发。


在本集中,节目输出不会显示。

你的目标是预测输出,如果发生任何神秘事件,那么就解释一下发生了什么

(再次,用明显的术语来说)。 />

有一个额外的功劳,可以提供设计见解

为什么事情就像它们一样。


尝试解决这些问题,而不是查看其他帖子。

如果你在路上学到了新的东西,请告诉我。


挑战那些想到的人最后一集

太容易了,我已经包含了一个没有文档的皱纹

只有那些已经阅读过代码的人知道。

享受,

Raymond Hettinger


ACT I -------------------------- ---------------------

print''*%* r *''%(10,''guido'')

print''*%。* f *''%((42,)* 2 )


ACT II ----------------------------------- ------------

s =''0100''

print int(s)

for b in (16,10,8,2,0,-909,-1000,无):

打印b,int(s,b)


ACT III ------------------------------------------------- ---

def一次(x):返回x

def两次(x):返回2 * x

def三次(x) :返回3 * x

funcs = [一次,两次,三次]


flim = [lambda x:funcs [0](x),lambda x :funcs [1](x),lambda x:funcs [2](x)]

flam = [lambda x:f(x)for f in funcs]

print flim [0](1),flim [1](1),flim [2](1)

print flam [0](1),flam [1] (1),flam [2](1)


ACT IV ------------------------- ---------------------------

import os

os.environ [' 'one''] =''现在有''

os.putenv(''''',''three'')

print os.getenv( ''one''),os.getenv(''''')

Here are four more mini-mysteries for your amusement
and edification.

In this episode, the program output is not shown.
Your goal is to predict the output and, if anything
mysterious occurs, then explain what happened
(again, in blindingly obvious terms).

There''s extra credit for giving a design insight as to
why things are as they are.

Try to solve these without looking at the other posts.
Let me know if you learned something new along the way.

To challenge the those who thought the last episode
was too easy, I''ve included one undocumented wrinkle
known only to those who have read the code.
Enjoy,
Raymond Hettinger

ACT I -----------------------------------------------
print ''*%*r*'' % (10, ''guido'')
print ''*%.*f*'' % ((42,) * 2)

ACT II -----------------------------------------------
s = ''0100''
print int(s)
for b in (16, 10, 8, 2, 0, -909, -1000, None):
print b, int(s, b)

ACT III ----------------------------------------------------
def once(x): return x
def twice(x): return 2*x
def thrice(x): return 3*x
funcs = [once, twice, thrice]

flim = [lambda x:funcs[0](x), lambda x:funcs[1](x), lambda x:funcs[2](x)]
flam = [lambda x:f(x) for f in funcs]

print flim[0](1), flim[1](1), flim[2](1)
print flam[0](1), flam[1](1), flam[2](1)

ACT IV ----------------------------------------------------
import os
os.environ[''one''] = ''Now there are''
os.putenv(''two'', ''three'')
print os.getenv(''one''), os.getenv(''two'')

推荐答案

2003年7月14日星期一上午05:42:13 +0000,Raymond Hettinger写道:

我没有看看代码,除了int()[这是一个很大的例外]
On Mon, Jul 14, 2003 at 05:42:13AM +0000, Raymond Hettinger wrote:
I didn''t look at the code, excepting int() [which is a big exception]
ACT I --------------------- --------------------------
print''*%* r *''%(10,''guido'')
打印''*%。* f *''%((42,)* 2)
我会假设''%r''是__repr__,因为''%s''是__str__

%之后的星号表示数字的占位符,从arg列表中获取

所以我的猜测是:

* ''guido''*#填充到十个地方,使用空格

* 42.000000000000000000000000 *#42小数点

ACT II ----------- ------------------------------------
s =''0100'' print int(s)
for b in(16,10,8,2,0,-909,-1000,None):
print b,int(s,b)
int(0100)== 64#octal

我在inb中查找了int_new() ject.c因为我从未使用过可选的

base参数。 ''b''参数仅对1> = base< = 36

合法,但魔术常数[1]为-909,被解释为基数10

ACT III --------------------------------------------- -------
def一次(x):返回x
def两次(x):返回2 * x
def三次(x):返回3 * x
funcs = [一次,两次,三次]

flim = [lambda x:funcs [0](x),lambda x:funcs [1](x),lambda x:funcs [2] (x)]
flam = [lambda x:f(x)for f in funcs]

print flim [0](1),flim [1](1),flim [ 2](1)
打印flam [0](1),flam [1](1),flam [2](1)
funcs,flim和flam看起来都和我一模一样。所有这些应打印

1 2 3

ACT IV ------------------------- ---------------------------
导入os
os.environ [''one''] =''现在有''
os.putenv(''''',''三'')
打印os.getenv(''one''),os.getenv(''''''' )
ACT I -----------------------------------------------
print ''*%*r*'' % (10, ''guido'')
print ''*%.*f*'' % ((42,) * 2) I''ll assume ''%r'' is __repr__ since ''%s'' is __str__
The star after a % means "placeholder for a number, get it from the arg list"
so my guess is:
* ''guido''* # padded to ten places, using spaces
*42.000000000000000000000000* # 42 decimal points
ACT II -----------------------------------------------
s = ''0100''
print int(s)
for b in (16, 10, 8, 2, 0, -909, -1000, None):
print b, int(s, b) int(0100) == 64 # octal
I looked up int_new() in intobject.c because I had never used the optional
base parameter. the ''b'' parameter is only legal for 1 >= base <= 36
but the magic constant[1] is -909, which is interpreted as base 10
ACT III ----------------------------------------------------
def once(x): return x
def twice(x): return 2*x
def thrice(x): return 3*x
funcs = [once, twice, thrice]

flim = [lambda x:funcs[0](x), lambda x:funcs[1](x), lambda x:funcs[2](x)]
flam = [lambda x:f(x) for f in funcs]

print flim[0](1), flim[1](1), flim[2](1)
print flam[0](1), flam[1](1), flam[2](1) funcs, flim, and flam all seem identical to me. all these should print
1 2 3
ACT IV ----------------------------------------------------
import os
os.environ[''one''] = ''Now there are''
os.putenv(''two'', ''three'')
print os.getenv(''one''), os.getenv(''two'')



不知道,所以我会支付

现在有三个


-jack


[1]当省略可选参数时(在本例中为''base''),记录它们的C变量

保持不变。在这种情况下,变量在-909处开始

,所以如果它被传入-909或省略代码不知道。

但为什么不能基地刚刚默认为10?如果结果

是-909(省略或传入-909),我们只需要进行10次转换。


intobject.c


PyObject * x = NULL;

int base = -909;

static char * kwlist [] = {" x" ,base,0};


if(type!=& PyInt_Type)

return int_subtype_new(type,args,kwds); / * Wimp out * /

if(!PyArg_ParseTupleAndKeywords(args,kwds," | Oi:int",kwlist,& x,& base))

返回NULL;

if(base == -909)

返回PyNumber_Int(x); / *无论如何,这将进行基数为10的转换! * /

if(PyString_Check(x))

返回PyInt_FromString(PyString_AS_STRING(x),NULL,base);


唯一的例外是,如果使用

可选的基本参数,则第一个参数必须是一个字符串。我确定这是有原因的吗??

int(''99'',10)#legal

int(99,10)#傻,但这应该是非法的吗?


no idea, so I''ll punt
Now there are three

-jack

[1] When optional arguments are omitted (in this case ''base'') the C variable
where they are recorded is left unchanged. In this case that variable starts
at -909 so if it is passed in as -909 or omitted the code doesn''t know.
But why can''t base just default to 10 in the first place? If the result
is -909 (omitted or passed in as -909) we just do a base-10 conversion anyway.

intobject.c

PyObject *x = NULL;
int base = -909;
static char *kwlist[] = {"x", "base", 0};

if (type != &PyInt_Type)
return int_subtype_new(type, args, kwds); /* Wimp out */
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|Oi:int", kwlist, &x, &base))
return NULL;
if (base == -909)
return PyNumber_Int(x); /* This will do a base-10 conversion anyway !!! */
if (PyString_Check(x))
return PyInt_FromString(PyString_AS_STRING(x), NULL, base);

The only exception is that the first argument has to be a string if the
optional base argument is used. I''m sure there was a reason for this ... ?
int(''99'', 10) # legal
int(99, 10) # silly, but should this really be illegal?


Raymond Hettinger写道:
Raymond Hettinger wrote:
ACT III -------- --------------------------------------------
def一次(x):返回x
def两次(x):返回2 * x
def三次(x):返回3 * x
funcs = [一次,两次,三次]

flim = [lambda x:funcs [0](x),lambda x:funcs [1](x),lambda x:funcs [2](x)]
flam = [lambda x :f(x)for f in funcs]

print flim [0](1),flim [1](1),flim [2](1)
print flam [0 ](1),flam [1](1),flam [2](1)
ACT III ----------------------------------------------------
def once(x): return x
def twice(x): return 2*x
def thrice(x): return 3*x
funcs = [once, twice, thrice]

flim = [lambda x:funcs[0](x), lambda x:funcs[1](x), lambda x:funcs[2](x)]
flam = [lambda x:f(x) for f in funcs]

print flim[0](1), flim[1](1), flim[2](1)
print flam[0](1), flam[1](1), flam[2](1)




好​​的,我相信知道为什么最后一行

打印''3''三次,因为只有一个参考

到''f''存储在lambda表达式中

这个值有'三次''当''打印''

被执行。

但是如何c我实现了一个类似于一个间接的

评估,以便

a引用''f''引用的函数

代替。


感谢提示。

(这只引用了Python的模型有时候很难用b / ba $


-

Helmut Jarausch


Lehrstuhl fuer Numerische Mathematik

RWTH - 亚琛大学
D 52056德国亚琛



OK, I believe to know why the last line
print ''3'' three times, since only a reference
to ''f'' is stored within the lambda expression
and this has the value ''thrice'' when ''print''
is executed.
But how can I achieve something like an
evaluation of one indirection so that
a reference to the function referenced by ''f''
is stored instead.

Thanks for hint.
(this references only model of Python is
a bit hard sometimes)

--
Helmut Jarausch

Lehrstuhl fuer Numerische Mathematik
RWTH - Aachen University
D 52056 Aachen, Germany


在尝试解决之前我没有看过文档或试用代码
问题。我正在使用Python 2.2.1。我没有解决Act I或Act

III,并直接尝试了它们。


Act I

我没有''知道python格式化可以做到这一点!我总是把它视为C'的printf风格的陈述,因为它似乎是它主要基于它的b $ b。我总是用两个字符串

替换来首先替换格式化部分,然后实际上

插入真正的替换!


例如:
I didn''t look at docs or try out the code until after trying to solve
the problem. I''m using Python 2.2.1. I did not solve Act I or Act
III, and tried them out directly.

Act I
I didn''t know that python formatting could do that! I''ve always
treated it like C''s printf-style of statements, as that seems to be
what it''s primarily based off. I''ve always used two string
substitutions to first replace the formatting parts, then actually
insert the real substitutions!

Eg:
print(''%%% if''%(10,))%(0.5,)
0.500000

现在找到我可以做的事:打印''%* f''%(10,0.5)
0.500000


In一些方面,从C / C ++迁移到Python有点像从Linux转移到Mac OS X.我使用基本螺丝刀,因为我知道如何

和哪里它是,并且没有看到漂亮的无绳电动螺丝刀

很好地放在柜子里。


幸运的是,我浏览了整个模块索引至少一次,

所以我不会错过手提钻并使用抹子。

第二幕

再次,''这里的行为我没想到。我首先假设

结果是:


print int('''0100'') - > 100(正确)

print 16,int(''0100'',16) - > 16 256(正确)

print 10,int(''0100'',10) - > 10 100(正确)

print 8,int(''0100'',8) - > 8 64(正确)

print 2,int(''0100'',2) - > 2 4(正确)

print 0,int(''0100'',0) - > ?

print -909,int(''0100'', - 909) - > ?

print -1000,int(''0100'', - 1000) - > ?

print None,int(''0100'',None) - >无100(错误,发生类型错误)


有趣的是当我尝试出来时:int(''0100'',0)
64 int(''0100 '', - 909)
100 int(''0100'', - 1000)
回溯(最近一次调用最后一次):

文件"< stdin>" ;,第1行,在?

ValueError:int()base必须是> = 2和< = 36


我使用的是Python 2.2。 1。根据int(x,radix)的文档,关于基数行为的

部分如下:


radix参数给出了基数转换,可以是[2,36]或零范围内的任何

整数。如果基数为零,则根据字符串的内容猜测正确的
基数;解释

与整数文字相同。


这解释了0基数和由-1000基数引起的异常。

那么为什么它的基数为-909?我假设一个错误(可能在以后的Python版本中修复了
)。我将不得不看看在家里的Python 2.3b下是否存在这种行为。

第三幕

Ick。拉姆达的。现在跳过。

第四幕

我猜它会打印出来:

''现在有三个''

因为环境变量是''现在有'',

环境变量2是''三''。


我的错。跑步后,我得到:

''现在没有''


显然,os.putenv()并没有像我想象的那样工作。


啊! os.putenv()更新环境,但不更新os.environ

字典。看起来os.getenv()从os.environ中检索环境

变量,并假设它是最新的。

因为它默认为None如果环境变量不存在

在os.environ []中,这就是我得到的。


嗯,所以os.getenv()和os.putenv()不对称。这不是在Python 2.2.1文档中提到的
,因为os.getenv()列出了

as:


返回环境变量varname的值(如果存在),或

值(如果不存在)。 value默认为None。


这误导了它从实际的

环境中获取值,而不是os.environ []变量。令人讨厌和微妙的!

第三幕


Ick。拉姆达的。哦,好吧,这里有点刺痛。


funcs是一个函数列表。

flim是一个调用函数的未命名函数列表funcs。

flam是lambda'的列表理解,用于调用

funcs中的函数。


flim and flam应该是功能相当的(2/3双关语)。


输出应该是:

1 2 3

1 2 3


因为他们只是调用funcs中列出的函数(一次,

两次,三次)。

$ b $嗯,输出真的是:

1 2 3

3 3 3


这很奇怪。为什么这是结果?

print [f .__ name__ for f in funcs]
[''once'',''two'',''thice'']


因此,f正确地更新为下一个值。

用于测试[lambda x:f .__ name__ for f in funcs]:print
测试(1),id(测试)

....

三次135971068

三次136291772

三次135757396


好​​的,所以正在创建的lambda'是唯一的,但是正在映射

到第三个函数。

def fourth(x):return 4 * x
.... f
< function twice at 0x81c36bc> f =第四
f
<函数第四位于0x817383c> flam [0](1)
print (''%%%if'' % (10,)) % (0.5,) 0.500000
Now to find I can do: print ''%*f'' % (10, 0.5) 0.500000

In some respects, moving from C/C++ to Python is a bit like moving
from Linux to Mac OS X. I use the basic screwdriver, since I know how
and where it is, and don''t see the nifty cordless power screwdriver
placed nicely in the cabinet.

Luckily, I have browsed through the entire module index at least once,
so I don''t miss the jackhammers and use a trowel instead.
Act II
Again, there''s behavior here that I didn''t expect. I first assumed
that the results would be:

print int(''0100'') -> 100 (Correct)
print 16, int(''0100'', 16) -> 16 256 (Correct)
print 10, int(''0100'', 10) -> 10 100 (Correct)
print 8, int(''0100'', 8) -> 8 64 (Correct)
print 2, int(''0100'', 2) -> 2 4 (Correct)
print 0, int(''0100'', 0) -> ?
print -909, int(''0100'', -909) -> ?
print -1000, int(''0100'', -1000) -> ?
print None, int(''0100'', None) -> None 100 (Wrong, TypeError occurs)

The interesting thing is when I tried it out: int(''0100'', 0) 64 int(''0100'', -909) 100 int(''0100'', -1000) Traceback (most recent call last):
File "<stdin>", line 1, in ?
ValueError: int() base must be >= 2 and <= 36

I am using Python 2.2.1. According to the doc for int(x, radix), the
part about the radix behaviour is as follows:

The radix parameter gives the base for the conversion and may be any
integer in the range [2, 36], or zero. If radix is zero, the proper
radix is guessed based on the contents of string; the interpretation
is the same as for integer literals.

That explains the 0 radix and the exception caused by the -1000 radix.
So why does it work with a radix of -909? I presume a bug (which
probably got fixed in later versions of Python). I''ll have to see if
this behavior is present under Python 2.3b at home.
Act III
Ick. Lambda''s. Skipping for now.
Act IV
I would guess that it would print:
''Now there are three''
Since the environmental variable one is ''Now there are'', and the
environmental variable two is ''three''.

My bad. Upon running, I get:
''Now there are None''

Apparently, os.putenv() doesn''t work like I thought.

Ah! os.putenv() updates the environment, but not the os.environ
dictionary. It looks like os.getenv() retrieves the environmental
variables from os.environ, and just assumes that it is up to date.
Since it defaults to None if the environmental variable doesn''t exist
in os.environ[], that''s what I get.

Hmm, so os.getenv() and os.putenv() are not symmetric. This isn''t
mentioned in the Python 2.2.1 documentation, as os.getenv() is listed
as:

Return the value of the environment variable varname if it exists, or
value if it doesn''t. value defaults to None.

This misleads that it is getting the value from the actual
environment, not the os.environ[] variable. Nasty and subtle, too!
Act III

Ick. Lambda''s. Oh well, here''s a stab at it.

funcs is a list of functions.
flim is a list of unnamed functions that call the functions in funcs.
flam is a list comprehension of lambda''s that call the functions in
funcs.

flim and flam should be functionally equivalent (2/3 pun intended).

The output should be:
1 2 3
1 2 3

Since they are just calling the functions listed in funcs (once,
twice, thrice).

Hmm, the output is really:
1 2 3
3 3 3

That''s odd. Why is this the result here?
print [ f.__name__ for f in funcs] [''once'', ''twice'', ''thrice'']

So, f is updating correctly to the next value.
for test in [ lambda x: f.__name__ for f in funcs]: print test(1), id(test)
....
thrice 135971068
thrice 136291772
thrice 135757396

Okay, so the lambda''s being created are unique, yet are being mapped
to the third function.
def fourth(x): return 4*x .... f <function thrice at 0x81c36bc> f = fourth
f <function fourth at 0x817383c> flam[0](1)



4


啊哈!因此,当执行
时,lambda正在查找当前范围内的f!而不是绑定到在列表推导中迭代的实际函数对象,lambda绑定到

变量''f''本身?


Ick!伊克!伊克!不好接触!


(嘿,这些很有趣!)


_()()Jason Trowbridge | ......但他的最后一个页脚说''页

(''。〜。通用程序员| 3 of 2'',这让我相信

\\ \\ = o = |出了点问题。

---"`-` - ''" --- + ra **** @ nmt.edu | --Scott Bucholtz


4

Aha! So the lambda is looking up f in the current scope when it is
executed! Instead of binding to the actual function object being
iterated over in the list comprehension, the lambda is binding to the
variable ''f'' itself?

Ick! Ick! Ick! Bad touch!

(Hey, these are fun!)

_ () () Jason Trowbridge | "... but his last footer says ''page
( '' .~. Generic Programmer | 3 of 2'', which leads me to believe
\ = o = | something is wrong."
---"`-`-''"---+ ra****@nmt.edu | --Scott Bucholtz


这篇关于Python神秘剧场 - 第2集:AsíFue的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆