Jak mogę przerwać tę długą linię w Pythonie?

176

Jak zabrałbyś się do formatowania tak długiej linii? Chciałbym, aby szerokość nie przekraczała 80 znaków:

logger.info("Skipping {0} because its thumbnail was already in our system as {1}.".format(line[indexes['url']], video.title))

Czy to moja najlepsza opcja?

url = "Skipping {0} because its thumbnail was already in our system as {1}."
logger.info(url.format(line[indexes['url']], video.title))
Gattster
źródło
1
Wydaje się, że to dobra opcja. Co ci się w nim nie podoba?
Hamish Grubijan,
2
Trochę subiektywne, prawda? :)
Adam Woś
1
related: stackoverflow.com/questions/1940710/… (konkatenacja ciągów w pythonie)
jldupont
14
Możesz zapisać znak, usuwając niepoprawne „to”.
jball
2
indexes: poprawna liczba mnoga indexto indices.
Niechlujny

Odpowiedzi:

336

To jest początek. Definiowanie dłuższych ciągów poza kodem, który ich używa, nie jest złą praktyką. To sposób na oddzielenie danych i zachowania. Pierwszą opcją jest niejawne łączenie ze sobą literałów łańcuchowych, ustawiając je obok siebie:

("This is the first line of my text, "
"which will be joined to a second.")

Lub z kontynuacjami kończącymi linię, co jest nieco bardziej delikatne, ponieważ działa:

"This is the first line of my text, " \
"which will be joined to a second."

Ale to nie jest:

"This is the first line of my text, " \ 
"which will be joined to a second."

Zobacz różnicę? Nie? Cóż, nie zrobisz tego, jeśli to twój kod.

Wadą niejawnego łączenia jest to, że działa tylko z literałami łańcuchowymi, a nie z łańcuchami pobranymi ze zmiennych, więc rzeczy mogą stać się trochę bardziej skomplikowane podczas refaktoryzacji. Ponadto można interpolować formatowanie tylko dla połączonego ciągu jako całości.

Alternatywnie możesz dołączyć jawnie za pomocą operatora konkatenacji ( +):

("This is the first line of my text, " + 
"which will be joined to a second.")

Jawne jest lepsze niż niejawne, jak mówi zen w Pythonie, ale tworzy to trzy ciągi zamiast jednego i zużywa dwa razy więcej pamięci: są dwa, które napisałeś, plus jeden, który jest połączeniem dwóch z nich, więc trzeba wiedzieć, kiedy ignorować zen. Plusem jest to, że możesz zastosować formatowanie do dowolnego z podciągów osobno w każdym wierszu lub do całej partii spoza nawiasów.

Na koniec możesz użyć ciągów w potrójnych cudzysłowach:

"""This is the first line of my text
which will be joined to a second."""

Jest to często mój ulubiony element, chociaż jego zachowanie jest nieco inne, ponieważ nowa linia i wszelkie początkowe białe znaki w kolejnych wierszach pojawią się w końcowym ciągu. Możesz usunąć znak nowej linii za pomocą uciekającego odwrotnego ukośnika.

"""This is the first line of my text \
which will be joined to a second."""

Ma to ten sam problem, co ta sama technika powyżej, ponieważ poprawny kod różni się od niepoprawnego tylko niewidoczną białą spacją.

To, które z nich jest „najlepsze”, zależy od konkretnej sytuacji, ale odpowiedź nie jest po prostu estetyczna, ale jest jednym z subtelnie różnych zachowań.

jcdyer
źródło
26
Kompilator CPython optymalizuje operacje literałów tak bardzo, jak to możliwe, co oznacza, że ​​dodanie dwóch literałów łańcuchowych daje tylko jeden literał łańcuchowy w kodzie bajtowym.
Ignacio Vazquez-Abrams
2
Chociaż wszystkie odpowiedzi, które otrzymałem, są pomocne, Twoja zdecydowanie pomaga mi zrozumieć wszystkie sposoby zrywania sznurków. Czy był problem z zakończeniem wiersza „\” polegającym na tym, że po nim była spacja?
Gattster
1
Nie widzę tutaj różnicy, ale to głównie z powodu raczej prymitywnego kolorowania składni SO. (Pewien doskonale dobry kod jest praktycznie nieczytelny w SO, ale tylko dlatego, że nie jest w języku, którego składnia jest bardzo zbliżona do C.) Nie jest niczym niezwykłym, że twój edytor w nieprzyjemny sposób wyróżnia spacje końcowe, ponieważ rzadko są przydatne (lub celowe) . :-)
Ken
1
@KhurshidAlam, możesz użyć pojedynczych cudzysłowów, 'aby zawrzeć ten ciąg, lub uciec od podwójnych cudzysłowów w ciągu lub użyć potrójnych podwójnych cudzysłowów """. Problem z napisami w cudzysłowie, które zawierają cudzysłowy, jest taki sam, niezależnie od tego, czy do zdefiniowania ciągu literału używany jest pojedynczy wiersz, czy wiele wierszy.
hugovdberg
1
Mój edytor zawsze usuwa końcowe spacje. Zalecam włączenie tego samego ustawienia. Oczywiście wtedy biały znak w nowej linii jest nadal częścią ciągu, więc ostatecznie użyłem +.
ThaJay
46

Kolejne literały ciągów są łączone przez kompilator, a wyrażenia w nawiasach są traktowane jako pojedynczy wiersz kodu:

logger.info("Skipping {0} because it's thumbnail was "
  "already in our system as {1}.".format(line[indexes['url']],
  video.title))
Ignacio Vazquez-Abrams
źródło
11

Osobiście nie lubię wieszać otwartych bloków, więc sformatowałbym to jako:

logger.info(
    'Skipping {0} because its thumbnail was already in our system as {1}.'
    .format(line[indexes['url']], video.title)
)

Ogólnie nie zawracałbym sobie głowy zbyt ciężkim zmaganiem się z dopasowaniem kodu dokładnie do 80-kolumnowej linii. Warto utrzymywać długość linii na rozsądnym poziomie, ale twardy limit 80 to już przeszłość.

bobince
źródło
8
To naprawdę nie należy do przeszłości. Standardowa biblioteka Pythona nadal używa PEP8 jako swojego przewodnika po stylach, więc ta reguła nadal istnieje i wiele osób (łącznie ze mną) ją przestrzega. To wygodne miejsce na narysowanie linii.
Devin Jeanpierre
3
Zastanawiam się, ile projektów wciąż przestrzega zasady 80 znaków. Dla średniego rozmiaru okna, którego używam, myślę, że 100-120 jest dla mnie bardziej produktywne niż 80 znaków.
Gattster,
1
Tak, chodzi o długość linii, której używam, chociaż [o horror! świętokradztwo!] Używam proporcjonalnej czcionki, więc dokładna długość linii nie jest tak ważna. Jest to bardziej kwestia tego, ile logiki w pojedynczym wierszu jest czytelnych, niż ile znaków, jako takich ... jeśli mam długi ciąg danych, których nikt nie musi czytać, cieszę się, że mogę się rozlać 120.
bobince
Proporcjonalne czcionki do kodu - jestem z tobą, bracie. Sądząc po niechęci, jaką darzyli do nich wszyscy, z którymi kiedykolwiek pracowałem, świat nie jest gotowy.
jlarcombe
4
~ 80 znaków ułatwia także porównywanie 2 plików obok siebie na tym samym ekranie. Ponadto, jeśli debugujesz coś podczas strasznego zagrożenia na konsoli serwera, naprawdę docenisz limit 80 znaków! :)
Mick T
4

Możesz użyć modułu textwrap, aby podzielić go na wiele linii

import textwrap
str="ABCDEFGHIJKLIMNO"
print("\n".join(textwrap.wrap(str,8)))

ABCDEFGH
IJKLIMNO

Z dokumentacji :

zawijanie tekstu. wrap (text [, width [, ...]])
Zawija pojedynczy akapit w tekście (łańcuch), tak aby każda linia miała co najwyżej szerokość znaków. Zwraca listę wierszy wyjściowych, bez ostatnich nowych wierszy.

Opcjonalne argumenty słów kluczowych odpowiadają atrybutom instancji TextWrapperudokumentowanym poniżej. szerokość domyślnie 70.

Zobacz TextWrapper.wrap()metodę, aby uzyskać dodatkowe informacje o zachowaniu metody wrap ().

Saurabh
źródło
2

Dla każdego, kto próbuje również wywołać .format()długi ciąg i nie jest w stanie użyć niektórych najpopularniejszych technik zawijania ciągów bez przerywania kolejnego .format(wywołania, możesz to zrobić str.format("", 1, 2)zamiast "".format(1, 2). To pozwala zrywać strunę dowolną techniką. Na przykład:

logger.info("Skipping {0} because its thumbnail was already in our system as {1}.".format(line[indexes['url']], video.title))

może być

logger.info(str.format(("Skipping {0} because its thumbnail was already"
+ "in our system as {1}"), line[indexes['url']], video.title))

W przeciwnym razie jedyną możliwością jest użycie kontynuacji zakończeń linii, których osobiście nie jestem fanem.

Simon Alford
źródło