代码之家  ›  专栏  ›  技术社区  ›  tel

剖析一行(模糊的?)蟒蛇

  •  8
  • tel  · 技术社区  · 14 年前

    我在读另一个关于堆栈溢出的问题( Zen of Python

    import this
    "".join([c in this.d and this.d[c] or c for c in this.s])
    

    "The Zen of Python, by Tim Peters\n\nBeautiful is better than ugly.\nExplicit is
    better than implicit.\nSimple is better than complex.\nComplex is better than 
    complicated.\nFlat is better than nested.\nSparse is better than dense.
    \nReadability counts.\nSpecial cases aren't special enough to break the rules.
    \nAlthough practicality beats purity.\nErrors should never pass silently.
    \nUnless explicitly silenced.\nIn the face of ambiguity, refuse the temptation to
    guess.\nThere should be one-- and preferably only one --obvious way to do it.
    \nAlthough that way may not be obvious at first unless you're Dutch.\nNow is 
    better than never.\nAlthough never is often better than *right* now.\nIf the 
    implementation is hard to explain, it's a bad idea.\nIf the implementation is
    easy to explain, it may be a good idea.\nNamespaces are one honking great idea 
    -- let's do more of those!"
    

    所以我不得不花了一上午的时间来理解上面的清单。。。理解。。。事情。我不太愿意直截了当地声明它是模糊的,但这仅仅是因为我只编写了一个半月的程序,所以不确定这种构造在python中是否很常见。

    this.s 包含上述打印输出的编码版本:

    "Gur Mra bs Clguba, ol Gvz Crgref\n\nOrnhgvshy vf orggre guna htyl.\nRkcyvpvg vf orggre guna vzcyvpvg.\nFvzcyr vf orggre guna pbzcyrk.\nPbzcyrk vf orggre guna pbzcyvpngrq.\nSyng vf orggre guna arfgrq.\nFcnefr vf orggre guna qrafr.\nErnqnovyvgl pbhagf.\nFcrpvny pnfrf nera'g fcrpvny rabhtu gb oernx gur ehyrf.\nNygubhtu cenpgvpnyvgl orngf chevgl.\nReebef fubhyq arire cnff fvyragyl.\nHayrff rkcyvpvgyl fvyraprq.\nVa gur snpr bs nzovthvgl, ershfr gur grzcgngvba gb thrff.\nGurer fubhyq or bar-- naq cersrenoyl bayl bar --boivbhf jnl gb qb vg.\nNygubhtu gung jnl znl abg or boivbhf ng svefg hayrff lbh'er Qhgpu.\nAbj vf orggre guna arire.\nNygubhtu arire vf bsgra orggre guna *evtug* abj.\nVs gur vzcyrzragngvba vf uneq gb rkcynva, vg'f n onq vqrn.\nVs gur vzcyrzragngvba vf rnfl gb rkcynva, vg znl or n tbbq vqrn.\nAnzrfcnprf ner bar ubaxvat terng vqrn -- yrg'f qb zber bs gubfr!"
    

    以及 this.d 包含一个字典和解码的密码 这个。s :

    {'A': 'N', 'C': 'P', 'B': 'O', 'E': 'R', 'D': 'Q', 'G': 'T', 'F': 'S', 'I': 'V', 'H': 'U', 'K': 'X', 'J': 'W', 'M': 'Z', 'L': 'Y', 'O': 'B', 'N': 'A', 'Q': 'D', 'P': 'C', 'S': 'F', 'R': 'E', 'U': 'H', 'T': 'G', 'W': 'J', 'V': 'I', 'Y': 'L', 'X': 'K', 'Z': 'M', 'a': 'n', 'c': 'p', 'b': 'o', 'e': 'r', 'd': 'q', 'g': 't', 'f': 's', 'i': 'v', 'h': 'u', 'k': 'x', 'j': 'w', 'm': 'z', 'l': 'y', 'o': 'b', 'n': 'a', 'q': 'd', 'p': 'c', 's': 'f', 'r': 'e', 'u': 'h', 't': 'g', 'w': 'j', 'v': 'i', 'y': 'l', 'x': 'k', 'z': 'm'}
    

    据我所知,Jaime代码中的执行流程如下:
    1循环 c for c in this.s
    c in this.d 计算结果为True时,“and”语句将执行其直接右边的任何内容(在本例中) this.d[c] .
    c在这个。d 计算结果为False(Jaime的代码中从不发生这种情况),“or”语句执行其直接右边的任何内容,在本例中是循环 .

    我说的对吗?

    for 循环开始执行并赋值,但实际上只在代码执行的稍后点返回一个值,如果有的话?

    另外,为了加分,禅宗档案里关于荷兰人的奇怪台词是怎么回事?

    编辑: 虽然现在说这话让我感到羞耻,但直到三秒钟前我还以为吉多·范·罗森是意大利人。在阅读了他的维基百科文章之后,我至少理解了,如果不是完全理解的话,为什么会有这句话。

    6 回复  |  直到 7 年前
        1
  •  11
  •   sth Wojciech Parzych    14 年前

    列表理解行中的运算符如下所示:

    "".join([(((c in this.d) and this.d[c]) or c) for c in this.s])
    

    result = []
    for c in this.s:
       result.append(((c in this.d) and this.d[c]) or c)
    print "".join(result)
    

    卸下 and / or 布尔技巧,用于模拟 if else 声明:

    result = []
    for c in this.s:
       if c in this.d:
          result.append(this.d[c])
       else:
          result.append(c)
    print "".join(result)
    
        2
  •  2
  •   Xavier Combelle    14 年前

    你说得对。

    [dosomething(c) for c in this.s]

    荷兰语部分是关于圭多·范·罗森的,python的创造者是荷兰人。

        3
  •  2
  •   recursive    14 年前

    here .

    列表理解的基本形式是

    [expression for var in enumerable if condition]
    

    1. 计算可枚举项
    2. 每个值依次分配给var
    3. 表达式已计算

    结果是枚举表中条件为真的每个元素的表达式值列表。

    [(c in this.d and this.d[c] or c) for c in (this.s)]
    

    this.s c 是迭代变量。 c in this.d and this.d[c] or c 是表达式。

    在这个,这个,这个,或 this.d[c] if c in this.d else c .

    总而言之,我不认为这是混淆的。一旦你理解了列表理解的力量,它就会显得很自然。

        4
  •  2
  •   unutbu    14 年前

    一般来说,列表理解的形式如下:

    [ expression for var in iterator ]
    

    [ for var in iterator ]
    

    因为多年的过程编程已经将for循环方面灌输到我的脑海中,作为第一部分。

    对于循环中的每一次传递,都会计算表达式。 (次要的一点是:计算表达式,执行语句。)

    所以在这种情况下,我们有

    [ expression for c in this.s ]
    

    这是一个字符串。在Python中,字符串是迭代器!当你写作的时候

    for c in some_string:
    

    c 按顺序呈现此.s中的每个角色。

    现在表达式是

    c in this.d and this.d[c] or c
    

    ternary operation . 这个链接解释了逻辑,但基本思想是

    if c in this.d:
        the expression evaluates to this.d[c]
    else:
        the expression evaluates c
    

    条件 c in this.d 因此,只需检查dict this.d 有一个具有值的键 c this.d[c] ,如果没有,返回 c 它自己。

    另一种写法是

    [this.d.get(c,c) for c in this.s]
    

    (第二个论点是 get method 当第一个参数不在dict中时返回的默认值)。

    三元形式

    condition and value1 or value2
    

    容易出错。(想想如果 condition 是真的,但是 value1 None . 自 条件 价值1 没有 没有 False value2 相反。因此,如果您不小心并意识到这个陷阱,三元形式可能会引入错误。)

    对于Python的现代版本,更好的编写方法是

    value1 if condition else value2
    

    条件 价值1 .

    this.d.get(c,c)

        5
  •  2
  •   John Machin Santi    14 年前

    "".join([c in this.d and this.d[c] or c for c in this.s]) 当然是混淆了。这里有一个禅宗版本:

    this.s.decode('rot13')

        6
  •  0
  •   Tony Veijalainen    14 年前

    带有现代if-else和生成器的我的版本:

    import this ## prints zenofpython
    print '-'*70
    whatiszenofpython = "".join(this.d[c] if c in this.d else c for c in this.s)
    zen = ''
    for c in this.s:
        zen += this.d[c] if c in this.d else c
    print zen
    

    口头版本: 导入这个,它的主程序解扰并打印这个消息 要对消息进行解扰,请将dict this.d中的字母替换为已解码的计数器部分(大小写不同)。其他字母不需要更改,但按原样打印。