2012-02-28 10 views
14

Staramy się postępować zgodnie z wytycznymi PEP8 w zakresie formatowania naszego kodu Python i utrzymywania poniżej 80 znaków w linii.Formatowanie kodu SQLAlchemy

Nasze linie SQLAlchemy są szczególnie kłopotliwe, mają wiele połączonych metod i mnóstwo złożonych parametrów, logiki i funkcji zagnieżdżonych.

Czy istnieją jakieś szczególne sprawdzone metody formatowania Python SQLAlchemy z ograniczeniami PEP8?

Najbliższa odpowiedź, którą znalazłem to here, ale kod, z którym mam do czynienia, jest daleko, znacznie bardziej skomplikowany.

Odpowiedz

7

pep-8 zniechęca odwrotne ukośniki, ale dla kodu SQLAlchemy nie mogę nie myśleć, że są one najbardziej czytelne, ponieważ możesz zachować każdą funkcję generatywną na początku własnej linii. Jeśli w nawiasie jest wiele argumentów, podzielę je również na poszczególne linie.

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() 

to oczywiście nie ma znaczenia, jak skomplikowany kod jest wzór wcięcie może być prowadzona dla każdej ilości kodu, jednak w Pythonie chcemy uniknąć nadmiernego zagnieżdżania. Zwykle w Query zagnieżdżenie wystąpiłoby, ponieważ tworzysz wiele podkwerend razem. Tak więc definitywnie skonstruuj podzapytania z wyprzedzeniem:

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) 

Chciałbym powitać inne opinie na temat odwrotnego ukośnika.

+2

ładny backslashe Wykorzystanie w pocoo zespołu przewodniku redakcyjnym http://www.pocoo.org/internal/styleguide/ – estin

1

Tak, to będzie nieprzyjemne, bez względu na to, co zrobisz, więc do tego stopnia, że ​​możesz podzielić te konstrukcje na krótsze linie, zdecydowanie zrób to.

Jeśli nie możesz, możesz prawdopodobnie pozbyć się tych wszystkich ukośników, umieszczając cały RHS w nawiasie. Python będzie następnie poprawnie analizował konstrukcje multilinii bez ukośników, ale jest też trudny, więc powiedz, czy to jest lepsze czy nie. W takich przypadkach, myślę, że musisz po prostu użyć najlepszego osądu, trzymać nos i zanurzać się.

+1

jakie są szanse pep8 są wyjaśnione w odniesieniu ukośniki (dosłownie: „To powinno być stosowane zamiast do korzystania odwrotny ukośnik do kontynuacji linii. "to jedyna wzmianka)? Jeśli są zniechęceni, dlaczego Python je ma? – zzzeek

2

Jestem częstym użytkownikiem odwróconych ukośników w sposób podobny do tego, który zzzeek wskazał w swojej odpowiedzi. PEP8 to tylko wskazówka, nie przestawaj spać nad tym, gdy go naruszysz!

Jednak, ja też często używają typ formatowania poniżej, gdzie mam skradzione zzzeek za pierwszy przykład, łagodnie manipulowane go i sformatowany:

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() 

Powtarzające przeniesieniu na q wydaje rodzaju nieprzyjemnych najpierw , ale mam już nad tym. Wpływ na wydajność jest praktycznie zerowy. Dużą zaletą w ten sposób jest to, że możesz mieszać zarówno komentarze końcowe, jak i komentarze, aby udokumentować swoje zapytania (tak jak zrobiłem to z bezużytecznymi dodatkami powyżej). Łańcuch linii z tylnymi ukośnikami ogranicza cię tutaj.

ten sposób formatowania szczególnie czyste przy formułowaniu masowe zapytań z ton modyfikacje logiki wyzwalania, osadzone skalarnych wybiera itp

Jako inny przykład, mieć stosunkowo duże (> 150 linii) CTE zapytania I generuję w SQLAlchemy, który ma dużo mieszanej logiki, aliasingu i etykietowania (co jest istotne dla czytelności wygenerowanego zapytania), które miesza obie metody.Poważnie zmniejszona (i zniekształcone) wersja nim zacznie coś jak poniżej:

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)... 

W ogóle, jeśli upewnij się, aby prowadzić swoje linie off z nowych operacji (jak wielu systemów formatowania wspólny SQL zrobić), to pozostanie całkiem czytelny. Nie bój się też nowych wierszy w nawiasach.

+1

Ma to tę dodatkową zaletę, że ułatwia debugowanie za pomocą 'pdb' a * lot *! Po każdym filtrze jest na własne oświadczenie! – exhuma

24

Przyjechałem tu z nadzieją na lepsze rozwiązanie, ale myślę, że wolą nawiasach styl otaczania:

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() 
) 

To jest ładne i czyste, a unika się bał backslash.

Powiązane problemy