簡體   English   中英

pythonic方法在if語句中重寫賦值

[英]pythonic way to rewrite an assignment in an if statement

有沒有一種pythonic首選方法來實現這一點,我將在C ++中做:


for s in str:
    if r = regex.match(s):
        print r.groups()

我真的很喜歡這種語法,因為它比在任何地方都有臨時變量要清晰得多。 唯一不太復雜的其他方式是


for s in str:
    r = regex.match(s)
    if r:
        print r.groups()

我想我抱怨一個非常迂腐的問題。 我只是想念以前的語法。

怎么樣

for r in [regex.match(s) for s in str]:
    if r:
        print r.groups()

或更多功能

for r in filter(None, map(regex.match, str)):
    print r.groups()

也許它有點hacky,但使用函數對象的屬性來存儲最后的結果允許你沿着這些方向做一些事情:

def fn(regex, s):
    fn.match = regex.match(s) # save result
    return fn.match

for s in strings:
    if fn(regex, s):
        print fn.match.groups()

或者更一般地說:

def cache(value):
    cache.value = value
    return value

for s in strings:
    if cache(regex.match(s)):
        print cache.value.groups()

請注意,盡管保存的“值”可以是許多內容的集合,但這種方法僅限於一次只保留一個,因此可能需要多個函數來處理需要同時保存多個值的情況例如在嵌套函數調用,循環或其他線程中。 因此,根據DRY原則,工廠功能可以幫助:而不是編寫每個原則。

def Cache():
    def cache(value):
        cache.value = value
        return value
    return cache

cache1 = Cache()
for s in strings:
    if cache1(regex.match(s)):
        # use another at same time
        cache2 = Cache()
        if cache2(somethingelse) != cache1.value:
            process(cache2.value)
        print cache1.value.groups()
          ...

有一個配方 ,使賦值表達式,但它是非常哈克。 你的第一個選項沒有編譯,所以你的第二個選擇是要走的路。

## {{{ http://code.activestate.com/recipes/202234/ (r2)
import sys
def set(**kw):
    assert len(kw)==1

    a = sys._getframe(1)
    a.f_locals.update(kw)
    return kw.values()[0]

#
# sample
#

A=range(10)

while set(x=A.pop()):
    print x
## end of http://code.activestate.com/recipes/202234/ }}}

正如您所看到的,生產代碼不應該用10英尺雙袋裝棒觸摸這個黑客。

這可能是一個過於簡單的答案,但你會考慮這個:

for s in str:
    if regex.match(s):
        print regex.match(s).groups()

沒有pythonic方法來做一些不是pythonic的事情。 這是出於某種原因,因為1,允許if語句的條件部分中的語句會使語法變得非常難看,例如,如果你在if條件中允許賦值語句,為什么不允許if語句呢? 你怎么寫這個? C語言沒有這個問題,因為它們沒有賦值語句。 他們只使用賦值表達式和表達式語句。

第二個原因是因為這樣

if foo = bar:
    pass

看起來非常相似

if foo == bar:
    pass

即使你足夠聰明地鍵入正確的一個,即使你團隊中的大多數成員都足夠清楚地注意到它,你確定你現在正在看的那個正是應該在那里嗎? 一個新的開發人員看到這個並且只是修復它(這種或那種方式)並不是沒有道理的,現在它肯定是錯誤的。

每當我發現我的循環邏輯變得復雜時,我會用任何其他邏輯做我想做的事情:我將它提取到函數中。 在Python中,干凈利落地比其他語言容易得多。

因此,提取僅生成感興趣項目的代碼:

def matching(strings, regex):
    for s in strings:
        r = regex.match(s)
        if r: yield r

然后當你想要使用它時,循環本身就像它們得到的一樣簡單:

for r in matching(strings, regex):
    print r.groups()

另一個答案是使用“分配和測試”方法,允許在O'Reilly Media 2002年7月第1版的Python Cookbook和Activestate 在線發布的單個語句中進行分配和測試。 它是面向對象的,其關鍵在於:

# from http://code.activestate.com/recipes/66061
class DataHolder:
    def __init__(self, value=None):
        self.value = value
    def set(self, value):
        self.value = value
        return value
    def get(self):
        return self.value

這可以通過添加下面顯示的自定義__call__()方法來稍微修改,以提供另一種方法來檢索實例的值 - 雖然不那么明確,但對於'DataHolder'對象來說,這似乎是完全合乎邏輯的事情。 , 我認為。

    def __call__(self):
        return self.value

允許重寫您的示例:

r = DataHolder()
for s in strings:
    if r.set(regex.match(s))
        print r.get().groups()
# or
        print r().groups()

正如原始配方中所指出的,如果你經常使用它,將它和/或它的實例添加到__builtin__模塊以使其全局可用是非常誘人的,盡管潛在的缺點:

import __builtin__
__builtin__.DataHolder = DataHolder
__builtin__.data = DataHolder()

正如我在對這個問題的另一個答案中提到的那樣,必須注意這種方法僅限於一次只保存一個結果/值,因此需要多個實例來處理需要同時保存多個值的情況,例如在嵌套函數調用,循環或其他線程中。 這並不意味着你應該使用它或其他答案,只需要付出更多的努力。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM