2012-12-11 20 views
2

下面是一些代碼:PEP8,當地人()和插值

foo = "Bears" 
"Lions, Tigers and %(foo)s" % locals() 

我PEP8棉短絨(SublimeLinter)抱怨這個,因爲foo是 「未引用」。我的問題是,PEP8是否應該將這種類型的字符串插值計算爲「引用」,或者是否有充分理由認爲這種「不良風格」。

回答

5

那麼,它是不是引用。可疑樣式的部分使用locals()來訪問變量,而不是通過名稱來訪問它們。看到this previous question爲什麼這是一個可疑的想法。這不是一件可怕的事情,但對於一個您想要長期維護的計劃來說,這並不是一種好風格。

編輯:確實,當你使用字面格式字符串時,它看起來更加明確。但前一篇文章的一部分內容是,在一個更大的程序中,您可能會使用文字格式字符串結束而不是。如果它是一個小程序,你不在乎,請繼續使用它。但是,警告以後可能導致可維護性問題的事情也是風格指南和絨毛衫的一部分。

此外,locals不是在文字中明確引用的名稱的規範表示形式。這是所有名稱在本地命名空間中的規範表示形式。如果你願意的話,你仍然可以做到,但它基本上是一個鬆散/草率的替代方案,可以明確地使用你正在使用的名稱,這也正是棉絨商應該警告你的事情。

+0

但是在這種情況下,字符串插值在文字中是明確的。當傳遞可能來自任何地方的格式字符串時,我會發現他來自另一個答案的位置,但即使它們使用相同的機制,它仍然是一個不同於具有帶有顯式格式標記和插值的字符串文字的怪物。我可以看到有一種方法來評估它的精神慾望,但是(在這裏)locals()是一個在文字中明確引用的名稱的規範表示,所以我覺得參數仍然可以用其他方式。我瘋了嗎? –

+1

@ A.Wilson:看到我編輯的答案。這篇文章的一部分內容是,如果它是一個大程序,你可能會永遠不會使用文字格式字符串。如果你知道這不會成爲問題,那就去做吧,但是你可以在後面告訴你一些可能會成爲問題的事情。 – BrenBarn

+0

@BrenBarn:這是一個很好的元組。 linter的目的是驗證您的代碼技術是否符合PEP8的字面文本,或避免PEP8試圖阻止的問題? – abarnert

1

即使你拒絕BrenBarn的論點,即foo沒有被引用,如果你接受,在字符串格式化通過locals()應該被標記的參數,它可能不值得寫代碼來考慮foo引用。

首先,在每一種情況下,額外的代碼都可以幫助,無論如何這個構造是不可接受的,用戶將不得不忽略皮棉警告。是的,當只有實際存在一個問題時,給予用戶兩個012警告忽視警告時會有一些傷害,特別是如果其中一個警告有些誤導。但是,爲了編寫非常複雜的代碼和向linter中引入新的錯誤,是否有足夠的傷害呢?

你也必須考慮到這一實際工作中,棉短絨已經認識到不只是%格式,而且還{}格式,和所有其他類型的字符串格式化,HTML模板等,用戶可以使用。實際上,這意味着處理各種常見的形式,併爲用戶提供某種形式的描述。

而且,最重要的是,即使您認爲它不應該與任意生成的格式字符串一起工作,它肯定至少需要使用l10n。這是如何工作的?如果格式字符串由類似gettext的東西生成,那麼linter無法知道foo是否被引用,除非它可以檢查所有翻譯並查看其中至少有一個引用foo,這意味着它必須理解(或有掛鉤要教)每個字符串翻譯機制,並有權訪問翻譯數據庫。

所以,我會建議,即使您在這種情況下考慮到虛假警告,您仍然會將其留在那裏。頂多加一些東西,有資格的警告:

foo可能是未引用的,但在功能使用locals()

+0

你說服了我。我希望我可以接受BrenBarn的,但 –

+0

我的回答很明顯取決於BrenBarn的;什麼是最好的是,如果有一種方式來表明這樣做,所以接受我的會自動給他一些信用,他的答案移動到名單上第二等。 – abarnert

+1

@ A.Wilson:一個進一步的思想對此:我想你想用'locals()'在_any_情況下使用合格警告。想象一下函數'def foo(func):bar = 3; FUNC(當地人())'。 'bar'是否被引用?即使絨毛可以以某種方式發現,人類讀者也不能,而這正是你想要標記的東西。 (但是你可能確實想找到比我的警告更好的措辭......) – abarnert

0

下不會使SublimeLinter快樂要麼,它查找每個變量名在字符串中引用並替換名稱空間映射中的相應值,該值默認爲調用者的locals。因此,它顯示了SublimeLinter在嘗試確定是否在Python中引用了某個實用程序時的實用程序的固有限制)。我的建議是忽略SublimeLinter或添加代碼來僞造它,如foo = foo。我必須做一些像後者一樣的東西來擺脫C編譯器對合法和意圖的警告。

import re 
import sys 
SUB_RE = re.compile(r"%\((.*?)\)s") 

def local_vars_subst(s, namespace=None): 
    if namespace is None: 
     namespace = sys._getframe(1).f_locals 

    def repl(matchobj): 
     var = matchobj.group(1).strip() 
     try: 
      retval = namespace[var] 
     except KeyError: 
      retval = "<undefined>" 
     return retval 

    return SUB_RE.sub(repl, s) 

foo = "Bears" 
print local_vars_subst("Lions, Tigers and %(foo)s")