Kompaktowy sposób pisania (a + b == c lub a + c == b lub b + c == a)

136

Czy istnieje bardziej zwarty lub pythoniczny sposób zapisu wyrażenia boolowskiego

a + b == c or a + c == b or b + c == a

wymyśliłem

a + b + c in (2*a, 2*b, 2*c)

ale to jest trochę dziwne.

qwr
źródło
16
Bardziej kompaktowy? Możliwie. Więcej Pythonic? Mało prawdopodobne.
chepner
126
Zrób sobie przysługę i zachowaj ją w pierwotnej formie: tylko to od razu mówi o celu tego. Nie modyfikuj tego. „Proste jest lepsze niż złożone”, „Czytelność się liczy”. „Jeśli implementacja jest trudna do wyjaśnienia, to zły pomysł”.
poke
21
Pythonic == nieczytelne?
nhaarman
3
@wwii Nie wykluczają się wzajemnie. Zobacz a = 0, b = 0, c = 0;)
Honza Brabec
1
Co powiedział @phresnel. Zamiast próbować „uprościć” wyrażenie, opakuj je w funkcję o opisowej nazwie.
Głowonóg

Odpowiedzi:

206

Jeśli spojrzymy na Zen Pythona, podkreśl moje:

Zen Pythona - Tim Peters

Piękne jest lepsze niż brzydkie.
Jawne jest lepsze niż niejawne.
Proste jest lepsze niż złożone.
Złożone jest lepsze niż skomplikowane.
Płaskie jest lepsze niż zagnieżdżone.
Rzadkie jest lepsze niż gęste.
Liczy się czytelność.
Specjalne przypadki nie są na tyle wyjątkowe, aby łamać zasady.
Chociaż praktyczność przewyższa czystość.
Błędy nigdy nie powinny przejść bezgłośnie.
Chyba że wyraźnie uciszono.
W obliczu niejasności odrzuć pokusę zgadywania.
Powinien być jeden - a najlepiej tylko jeden - oczywisty sposób na zrobienie tego.
Chociaż na początku może to nie być oczywiste, chyba że jesteś Holendrem.
Teraz jest lepiej niż nigdy.
Chociaż nigdy nie jest często lepsze niżprawo teraz.
Jeśli implementacja jest trudna do wyjaśnienia, to zły pomysł.
Jeśli implementacja jest łatwa do wyjaśnienia, może to być dobry pomysł.
Przestrzenie nazw to świetny pomysł - zróbmy ich więcej!

Najbardziej Pythonowe rozwiązanie to takie, które jest najbardziej przejrzyste, najprostsze i najłatwiejsze do wyjaśnienia:

a + b == c or a + c == b or b + c == a

Co więcej, nie musisz nawet znać języka Python, aby zrozumieć ten kod! To takie proste. To bez zastrzeżeń najlepsze rozwiązanie. Wszystko inne to intelektualna masturbacja.

Co więcej, jest to prawdopodobnie również najlepsze rozwiązanie, ponieważ jest to jedyna ze wszystkich propozycji, która powoduje zwarcia. Jeśli a + b == cwykonuje się tylko jedno dodanie i porównanie.

Barry
źródło
11
Jeszcze lepiej, dodaj kilka nawiasów, aby intencja była krystalicznie jasna.
Bryan Oakley,
3
Zamiar jest już krystalicznie jasny bez nawiasów. Nawiasy utrudniałyby czytanie - dlaczego autor używa nawiasów, skoro pierwszeństwo już to obejmuje?
Miles Rout,
1
Jeszcze jedna uwaga dotycząca próby bycia zbyt sprytnym: możesz wprowadzić nieprzewidziane błędy, pomijając warunki, których nie brałeś pod uwagę. Innymi słowy, możesz pomyśleć, że Twoje nowe kompaktowe rozwiązanie jest równoważne, ale nie we wszystkich przypadkach. Jeśli nie ma ważnego powodu, aby kodować inaczej (wydajność, ograniczenia pamięci itp.), Przejrzystość jest najważniejsza.
Rob Craig,
To zależy od tego, do czego służy formuła. Spójrz na „Jawne jest lepsze niż niejawne”, może być tak, że podejście „najpierw sortowanie” jaśniej wyraża to, co robi program, lub jedno z pozostałych. Myślę, że nie możemy oceniać na podstawie pytania.
Thomas Ahle
101

Rozwiązanie trzech równości dla:

a in (b+c, b-c, c-b)
Alex Varga
źródło
4
Jedynym problemem są skutki uboczne. Jeśli b lub c są bardziej złożonymi wyrażeniami, zostaną uruchomione wiele razy.
Silvio Mayolo
3
@Kroltan Chodziło mi o to, że faktycznie odpowiedziałem na jego pytanie, w którym prosiłem o „bardziej zwartą” reprezentację. Zobacz: en.m.wikipedia.org/wiki/Short-circuit_evaluation
Alex Varga
24
Każdy, kto czyta ten kod, prawdopodobnie przeklnie cię za bycie „sprytnym”.
Karoly Horvath
5
@SilvioMayolo To samo dotyczy oryginału
Izkata
1
@AlexVarga, „Chodziło mi o to, że faktycznie odpowiedziałem na jego pytanie”. Zrobiłeś; używa o 30% mniej znaków (wstawia spacje między operatorami). Nie próbowałem powiedzieć, że twoja odpowiedź była błędna, tylko komentowałem, jak idiomatyczne (pytoniczne) jest. Niezła odpowiedź.
Paul Draper
54

Python ma anyfunkcję, która wykonuje operacje orna wszystkich elementach sekwencji. Tutaj przekonwertowałem twoje oświadczenie na krotkę 3-elementową.

any((a + b == c, a + c == b, b + c == a))

Zwróć uwagę, że orjest to zwarcie, więc jeśli obliczenie indywidualnych warunków jest kosztowne, może być lepiej zachować oryginalną konstrukcję.

Mark Okup
źródło
2
any()i all()zwarcie też.
TigerhawkT3
42
@ TigerhawkT3 Jednak nie w tym przypadku; trzy wyrażenia zostaną ocenione, zanim krotka istnieje, a krotka będzie istnieć anyjeszcze przed uruchomieniem.
poke
13
O, rozumiem. Myślę, że dzieje się tak tylko wtedy, gdy jest tam generator lub podobny leniwy iterator.
TigerhawkT3
4
anyi all„zewrzyj” proces sprawdzania iterowalności, którą otrzymają; ale jeśli ta iterowalna jest sekwencją, a nie generatorem, to została już w pełni oceniona przed wywołaniem funkcji .
Karl Knechtel,
Ma to tę zaletę, że łatwo jest podzielić na wiele wierszy (podwójne wcięcie argumentów any, pojedyncze wcięcie ):w ifinstrukcji), co bardzo pomaga w czytelności, gdy w
grę
40

Jeśli wiesz, że masz do czynienia tylko z liczbami dodatnimi, to zadziała i jest całkiem jasne:

a, b, c = sorted((a, b, c))
if a + b == c:
    do_stuff()

Jak powiedziałem, działa to tylko w przypadku liczb dodatnich; ale jeśli wiesz, że będą pozytywne, jest to bardzo czytelne rozwiązanie IMO, nawet bezpośrednio w kodzie, a nie w funkcji.

Mógłbyś to zrobić, co może wykonać trochę powtarzających się obliczeń; ale nie określiłeś skuteczności jako celu:

from itertools import permutations

if any(x + y == z for x, y, z in permutations((a, b, c), 3)):
    do_stuff()

Lub bez permutations()i możliwość wielokrotnych obliczeń:

if any(x + y == z for x, y, z in [(a, b, c), (a, c, b), (b, c, a)]:
    do_stuff()

Prawdopodobnie umieściłbym to lub jakiekolwiek inne rozwiązanie w funkcji. Następnie możesz po prostu czysto wywołać funkcję w swoim kodzie.

Osobiście, jeśli nie potrzebowałbym większej elastyczności od kodu, użyłbym tylko pierwszej metody w twoim pytaniu. To proste i wydajne. Nadal mógłbym umieścić to w funkcji:

def two_add_to_third(a, b, c):
    return a + b == c or a + c == b or b + c == a

if two_add_to_third(a, b, c):
    do_stuff()

To całkiem Pythonic i jest to prawdopodobnie najbardziej efektywny sposób na zrobienie tego (pomijając dodatkowe wywołanie funkcji); chociaż i tak nie powinieneś martwić się zbytnio o wydajność, chyba że faktycznie powoduje to problem.

Cyfaza
źródło
zwłaszcza jeśli możemy założyć, że a, b, c są nieujemne.
cphlewis
Uważam, że wyrażenie „nie zawsze działa” jest trochę mylące. Pierwsze rozwiązanie działa tylko wtedy, gdy wiesz na pewno, że twoje liczby są nieujemne. Na przykład z (a, b, c) = (-3, -2, -1) masz a + b! = C, ale b + c = a. Podobne przypadki z (-1, 1, 2) i (-2, -1, 1).
numer użytkownika
@usernumber, wiesz, zauważyłem to wcześniej; nie wiem, dlaczego tego nie naprawiłem.
Cyphase
Twoje najlepsze rozwiązanie nie działa dla dużej klasy wejść, podczas gdy sugestia OP działa dla wszystkich wejść. Dlaczego „nie działa” bardziej Pythonic niż „działa”?
Barry
3
Ooh, pstryk. „ Jeśli wiesz, że masz do czynienia tylko z liczbami dodatnimi , to zadziała i jest całkiem czyste”. Wszystkie inne działają dla dowolnych liczb, ale jeśli wiesz, że masz do czynienia tylko z liczbami dodatnimi , górna jest bardzo czytelna / Pythonic IMO.
Cyphase
17

Jeśli będziesz używać tylko trzech zmiennych, to Twoja metoda początkowa:

a + b == c or a + c == b or b + c == a

Jest już bardzo pytoniczny.

Jeśli planujesz używać większej liczby zmiennych, zastosuj metodę rozumowania z:

a + b + c in (2*a, 2*b, 2*c)

Jest bardzo sprytny, ale zastanówmy się, dlaczego. Dlaczego to działa?
Cóż, dzięki prostej arytmetyce widzimy, że:

a + b = c
c = c
a + b + c == c + c == 2*c
a + b + c == 2*c

I to będzie musiał uznać za prawdziwe dla A, B lub C, co oznacza, że tak będzie równa 2*a, 2*blub 2*c. Będzie to prawdą dla dowolnej liczby zmiennych.

Więc dobrym sposobem na szybkie napisanie tego byłoby po prostu sporządzenie listy swoich zmiennych i porównanie ich sumy z listą podwojonych wartości.

values = [a,b,c,d,e,...]
any(sum(values) in [2*x for x in values])

W ten sposób, aby dodać więcej zmiennych do równania, wszystko, co musisz zrobić, to edytować listę wartości za pomocą „n” nowych zmiennych, a nie pisać „n” równań

ThatGuyRussell
źródło
4
Co a=-1, b=-1, c=-2, a następnie a+b=c, ale a+b+c = -4i 2*max(a,b,c)to-2
Eric Renouf
Dziękuję, że to prawda, musiałbym użyć abs. Dokonywanie tej korekty teraz.
ThatGuyRussell
2
Po obsypaniu go pół tuzinem abs()wywołań, jest to Pythonic niż fragment OP (tak naprawdę nazwałbym go znacznie mniej czytelnym).
TigerhawkT3
To prawda, dostosuję to teraz
ThatGuyRussell
1
@ThatGuyRussell W celu zwarcia, chciałbyś użyć generatora ... coś takiego any(sum(values) == 2*x for x in values), w ten sposób nie musiałbyś robić całego podwajania z góry, tak jak jest to konieczne.
Barry
12

Poniższy kod może służyć do iteracyjnego porównywania każdego elementu z sumą pozostałych, która jest obliczana z sumy całej listy, z wyłączeniem tego elementu.

 l = [a,b,c]
 any(sum(l)-e == e for e in l)
Arcanum
źródło
2
Fajnie :) Myślę, że jeśli usuniesz []nawiasy z drugiej linii to nawet zwarcie jak oryginał z or...
psmears 19.08.15
1
co jest w zasadzie any(a + b + c == 2*x for x in [a, b, c])dość bliskie sugestii PO
njzk2 Sierpnia
To jest podobne, ale ta metoda rozciąga się na dowolną liczbę zmiennych. Uwzględniłem sugestię @psmears dotyczącą zwarcia.
Arcanum
10

Nie próbuj tego upraszczać. Zamiast tego nazwij to, co robisz za pomocą funkcji:

def any_two_sum_to_third(a, b, c):
  return a + b == c or a + c == b or b + c == a

if any_two_sum_to_third(foo, bar, baz):
  ...

Zastąpienie warunku czymś „sprytnym” może skrócić go, ale nie uczyni go bardziej czytelnym. Pozostawienie tego tak, jak jest, również nie jest zbyt czytelne, ponieważ trudno jest wiedzieć, dlaczego sprawdzasz te trzy warunki na pierwszy rzut oka. Dzięki temu jest absolutnie jasne, czego szukasz.

Jeśli chodzi o wydajność, to podejście dodaje narzut wywołania funkcji, ale nigdy nie poświęcaj czytelności dla wydajności, chyba że znalazłeś wąskie gardło, które absolutnie musisz naprawić. I zawsze mierz, ponieważ niektóre sprytne implementacje są w stanie zoptymalizować i wstawić niektóre wywołania funkcji w pewnych okolicznościach.

Jacek
źródło
1
Funkcje należy pisać tylko wtedy, gdy spodziewasz się użyć tego samego kodu w więcej niż jednym miejscu lub jeśli kod jest złożony. W pierwotnym pytaniu nie ma wzmianki o ponownym wykorzystaniu kodu, a pisanie funkcji dla pojedynczej linii kodu jest nie tylko przesadą, ale w rzeczywistości pogarsza czytelność.
Igor Levicki
5
Pochodząc ze szkoły rzeczy FP, prawie całkowicie się z tym nie zgadzam i stwierdzam, że dobrze nazwane jednowierszowe funkcje są jednymi z najlepszych narzędzi zwiększających czytelność, jakie kiedykolwiek znajdziesz. Utwórz funkcję za każdym razem, gdy kroki, które podejmujesz, aby coś zrobić, nie od razu wyjaśniają to, co robisz, ponieważ nazwa funkcji pozwala określić, co jest lepsze niż jakikolwiek komentarz.
Jack
Bez względu na to, jaką szkołę przywołujesz, źle jest ślepo przestrzegać zestawu reguł. Konieczność przeskoczenia do innej części źródła w celu odczytania tej jednej linii kodu ukrytej wewnątrz funkcji tylko po to, aby móc zweryfikować, czy faktycznie robi to, co mówi w nazwie, a następnie konieczność przełączenia się z powrotem do miejsca wywołania funkcji Upewnij się, że przekazujesz prawidłowe parametry, jest to całkowicie niepotrzebne przełączanie kontekstu. Moim zdaniem utrudnia to zarówno czytelność, jak i przepływ pracy. Wreszcie, ani nazwa funkcji, ani komentarze do kodu nie zastępują dokumentacji kodu.
Igor Levicki
9

Python 3:

(a+b+c)/2 in (a,b,c)
(a+b+c+d)/2 in (a,b,c,d)
...

Skaluje się do dowolnej liczby zmiennych:

arr = [a,b,c,d,...]
sum(arr)/2 in arr

Jednak generalnie zgadzam się, że jeśli nie masz więcej niż trzech zmiennych, oryginalna wersja jest bardziej czytelna.

Vitalii Fedorenko
źródło
3
Zwraca to nieprawidłowe wyniki dla niektórych danych wejściowych z powodu błędów zaokrąglania zmiennoprzecinkowego.
pkt
Należy unikać dzielenia ze względu na wydajność i dokładność.
Igor Levicki
1
@pts Czy żadna implementacja nie zwróci nieprawidłowych wyników z powodu zaokrąglania zmiennoprzecinkowego? Nawet a + b == c
osundblad
@osundblad: Jeśli a, b i c są liczbami int, to (a + b + c) / 2 zaokrągla (i może zwrócić nieprawidłowe wyniki), ale a + b == c jest dokładne.
pts
3
dzielenie przez 2 to po prostu zmniejszenie wykładnika o jeden, więc będzie dokładne dla każdej liczby całkowitej mniejszej niż 2 ^ 53 (część ułamkowa liczby zmiennoprzecinkowej w Pythonie), a dla większych liczb całkowitych można użyć dziesiętnych . Na przykład, aby sprawdzić liczby całkowite mniejsze niż 2 ^ 30, uruchom[x for x in range(pow(2,30)) if x != ((x * 2)/ pow(2,1))]
Vitalii Fedorenko
6
(a+b-c)*(a+c-b)*(b+c-a) == 0

Jeśli suma dowolnych dwóch składników jest równa trzeciemu składnikowi, to jeden z czynników będzie wynosił zero, co spowoduje, że cały iloczyn będzie równy zero.

mbeckish
źródło
Myślałem dokładnie o tym samym, ale nie mogę zaprzeczyć, że jego oryginalna propozycja jest o wiele czystsza ...
user541686
@Mehrdad - Zdecydowanie. Naprawdę nie różni się od(a+b<>c) && (a+c<>b) && (b+c<>a) == false
mbeckish
Po prostu mnożenie jest droższe niż wyrażenia logiczne i podstawowa arytmetyka.
Igor Levicki,
@IgorLevicki - Tak, chociaż jest to BARDZO przedwczesny problem optymalizacji. Czy będzie to wykonywane dziesiątki tysięcy razy na sekundę? Jeśli tak, to prawdopodobnie chciałbyś spojrzeć na coś innego.
mbeckish
@mbeckish - Dlaczego uważasz, że jest to przedwczesne? Kod powinien być napisany z myślą o optymalizacji, a nie jako refleksja. Pewnego dnia jakiś stażysta skopiuje ten fragment kodu i wklei go do jakiejś pętli krytycznej dla wydajności na wbudowanej platformie, która będzie następnie działać na milionach urządzeń, niekoniecznie spowolnionych, ale być może marnując więcej energii baterii. Pisanie takiego kodu tylko zachęca do złych praktyk kodowania. Moim zdaniem OP powinien zapytać, czy istnieje sposób optymalizacji tego wyrażenia logicznego.
Igor Levicki
6

Może po prostu:

a == b + c or abs(a) == abs(b - c)

Zauważ, że to nie zadziała, jeśli zmienne są bez znaku.

Z punktu widzenia optymalizacji kodu (przynajmniej na platformie x86) wydaje się to być najbardziej wydajnym rozwiązaniem.

Nowoczesne kompilatory wbudowują wywołania funkcji abs () i unikają testowania znaków i późniejszej gałęzi warunkowej, używając sprytnej sekwencji instrukcji CDQ, XOR i SUB . Powyższy kod wysokiego poziomu będzie zatem reprezentowany tylko za pomocą instrukcji ALU o małym opóźnieniu, dużej przepustowości i tylko dwóch instrukcji warunkowych.

Igor Levicki
źródło
I myślę, że fabs()można to wykorzystać do floattypów;).
shA.t
4

Rozwiązanie dostarczone przez Alexa Vargę „a in (b + c, bc, cb)” jest zwarte i matematycznie piękne, ale nie pisałbym w ten sposób kodu, ponieważ następny programista nie zrozumiałby od razu celu kodu .

Rozwiązanie Mark Ransom dla

any((a + b == c, a + c == b, b + c == a))

jest bardziej jasny, ale niewiele bardziej zwięzły niż

a + b == c or a + c == b or b + c == a

Pisząc kod, któremu ktoś inny będzie musiał przyjrzeć się, lub na który będę musiał przyjrzeć się długo później, kiedy zapomniałem, o czym myślałem, kiedy go pisałem, bycie zbyt krótkim lub sprytnym powoduje więcej szkody niż pożytku. Kod powinien być czytelny. Tak zwięzły jest dobry, ale nie tak zwięzły, żeby następny programista nie mógł tego zrozumieć.

Paul J Abernathy
źródło
Szczere pytanie: dlaczego ludzie zawsze zakładają, że następny programista będzie idiotą niezdolnym do czytania kodu? Osobiście uważam ten pomysł za obraźliwy. Jeśli kod musi być napisany tak, aby był rażąco oczywisty dla każdego programisty, oznacza to, że jako zawód dbamy o najniższy wspólny mianownik, najmniej wykwalifikowany spośród nas. Jeśli nadal będziemy to robić, w jaki sposób mogą poprawić swoje umiejętności osobiste? Nie widzę tego w innych zawodach. Kiedy ostatnio widziałeś kompozytora piszącego prostą partyturę muzyczną tylko po to, aby każdy muzyk mógł ją zagrać, niezależnie od poziomu umiejętności?
Igor Levicki
6
Problem polega na tym, że nawet programiści mają ograniczoną energię umysłową, więc czy chcesz poświęcić swoją ograniczoną energię psychiczną na algorytm i aspekty programu wyższego poziomu, czy też na zastanowienie się, co oznacza jakiś skomplikowany wiersz kodu, kiedy można go wyrazić w prostszy sposób ? Programowanie jest trudne, więc nie utrudniaj mu niepotrzebnie, tak jak biegacz olimpijski nie przebiegłby wyścigu z ciężkim plecakiem tylko dlatego, że może. Jak mówi Steve McConell w Code Complete 2, czytelność jest jednym z najważniejszych aspektów kodu.
Paul J Abernathy
2

Żądanie jest bardziej zwarte LUB bardziej pythonowe - próbowałem swoich sił w bardziej zwartym.

dany

import functools, itertools
f = functools.partial(itertools.permutations, r = 3)
def g(x,y,z):
    return x + y == z

To o 2 znaki mniej niż oryginał

any(g(*args) for args in f((a,b,c)))

test z:

assert any(g(*args) for args in f((a,b,c))) == (a + b == c or a + c == b or b + c == a)

dodatkowo podane:

h = functools.partial(itertools.starmap, g)

To jest równoważne

any(h(f((a,b,c))))
wwii
źródło
Cóż, jest o dwa znaki krótsze niż oryginał, ale nie ten, który dał OP zaraz potem, z którego, jak powiedział, obecnie korzysta. Oryginał zawiera również dużo białych znaków, które to pomija, gdy tylko jest to możliwe. Jest też mała kwestia funkcji, g()którą musisz zdefiniować, aby to zadziałało. Biorąc to wszystko pod uwagę, powiedziałbym, że jest znacznie większy.
TigerhawkT3
@ TigerhawkT3, zinterpretowałem to jako żądanie krótszego wyrażenia / wiersza. zobacz edycję dla dalszych ulepszeń .
wojna światowa
4
Bardzo złe nazwy funkcji, odpowiednie tylko dla kodu golfa.
0xc0de
@ 0xc0de - przepraszam, nie gram. Odpowiedni może być dość subiektywny i zależny od okoliczności - ale ograniczę się do społeczności.
wojna światowa
Nie rozumiem, jak to jest bardziej zwarte, gdy ma więcej znaków niż oryginalny kod.
Igor Levicki
1

Chcę przedstawić to, co uważam za najbardziej pytoniczną odpowiedź:

def one_number_is_the_sum_of_the_others(a, b, c):
    return any((a == b + c, b == a + c, c == a + b))

Ogólny przypadek, niezoptymalizowany:

def one_number_is_the_sum_of_the_others(numbers):
    for idx in range(len(numbers)):
        remaining_numbers = numbers[:]
        sum_candidate = remaining_numbers.pop(idx)
        if sum_candidate == sum(remaining_numbers):
            return True
    return False 

Jeśli chodzi o Zen Pythona, myślę, że podkreślone stwierdzenia są bardziej przestrzegane niż w przypadku innych odpowiedzi:

Zen Pythona - Tim Peters

Piękne jest lepsze niż brzydkie.
Jawne jest lepsze niż niejawne.
Proste jest lepsze niż złożone.
Złożone jest lepsze niż skomplikowane.
Płaskie jest lepsze niż zagnieżdżone.
Rzadkie jest lepsze niż gęste.
Liczy się czytelność.
Specjalne przypadki nie są na tyle wyjątkowe, aby łamać zasady.
Chociaż praktyczność przewyższa czystość.
Błędy nigdy nie powinny przejść bezgłośnie.
Chyba że wyraźnie uciszono.
W obliczu niejasności odrzuć pokusę zgadywania.
Powinien być jeden - a najlepiej tylko jeden - oczywisty sposób na zrobienie tego.
Chociaż na początku może to nie być oczywiste, chyba że jesteś Holendrem.
Teraz jest lepiej niż nigdy.
Chociaż nigdy nie jest często lepsze niżprawo teraz.
Jeśli implementacja jest trudna do wyjaśnienia, to zły pomysł.
Jeśli implementacja jest łatwa do wyjaśnienia, może to być dobry pomysł.
Przestrzenie nazw to świetny pomysł - zróbmy ich więcej!

Sevenforce
źródło
1

Zgodnie ze starym nawykiem mojego programowania, myślę, że umieszczanie złożonego wyrażenia po prawej stronie w klauzuli może uczynić ją bardziej czytelną w następujący sposób:

a == b+c or b == a+c or c == a+b

Plus ():

((a == b+c) or (b == a+c) or (c == a+b))

Myślę też, że używanie multilinii może wywołać więcej zmysłów, takich jak ten:

((a == b+c) or 
 (b == a+c) or 
 (c == a+b))
shA.t
źródło
0

W ogólny sposób

m = a+b-c;
if (m == 0 || m == 2*a || m == 2*b) do_stuff ();

jeśli manipulowanie zmienną wejściową jest dla Ciebie OK,

c = a+b-c;
if (c==0 || c == 2*a || c == 2*b) do_stuff ();

jeśli chcesz wykorzystać bit hacki, możesz użyć "!", ">> 1" i "<< 1"

Uniknąłem dzielenia, chociaż pozwala to na uniknięcie podwójnego mnożenia, aby uniknąć błędów zaokrągleń. Jednak sprawdź, czy nie ma przepełnień

Padmabushan
źródło
0
def any_sum_of_others (*nums):
    num_elements = len(nums)
    for i in range(num_elements):
        discriminating_map = map(lambda j: -1 if j == i else 1, range(num_elements))
        if sum(n * u for n, u in zip(nums, discriminating_map)) == 0:
            return True
    return False

print(any_sum_of_others(0, 0, 0)) # True
print(any_sum_of_others(1, 2, 3)) # True
print(any_sum_of_others(7, 12, 5)) # True
print(any_sum_of_others(4, 2, 2)) # True
print(any_sum_of_others(1, -1, 0)) # True
print(any_sum_of_others(9, 8, -4)) # False
print(any_sum_of_others(4, 3, 2)) # False
print(any_sum_of_others(1, 1, 1, 1, 4)) # True
print(any_sum_of_others(0)) # True
print(any_sum_of_others(1)) # False
Hammerite
źródło
Funkcje należy pisać tylko wtedy, gdy spodziewasz się użyć tego samego kodu w więcej niż jednym miejscu lub jeśli kod jest złożony. W pierwotnym pytaniu nie ma wzmianki o ponownym wykorzystaniu kodu, a pisanie funkcji dla pojedynczej linii kodu jest nie tylko przesadą, ale w rzeczywistości pogarsza czytelność.
Igor Levicki
Nie zgadzam się, że ogranicza to czytelność; jeśli wybierzesz odpowiednią nazwę, może to poprawić czytelność (ale nie przedstawiam jakości nazwy, którą wybrałem w tej odpowiedzi). Ponadto pomocne może być nadanie nazwy koncepcji, którą będziesz musiał wykonać, o ile będziesz zmuszony nadać dobre imię swojej funkcji. Funkcje są dobre. To, czy funkcjonalność jest wystarczająco złożona, aby skorzystać na jej zamknięciu w funkcji, jest subiektywnym osądem.
Hammerite