2012-02-28 50 views
14

我們正在嘗試遵循PEP8格式化我們的Python代碼並保持每行低於80個字符的指導原則。格式化SQLAlchemy代碼

我們的SQLAlchemy行特別麻煩,有大量的鏈接方法和大量的複雜參數,邏輯和嵌套函數。

是否有任何特定的最佳實踐來格式化Python SQLAlchemy的約束PEP8?

我發現的最接近的答案是here,但我所處理的代碼遠遠更復雜。

回答

7

pep-8不鼓勵反斜槓,但對於SQLAlchemy代碼,我不禁想到它們是最可讀的,因爲您可以將每個生成函數保留在自己的行的開頭。如果括號內有很多參數,我會在個別行上分解它們。

subkeyword = Session.query(
        Subkeyword.subkeyword_id, 
        Subkeyword.subkeyword_word 
      ).\ 
       filter_by(subkeyword_company_id=self.e_company_id).\ 
       filter_by(subkeyword_word=subkeyword_word).\ 
       filter_by(subkeyword_active=True).\ 
       one() 

當然不要緊代碼是如何複雜的是它,壓痕模式可以爲任何代碼量進行下去,但是在Python我們要避免過多的嵌套。通常在使用Query時,會發生嵌套,因爲您正在組合許多子查詢。因此,絕對提前構建子查詢:

subq = Session.query(
       Bat.id, 
       func.foo(Bat.x, Bat.y).label('foo') 
       ).\ 
       filter(Bat.id==Bar.name).\ 
       correlate(Bar).\ 
       subquery() 

subq2 = Session.query(Foo.id, Foo.bar).\ 
       filter_by(flag>5).\ 
       subquery() 

result = Session.query(
        subq.c.id, 
        subq.c.foo, 
        subq2.c.bar 
       ).\ 
       join(subq2, 
        and_(
         subq.c.id > subq2.c.foo, 
         subq.bar == subq2.id 
        ) 
       ).\ 
       order_by(subq.c.id, subq2.c.bar) 

我會歡迎其他意見反斜槓的事情。

+2

pocoo團隊風格指南中很好的反斜槓用法http://www.pocoo.org/internal/styleguide/ – estin 2012-02-28 12:04:59

1

是的,無論你做什麼,這些都會變得很討厭,所以如果你能把這些結構分成更短的行,那肯定是這樣。

當你不能的時候,你可以通過把整個RHS放在一個圓括號中去掉所有的反斜槓。然後,Python將正確地解析多行構造,而不用反斜槓,但也很難說這是否更好。在這樣的情況下,我認爲你只需要用你最好的判斷,抓住你的鼻子並投入。

+1

pep8有關反斜槓的說明的機會是什麼(字面上,「這些應該優先使用反斜槓換行「)是唯一提及的)?如果他們不鼓勵,爲什麼Python甚至擁有它們? – zzzeek 2012-02-28 19:45:50

2

我是類似於zzzeek在他的回答中指出的反斜槓的用戶。 PEP8只是一個指導方針,當你違犯它時不要失眠!

不過,我也經常使用以下格式,在那裏我已經偷zzzeek的第一個例子中的類型,輕度調整了它,並重新格式化:

q = Session.query(
    Subkeyword.subkeyword_id, 
    Subkeyword.subkeyword_word, 
) 
q = q.filter_by(subkeyword_company_id=self.e_company_id) # first filter 
q = q.filter_by(subkeyword_word=subkeyword_word) # 2nd filter 
q = q.filter_by(subkeyword_active=True) 

if filter_by_foo: 
    q = q.filter(Subkeyword.foo == True) 

# Run the query (I usually wrap in a try block)... 
subkeyword = q.one() 

反覆重新分配到q起初似乎有點討厭,但我已經完成了。性能影響實際上是零。這種方式的一大優勢是,您可以在尾部註釋和註釋行中混合使用,以記錄您的查詢(正如我對上面的無用添加所做的那樣)。用反斜槓鏈接線限制你在這裏。

格式的這種方式與邏輯觸發修改噸,嵌入式標量選擇等

作爲另一示例配製大量查詢時,特別乾淨,我有一個相當大(> 150線)CTE查詢我在SQLAlchemy中生成的混合邏輯,別名和標籤(這對生成的查詢的可讀性來說非常重要)混合了這兩種方法。它的一個嚴重降低(血肉模糊)版本開始像下面的東西:

cte_init = session.\ 
    query(
     child1.foo.label("child1_foo"), 
     sa.literal(1).label("indent"), # can comment on non-slashed lines 
     child2.bar.label("child2bar"), 
     #comments between non-slashed lines ok, too 
     sa.func.MAX(toplevel.baz).label("max_baz"), 
    ).\ 
    select_from(top_level).\ 
    join(child1, 
     child1.id == toplevel.fk_child1_id).\ 
    join(child2. 
     child2.id == toplevel.fk_child2.id).\ 
    filter(top_level.name == "bogus").\ 
    cte(name = "cte", recursive = True) 

if(use_filter_x): 
    cte_init = cte_init.filter_by(x = "whatever") 

# etc (no, the above doesn't make any sense)... 

在一般情況下,如果要確保新業務(如許多常見的SQL格式方案做)帶領你行了,它保持很可讀。不要害怕括號內的換行符。

+1

這也帶來了額外的好處,它使得'pdb' a * lot *更容易調試!因爲每個過濾器都有自己的聲明! – exhuma 2014-02-24 10:20:47

24

來到這裏,希望有一個更好的解決方案,但我想我更喜歡括號環繞方式:

subkeyword = (
    Session.query(
     Subkeyword.subkeyword_id, 
     Subkeyword.subkeyword_word 
    ) 
    .filter_by(subkeyword_company_id=self.e_company_id) 
    .filter_by(subkeyword_word=subkeyword_word) 
    .filter_by(subkeyword_active=True) 
    .one() 
) 

這是很好的和明確的,並且避免了可怕的反斜槓。