@wwii Sie schließen sich nicht gegenseitig aus. Siehe a = 0, b = 0, c = 0;)
Honza Brabec
1
Was @phresnel gesagt hat. Anstatt zu versuchen, den Ausdruck zu "vereinfachen", schließen Sie ihn in eine Funktion mit einem beschreibenden Namen ein.
Kopffüßer
Antworten:
206
Wenn wir uns das Zen von Python ansehen, betonen Sie meine:
Das Zen von Python, von Tim Peters
Schön ist besser als hässlich.
Explizit ist besser als implizit. Einfach ist besser als komplex.
Komplex ist besser als kompliziert.
Wohnung ist besser als verschachtelt.
Spärlich ist besser als dicht. Lesbarkeit zählt.
Sonderfälle sind nicht speziell genug, um gegen die Regeln zu verstoßen.
Obwohl Praktikabilität die Reinheit übertrifft.
Fehler sollten niemals stillschweigend vergehen.
Sofern nicht ausdrücklich zum Schweigen gebracht.
Verweigern Sie angesichts von Zweideutigkeiten die Versuchung zu raten. Es sollte einen - und vorzugsweise nur einen - offensichtlichen Weg geben, dies zu tun.
Obwohl dieser Weg zunächst vielleicht nicht offensichtlich ist, es sei denn, Sie sind Niederländer.
Jetzt ist besser als nie.
Obwohl nie oft besser ist alsgerade jetzt. Wenn die Implementierung schwer zu erklären ist, ist es eine schlechte Idee. Wenn die Implementierung leicht zu erklären ist, ist dies möglicherweise eine gute Idee.
Namespaces sind eine großartige Idee - lasst uns mehr davon machen!
Die pythonischste Lösung ist die, die am klarsten, einfachsten und am einfachsten zu erklären ist:
a + b == c or a + c == b or b + c == a
Noch besser ist, dass Sie Python nicht einmal kennen müssen, um diesen Code zu verstehen! Es ist das einfach. Dies ist vorbehaltlos die beste Lösung. Alles andere ist intellektuelle Masturbation.
Darüber hinaus ist dies wahrscheinlich auch die Lösung mit der besten Leistung, da es der einzige von allen Vorschlägen ist, der einen Kurzschluss verursacht. Wenn a + b == cnur eine einzige Addition und ein Vergleich durchgeführt werden.
Noch besser, werfen Sie einige Klammern ein, um die Absicht kristallklar zu machen.
Bryan Oakley
3
Die Absicht ist bereits ohne Klammern kristallklar. Klammern würden das Lesen erschweren - warum verwendet der Autor Klammern, wenn dies bereits Vorrang hat?
Miles Rout
1
Ein weiterer Hinweis zum Versuch, zu klug zu sein: Sie können unvorhergesehene Fehler einführen, indem Sie Bedingungen vermissen, die Sie nicht berücksichtigt haben. Mit anderen Worten, Sie denken vielleicht, dass Ihre neue kompakte Lösung gleichwertig ist, aber nicht in allen Fällen. Sofern es keinen zwingenden Grund gibt, anders zu codieren (Leistung, Speicherbeschränkungen usw.), ist Klarheit das A und O.
Rob Craig
Es hängt davon ab, wofür die Formel ist. Schauen Sie sich "Explizit ist besser als implizit" an. Möglicherweise drückt der Ansatz "Zuerst sortieren" klarer aus, was das Programm tut, oder einer der anderen. Ich glaube nicht, dass wir nach der Frage urteilen können.
Jeder, der diesen Code liest, wird Sie wahrscheinlich dafür verfluchen, "klug" zu sein.
Karoly Horvath
5
@ SilvioMayolo Das gleiche gilt für das Original
Izkata
1
@AlexVarga, "Mein Punkt war, dass ich seine Frage tatsächlich beantwortet habe". Du machtest; Es werden 30% weniger Zeichen verwendet (Leerzeichen zwischen Operatoren setzen). Ich habe nicht versucht zu sagen, dass Ihre Antwort falsch war, sondern nur kommentiert, wie idiomatisch (pythonisch) sie ist. Gute Antwort.
Paul Draper
54
Python hat eine anyFunktion, die oralle Elemente einer Sequenz ausführt. Hier habe ich Ihre Aussage in ein 3-Element-Tupel umgewandelt.
any((a + b == c, a + c == b, b + c == a))
Beachten Sie, dass dies ein orKurzschluss ist. Wenn die Berechnung der einzelnen Bedingungen teuer ist, ist es möglicherweise besser, das ursprüngliche Konstrukt beizubehalten.
@ TigerhawkT3 In diesem Fall allerdings nicht; Die drei Ausdrücke werden ausgewertet, bevor das Tupel existiert, und das Tupel wird existieren, bevor es anyüberhaupt ausgeführt wird.
Poke
13
Ah ich sehe. Ich denke, es ist nur, wenn es einen Generator oder einen ähnlichen faulen Iterator gibt.
TigerhawkT3
4
anyund all"Kurzschluss" des Prozesses der Prüfung der Iterierbarkeit, die sie erhalten; Wenn es sich bei dieser Iterierbarkeit jedoch eher um eine Sequenz als um einen Generator handelt, wurde sie bereits vollständig ausgewertet, bevor der Funktionsaufruf erfolgt .
Karl Knechtel
Dies hat den Vorteil , dass es einfach zu Split über mehrere Zeilen (Doppel-indent der Argumente any, Single-indent des ):in der ifErklärung), die viel zur besseren Lesbarkeit hilft , bei der Mathematik beteiligt ist
Izkata
40
Wenn Sie wissen, dass Sie nur mit positiven Zahlen zu tun haben, funktioniert dies und ist ziemlich sauber:
a, b, c = sorted((a, b, c))if a + b == c:
do_stuff()
Wie gesagt, das funktioniert nur bei positiven Zahlen; Aber wenn Sie wissen, dass sie positiv sein werden, ist dies eine sehr lesbare Lösung, IMO, sogar direkt im Code im Gegensatz zu einer Funktion.
Sie könnten dies tun, was einige wiederholte Berechnungen durchführen könnte; Sie haben jedoch keine Leistung als Ziel angegeben:
from itertools import permutations
if any(x + y == z for x, y, z in permutations((a, b, c),3)):
do_stuff()
Oder ohne permutations()und die Möglichkeit wiederholter Berechnungen:
if any(x + y == z for x, y, z in[(a, b, c),(a, c, b),(b, c, a)]:
do_stuff()
Ich würde diese oder eine andere Lösung wahrscheinlich in eine Funktion einfügen. Dann können Sie die Funktion in Ihrem Code einfach sauber aufrufen.
Persönlich würde ich nur die erste Methode in Ihrer Frage verwenden, es sei denn, ich benötige mehr Flexibilität für den Code. Es ist einfach und effizient. Ich könnte es immer noch in eine Funktion setzen:
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()
Das ist ziemlich pythonisch und wahrscheinlich der effizienteste Weg, dies zu tun (der zusätzliche Funktionsaufruf beiseite); Sie sollten sich jedoch sowieso nicht zu viele Sorgen um die Leistung machen, es sei denn, dies verursacht tatsächlich ein Problem.
besonders wenn wir annehmen können, dass a, b, c alle nicht negativ sind.
Cphlewis
Ich finde den Satz "funktioniert nicht immer" etwas verwirrend. Die erste Lösung funktioniert nur, wenn Sie sicher sind, dass Ihre Zahlen nicht negativ sind. Zum Beispiel mit (a, b, c) = (-3, -2, -1) haben Sie a + b! = C, aber b + c = a. Ähnliche Fälle mit (-1, 1, 2) und (-2, -1, 1).
Benutzernummer
@usernumber, weißt du, das habe ich früher bemerkt; Ich bin mir nicht sicher, warum ich es nicht repariert habe.
Cyphase
Ihre Top-Lösung funktioniert nicht für eine große Klasse von Eingaben, während der Vorschlag des OP für alle Eingaben funktioniert. Wie ist "nicht arbeiten" mehr pythonisch als "arbeiten"?
Barry
3
Ooh, schnapp. " Wenn Sie wissen, dass Sie nur mit positiven Zahlen zu tun haben , funktioniert dies und ist ziemlich sauber." Alle anderen arbeiten für beliebige Zahlen, aber wenn Sie wissen, dass Sie nur mit positiven Zahlen zu tun haben , ist die oberste sehr gut lesbar / Pythonic IMO.
Cyphase
17
Wenn Sie nur drei Variablen verwenden, dann Ihre ursprüngliche Methode:
a + b == c or a + c == b or b + c == a
Ist schon sehr pythonisch.
Wenn Sie vorhaben, mehr Variablen zu verwenden, können Sie folgendermaßen argumentieren:
a + b + c in(2*a,2*b,2*c)
Ist sehr klug, aber lassen Sie uns darüber nachdenken, warum. Warum funktioniert das?
Nun, durch eine einfache Arithmetik sehen wir Folgendes:
a + b = c
c = c
a + b + c == c + c ==2*c
a + b + c ==2*c
Und dies muss entweder für a, b oder c gelten, was bedeutet, dass es ja gleich 2*aist 2*b, oder 2*c. Dies gilt für eine beliebige Anzahl von Variablen.
Eine gute Möglichkeit, dies schnell zu schreiben, besteht darin, einfach eine Liste Ihrer Variablen zu erstellen und deren Summe mit einer Liste der doppelten Werte zu vergleichen.
values =[a,b,c,d,e,...]
any(sum(values)in[2*x for x in values])
Um der Gleichung weitere Variablen hinzuzufügen, müssen Sie lediglich Ihre Werteliste mit 'n' neuen Variablen bearbeiten und nicht 'n' Gleichungen schreiben
Was ist a=-1, b=-1, c=-2, dann a+b=caber a+b+c = -4und 2*max(a,b,c)ist-2
Eric Renouf
Danke das stimmt, ich müsste abs benutzen. Nehmen Sie diese Einstellung jetzt vor.
ThatGuyRussell
2
Nach einem halben Dutzend abs()Aufrufen ist es Pythonic als das OP-Snippet (ich würde es tatsächlich als deutlich weniger lesbar bezeichnen).
TigerhawkT3
Das ist sehr wahr, ich werde das jetzt anpassen
ThatGuyRussell
1
@ThatGuyRussell Um einen Kurzschluss zu verursachen, möchten Sie einen Generator verwenden ... so etwas any(sum(values) == 2*x for x in values)müssten Sie nicht das ganze Verdoppeln im Voraus durchführen, genauso wie nötig.
Barry
12
Der folgende Code kann verwendet werden, um jedes Element iterativ mit der Summe der anderen zu vergleichen, die aus der Summe der gesamten Liste ohne dieses Element berechnet wird.
Schön :) Ich denke, wenn Sie die []Klammern aus der zweiten Zeile entfernen , wird dies sogar wie das Original mit or...
psmears
1
Das ist im Grunde any(a + b + c == 2*x for x in [a, b, c])ziemlich nah an dem Vorschlag des OP
njzk2
Das ist ähnlich, jedoch erstreckt sich diese Methode auf eine beliebige Anzahl von Variablen. Ich habe den Vorschlag von @psmears zum Kurzschließen aufgenommen.
Arcanum
10
Versuchen Sie nicht, es zu vereinfachen. Stattdessen nennen , was Sie mit einer Funktion tun:
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):...
Wenn Sie die Bedingung durch etwas "Kluges" ersetzen, wird sie möglicherweise kürzer, aber nicht lesbarer. Es zu belassen, wie es ist, ist jedoch auch nicht sehr lesbar, da es schwierig ist zu wissen, warum Sie diese drei Bedingungen auf einen Blick überprüfen. Dies macht absolut klar, wonach Sie suchen.
In Bezug auf die Leistung erhöht dieser Ansatz zwar den Overhead eines Funktionsaufrufs, beeinträchtigt jedoch niemals die Lesbarkeit für die Leistung, es sei denn, Sie haben einen Engpass gefunden, den Sie unbedingt beheben müssen. Und messen Sie immer, da einige clevere Implementierungen unter bestimmten Umständen einige Funktionsaufrufe optimieren und einbinden können.
Funktionen sollten nur geschrieben werden, wenn Sie erwarten, denselben Code an mehr als einer Stelle zu verwenden, oder wenn der Code komplex ist. In der ursprünglichen Frage wird die Wiederverwendung von Code nicht erwähnt, und das Schreiben einer Funktion für eine einzelne Codezeile ist nicht nur übertrieben, sondern beeinträchtigt auch die Lesbarkeit.
Igor Levicki
5
Ich komme aus der FP-Schule der Dinge und muss so ziemlich völlig anderer Meinung sein und feststellen, dass gut benannte einzeilige Funktionen einige der besten Werkzeuge sind, um die Lesbarkeit zu verbessern, die Sie jemals finden werden. Machen Sie eine Funktion , wenn die Schritte Sie nehmen etwas zu tun , nicht sofort Klarheit bringen, was Sie tun, wie der Name der Funktion , die Sie die angeben können , was besser als jeder Kommentar konnte.
Jack
Unabhängig davon, welche Schule Sie anrufen, ist es schlecht, sich blind an ein Regelwerk zu halten. Sie müssen zu einem anderen Teil der Quelle springen, um diese eine Codezeile zu lesen, die in einer Funktion versteckt ist, um zu überprüfen, ob sie tatsächlich das tut, was im Namen steht, und dann zum Ort eines Aufrufs zurückkehren Stellen Sie sicher, dass Sie die richtigen Parameter übergeben. Dies ist eine völlig unnötige Kontextumschaltung. Meiner Meinung nach beeinträchtigt dies sowohl die Lesbarkeit als auch den Workflow. Schließlich sind weder der Name einer Funktion noch die Codekommentare ein angemessener Ersatz für die Codedokumentation.
Igor Levicki
9
Python 3:
(a+b+c)/2in(a,b,c)(a+b+c+d)/2in(a,b,c,d)...
Es lässt sich auf eine beliebige Anzahl von Variablen skalieren:
arr =[a,b,c,d,...]
sum(arr)/2in arr
Im Allgemeinen stimme ich jedoch zu, dass die Originalversion besser lesbar ist, wenn Sie nicht mehr als drei Variablen haben.
Dies gibt für einige Eingaben aufgrund von Gleitkomma-Rundungsfehlern falsche Ergebnisse zurück.
Punkte
Eine Teilung sollte aus Gründen der Leistung und Genauigkeit vermieden werden.
Igor Levicki
1
@pts Gibt keine Implementierung aufgrund von Gleitkomma-Rundungen falsche Ergebnisse zurück? Sogar a + b == c
osundblad
@osundblad: Wenn a, b und c Ints sind, rundet (a + b + c) / 2 (und liefert möglicherweise falsche Ergebnisse), aber a + b == c ist genau.
Punkte
3
Durch Division durch 2 wird der Exponent einfach um eins verringert, sodass er für jede Ganzzahl, die kleiner als 2 ^ 53 ist (der Bruchteil eines Gleitkommas in Python), genau ist. Für größere Ganzzahlen können Sie Dezimalzahlen verwenden . Zum Beispiel, um ganze Zahlen zu überprüfen, die kleiner als 2 ^ 30 sind[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
Wenn die Summe von zwei beliebigen Begriffen gleich dem dritten Begriff ist, ist einer der Faktoren Null, wodurch das gesamte Produkt Null wird.
Ich habe genau das Gleiche gedacht, aber ich kann nicht leugnen, dass sein ursprünglicher Vorschlag viel sauberer ist ...
user541686
@Mehrdad - Auf jeden Fall. Es ist wirklich nicht anders als(a+b<>c) && (a+c<>b) && (b+c<>a) == false
mbeckish
Es ist nur so, dass die Multiplikation teurer ist als die logischen Ausdrücke und die Grundrechenarten.
Igor Levicki
@IgorLevicki - Ja, obwohl dies ein SEHR vorzeitiges Optimierungsproblem ist. Wird dies zehntausende Male pro Sekunde durchgeführt? Wenn ja, dann möchten Sie sich wahrscheinlich etwas anderes ansehen.
mbeckish
@mbeckish - Warum denkst du, ist es verfrüht? Code sollte unter Berücksichtigung der Optimierung geschrieben und nicht nachträglich optimiert werden. Eines Tages wird ein Praktikant dieses Code-Snippet kopieren und es in eine leistungskritische Schleife auf einer eingebetteten Plattform einfügen, die dann auf Millionen von Geräten ausgeführt wird, die nicht unbedingt langsam sind, aber möglicherweise mehr Batteriestrom verschwenden. Das Schreiben eines solchen Codes fördert nur schlechte Codierungspraktiken. Meiner Meinung nach hätte OP fragen sollen, ob es einen Weg gibt, diesen logischen Ausdruck zu optimieren.
Igor Levicki
6
Wie wäre es einfach:
a == b + c or abs(a)== abs(b - c)
Beachten Sie, dass dies nicht funktioniert, wenn Variablen ohne Vorzeichen sind.
Unter dem Gesichtspunkt der Codeoptimierung (zumindest auf der x86-Plattform) scheint dies die effizienteste Lösung zu sein.
Moderne Compiler integrieren beide abs () - Funktionsaufrufe und vermeiden Vorzeichentests und nachfolgende bedingte Verzweigungen, indem sie eine clevere Folge von CDQ-, XOR- und SUB-Anweisungen verwenden . Der obige High-Level-Code wird daher nur mit ALU-Befehlen mit geringer Latenz, hohem Durchsatz und nur zwei Bedingungen dargestellt.
Und ich denke fabs()kann für floatTypen verwendet werden;).
shA.t
4
Die von Alex Varga "a in (b + c, bc, cb)" bereitgestellte Lösung ist kompakt und mathematisch schön, aber ich würde Code nicht so schreiben, weil der nächste Entwickler den Zweck des Codes nicht sofort verstehen würde .
Mark Ransoms Lösung von
any((a + b == c, a + c == b, b + c == a))
ist klarer, aber nicht viel prägnanter als
a + b == c or a + c == b or b + c == a
Wenn ich Code schreibe, den jemand anderes anschauen muss oder den ich lange später anschauen muss, wenn ich vergessen habe, was ich beim Schreiben gedacht habe, kann es mehr schaden als nützen, zu kurz oder klug zu sein. Code sollte lesbar sein. So prägnant ist gut, aber nicht so prägnant, dass der nächste Programmierer es nicht verstehen kann.
Ehrliche Frage: Warum gehen die Leute immer davon aus, dass der nächste Programmierer ein Idiot sein wird, der nicht in der Lage ist, Code zu lesen? Ich persönlich finde diese Idee beleidigend. Wenn Code so geschrieben werden muss, dass er für jeden Programmierer offensichtlich ist, bedeutet dies, dass wir als Beruf den kleinsten gemeinsamen Nenner haben, den am wenigsten qualifizierten unter uns. Wenn wir das weiter machen, wie werden sie jemals ihre persönlichen Fähigkeiten verbessern? Ich sehe das nicht in anderen Berufen. Wann haben Sie das letzte Mal einen Komponisten gesehen, der eine einfache Musikpartitur geschrieben hat, damit jeder Musiker sie spielen kann, unabhängig von seinem Können?
Igor Levicki
6
Das Problem ist, dass selbst Programmierer nur eine begrenzte mentale Energie haben. Sie möchten also Ihre begrenzte mentale Energie für den Algorithmus und übergeordnete Aspekte des Programms verwenden oder herausfinden, was eine komplizierte Codezeile bedeutet, wenn sie einfacher ausgedrückt werden kann ? Das Programmieren ist schwierig, machen Sie es sich also nicht unnötig schwerer, so wie ein olympischer Läufer kein Rennen mit einem schweren Rucksack fahren würde, nur weil er es kann. Wie Steve McConell in Code Complete 2 sagt, ist die Lesbarkeit einer der wichtigsten Aspekte des Codes.
Paul J Abernathy
2
Die Anfrage ist kompakter ODER pythonischer - ich habe mich an kompakter versucht.
gegeben
import functools, itertools
f = functools.partial(itertools.permutations, r =3)def g(x,y,z):return x + y == z
Dies sind 2 Zeichen weniger als das Original
any(g(*args)for args in f((a,b,c)))
Test mit:
assert any(g(*args)for args in f((a,b,c)))==(a + b == c or a + c == b or b + c == a)
Nun, es sind zwei Zeichen kürzer als das Original, aber nicht das, das das OP direkt danach gegeben hat, was er derzeit verwendet. Das Original enthält auch viele Leerzeichen, die nach Möglichkeit weggelassen werden. Es gibt auch die kleine Sache der Funktion, die g()Sie definieren müssen, damit dies funktioniert. Angesichts all dessen würde ich sagen, dass es bedeutend größer ist.
TigerhawkT3
@ TigerhawkT3, ich habe es als Anfrage für einen kürzeren Ausdruck / eine kürzere Zeile interpretiert. Weitere Informationen finden Sie unter Bearbeiten .
wwii
4
Sehr schlechte Funktionsnamen, nur für einen Code Golf geeignet.
0xc0de
@ 0xc0de - Entschuldigung, ich spiele nicht. Geeignet kann ziemlich subjektiv sein und von den Umständen abhängen - aber ich werde mich der Community widersetzen.
wwii
Ich sehe nicht, wie kompakter das ist, wenn es mehr Zeichen als der ursprüngliche Code hat.
Igor Levicki
1
Ich möchte das präsentieren, was ich als die pythonischste Antwort sehe :
def one_number_is_the_sum_of_the_others(a, b, c):return any((a == b + c, b == a + c, c == a + b))
In Bezug auf das Zen von Python denke ich, dass die hervorgehobenen Aussagen mehr befolgt werden als aus anderen Antworten:
Das Zen von Python, von Tim Peters
Schön ist besser als hässlich. Explizit ist besser als implizit. Einfach ist besser als komplex.
Komplex ist besser als kompliziert.
Wohnung ist besser als verschachtelt.
Spärlich ist besser als dicht. Lesbarkeit zählt.
Sonderfälle sind nicht speziell genug, um gegen die Regeln zu verstoßen.
Obwohl Praktikabilität die Reinheit übertrifft.
Fehler sollten niemals stillschweigend vergehen.
Sofern nicht ausdrücklich zum Schweigen gebracht.
Verweigern Sie angesichts von Zweideutigkeiten die Versuchung zu raten.
Es sollte einen - und vorzugsweise nur einen - offensichtlichen Weg geben, dies zu tun.
Obwohl dieser Weg zunächst vielleicht nicht offensichtlich ist, es sei denn, Sie sind Niederländer.
Jetzt ist besser als nie.
Obwohl nie oft besser ist alsgerade jetzt.
Wenn die Implementierung schwer zu erklären ist, ist es eine schlechte Idee.
Wenn die Implementierung leicht zu erklären ist, ist dies möglicherweise eine gute Idee.
Namespaces sind eine großartige Idee - lasst uns mehr davon machen!
Als alte Gewohnheit meiner Programmierung denke ich, dass das Platzieren eines komplexen Ausdrucks in einer Klausel die Lesbarkeit folgendermaßen verbessern kann:
a == b+c or b == a+c or c == a+b
Plus ():
((a == b+c)or(b == a+c)or(c == a+b))
Und ich denke auch, dass die Verwendung von Mehrfachzeilen mehr Sinne wie diese ergeben kann:
m = a+b-c;if(m ==0|| m ==2*a || m ==2*b) do_stuff ();
Wenn das Bearbeiten einer Eingabevariablen für Sie in Ordnung ist,
c = a+b-c;if(c==0|| c ==2*a || c ==2*b) do_stuff ();
Wenn Sie mit Bit-Hacks ausnutzen möchten, können Sie "!", ">> 1" und "<< 1" verwenden.
Ich habe die Division vermieden, obwohl dadurch zwei Multiplikationen vermieden werden können, um Rundungsfehler zu vermeiden. Überprüfen Sie jedoch, ob Überläufe vorliegen
def any_sum_of_others (*nums):
num_elements = len(nums)for i in range(num_elements):
discriminating_map = map(lambda j:-1if j == i else1, range(num_elements))if sum(n * u for n, u in zip(nums, discriminating_map))==0:returnTruereturnFalseprint(any_sum_of_others(0,0,0))# Trueprint(any_sum_of_others(1,2,3))# Trueprint(any_sum_of_others(7,12,5))# Trueprint(any_sum_of_others(4,2,2))# Trueprint(any_sum_of_others(1,-1,0))# Trueprint(any_sum_of_others(9,8,-4))# Falseprint(any_sum_of_others(4,3,2))# Falseprint(any_sum_of_others(1,1,1,1,4))# Trueprint(any_sum_of_others(0))# Trueprint(any_sum_of_others(1))# False
Funktionen sollten nur geschrieben werden, wenn Sie erwarten, denselben Code an mehr als einer Stelle zu verwenden, oder wenn der Code komplex ist. In der ursprünglichen Frage wird die Wiederverwendung von Code nicht erwähnt, und das Schreiben einer Funktion für eine einzelne Codezeile ist nicht nur übertrieben, sondern beeinträchtigt auch die Lesbarkeit.
Igor Levicki
Ich bin nicht der Meinung, dass dies die Lesbarkeit beeinträchtigt. Wenn Sie einen geeigneten Namen wählen, kann dies die Lesbarkeit verbessern (ich mache jedoch keine Angaben zur Qualität des Namens, den ich in dieser Antwort gewählt habe). Darüber hinaus kann es hilfreich sein, einem Konzept einen Namen zu geben, was Sie tun müssen, solange Sie sich zwingen, Ihrer Funktion einen guten Namen zu geben. Funktionen sind gut. Ob die Funktionalität komplex genug ist, um von der Einkapselung in eine Funktion zu profitieren, ist eine subjektive Beurteilung.
Antworten:
Wenn wir uns das Zen von Python ansehen, betonen Sie meine:
Die pythonischste Lösung ist die, die am klarsten, einfachsten und am einfachsten zu erklären ist:
Noch besser ist, dass Sie Python nicht einmal kennen müssen, um diesen Code zu verstehen! Es ist das einfach. Dies ist vorbehaltlos die beste Lösung. Alles andere ist intellektuelle Masturbation.
Darüber hinaus ist dies wahrscheinlich auch die Lösung mit der besten Leistung, da es der einzige von allen Vorschlägen ist, der einen Kurzschluss verursacht. Wenn
a + b == c
nur eine einzige Addition und ein Vergleich durchgeführt werden.quelle
Lösen der drei Gleichungen für a:
quelle
Python hat eine
any
Funktion, dieor
alle Elemente einer Sequenz ausführt. Hier habe ich Ihre Aussage in ein 3-Element-Tupel umgewandelt.Beachten Sie, dass dies ein
or
Kurzschluss ist. Wenn die Berechnung der einzelnen Bedingungen teuer ist, ist es möglicherweise besser, das ursprüngliche Konstrukt beizubehalten.quelle
any()
undall()
Kurzschluss auch.any
überhaupt ausgeführt wird.any
undall
"Kurzschluss" des Prozesses der Prüfung der Iterierbarkeit, die sie erhalten; Wenn es sich bei dieser Iterierbarkeit jedoch eher um eine Sequenz als um einen Generator handelt, wurde sie bereits vollständig ausgewertet, bevor der Funktionsaufruf erfolgt .any
, Single-indent des):
in derif
Erklärung), die viel zur besseren Lesbarkeit hilft , bei der Mathematik beteiligt istWenn Sie wissen, dass Sie nur mit positiven Zahlen zu tun haben, funktioniert dies und ist ziemlich sauber:
Wie gesagt, das funktioniert nur bei positiven Zahlen; Aber wenn Sie wissen, dass sie positiv sein werden, ist dies eine sehr lesbare Lösung, IMO, sogar direkt im Code im Gegensatz zu einer Funktion.
Sie könnten dies tun, was einige wiederholte Berechnungen durchführen könnte; Sie haben jedoch keine Leistung als Ziel angegeben:
Oder ohne
permutations()
und die Möglichkeit wiederholter Berechnungen:Ich würde diese oder eine andere Lösung wahrscheinlich in eine Funktion einfügen. Dann können Sie die Funktion in Ihrem Code einfach sauber aufrufen.
Persönlich würde ich nur die erste Methode in Ihrer Frage verwenden, es sei denn, ich benötige mehr Flexibilität für den Code. Es ist einfach und effizient. Ich könnte es immer noch in eine Funktion setzen:
Das ist ziemlich pythonisch und wahrscheinlich der effizienteste Weg, dies zu tun (der zusätzliche Funktionsaufruf beiseite); Sie sollten sich jedoch sowieso nicht zu viele Sorgen um die Leistung machen, es sei denn, dies verursacht tatsächlich ein Problem.
quelle
Wenn Sie nur drei Variablen verwenden, dann Ihre ursprüngliche Methode:
Ist schon sehr pythonisch.
Wenn Sie vorhaben, mehr Variablen zu verwenden, können Sie folgendermaßen argumentieren:
Ist sehr klug, aber lassen Sie uns darüber nachdenken, warum. Warum funktioniert das?
Nun, durch eine einfache Arithmetik sehen wir Folgendes:
Und dies muss entweder für a, b oder c gelten, was bedeutet, dass es ja gleich
2*a
ist2*b
, oder2*c
. Dies gilt für eine beliebige Anzahl von Variablen.Eine gute Möglichkeit, dies schnell zu schreiben, besteht darin, einfach eine Liste Ihrer Variablen zu erstellen und deren Summe mit einer Liste der doppelten Werte zu vergleichen.
Um der Gleichung weitere Variablen hinzuzufügen, müssen Sie lediglich Ihre Werteliste mit 'n' neuen Variablen bearbeiten und nicht 'n' Gleichungen schreiben
quelle
a=-1
,b=-1
,c=-2
, danna+b=c
abera+b+c = -4
und2*max(a,b,c)
ist-2
abs()
Aufrufen ist es Pythonic als das OP-Snippet (ich würde es tatsächlich als deutlich weniger lesbar bezeichnen).any(sum(values) == 2*x for x in values)
müssten Sie nicht das ganze Verdoppeln im Voraus durchführen, genauso wie nötig.Der folgende Code kann verwendet werden, um jedes Element iterativ mit der Summe der anderen zu vergleichen, die aus der Summe der gesamten Liste ohne dieses Element berechnet wird.
quelle
[]
Klammern aus der zweiten Zeile entfernen , wird dies sogar wie das Original mitor
...any(a + b + c == 2*x for x in [a, b, c])
ziemlich nah an dem Vorschlag des OPVersuchen Sie nicht, es zu vereinfachen. Stattdessen nennen , was Sie mit einer Funktion tun:
Wenn Sie die Bedingung durch etwas "Kluges" ersetzen, wird sie möglicherweise kürzer, aber nicht lesbarer. Es zu belassen, wie es ist, ist jedoch auch nicht sehr lesbar, da es schwierig ist zu wissen, warum Sie diese drei Bedingungen auf einen Blick überprüfen. Dies macht absolut klar, wonach Sie suchen.
In Bezug auf die Leistung erhöht dieser Ansatz zwar den Overhead eines Funktionsaufrufs, beeinträchtigt jedoch niemals die Lesbarkeit für die Leistung, es sei denn, Sie haben einen Engpass gefunden, den Sie unbedingt beheben müssen. Und messen Sie immer, da einige clevere Implementierungen unter bestimmten Umständen einige Funktionsaufrufe optimieren und einbinden können.
quelle
Python 3:
Es lässt sich auf eine beliebige Anzahl von Variablen skalieren:
Im Allgemeinen stimme ich jedoch zu, dass die Originalversion besser lesbar ist, wenn Sie nicht mehr als drei Variablen haben.
quelle
[x for x in range(pow(2,30)) if x != ((x * 2)/ pow(2,1))]
Wenn die Summe von zwei beliebigen Begriffen gleich dem dritten Begriff ist, ist einer der Faktoren Null, wodurch das gesamte Produkt Null wird.
quelle
(a+b<>c) && (a+c<>b) && (b+c<>a) == false
Wie wäre es einfach:
Beachten Sie, dass dies nicht funktioniert, wenn Variablen ohne Vorzeichen sind.
Unter dem Gesichtspunkt der Codeoptimierung (zumindest auf der x86-Plattform) scheint dies die effizienteste Lösung zu sein.
Moderne Compiler integrieren beide abs () - Funktionsaufrufe und vermeiden Vorzeichentests und nachfolgende bedingte Verzweigungen, indem sie eine clevere Folge von CDQ-, XOR- und SUB-Anweisungen verwenden . Der obige High-Level-Code wird daher nur mit ALU-Befehlen mit geringer Latenz, hohem Durchsatz und nur zwei Bedingungen dargestellt.
quelle
fabs()
kann fürfloat
Typen verwendet werden;).Die von Alex Varga "a in (b + c, bc, cb)" bereitgestellte Lösung ist kompakt und mathematisch schön, aber ich würde Code nicht so schreiben, weil der nächste Entwickler den Zweck des Codes nicht sofort verstehen würde .
Mark Ransoms Lösung von
ist klarer, aber nicht viel prägnanter als
Wenn ich Code schreibe, den jemand anderes anschauen muss oder den ich lange später anschauen muss, wenn ich vergessen habe, was ich beim Schreiben gedacht habe, kann es mehr schaden als nützen, zu kurz oder klug zu sein. Code sollte lesbar sein. So prägnant ist gut, aber nicht so prägnant, dass der nächste Programmierer es nicht verstehen kann.
quelle
Die Anfrage ist kompakter ODER pythonischer - ich habe mich an kompakter versucht.
gegeben
Dies sind 2 Zeichen weniger als das Original
Test mit:
zusätzlich gegeben:
Das ist gleichwertig
quelle
g()
Sie definieren müssen, damit dies funktioniert. Angesichts all dessen würde ich sagen, dass es bedeutend größer ist.Ich möchte das präsentieren, was ich als die pythonischste Antwort sehe :
Der allgemeine Fall, nicht optimiert:
In Bezug auf das Zen von Python denke ich, dass die hervorgehobenen Aussagen mehr befolgt werden als aus anderen Antworten:
quelle
Als alte Gewohnheit meiner Programmierung denke ich, dass das Platzieren eines komplexen Ausdrucks in einer Klausel die Lesbarkeit folgendermaßen verbessern kann:
Plus
()
:Und ich denke auch, dass die Verwendung von Mehrfachzeilen mehr Sinne wie diese ergeben kann:
quelle
Im Allgemeinen
Wenn das Bearbeiten einer Eingabevariablen für Sie in Ordnung ist,
Wenn Sie mit Bit-Hacks ausnutzen möchten, können Sie "!", ">> 1" und "<< 1" verwenden.
Ich habe die Division vermieden, obwohl dadurch zwei Multiplikationen vermieden werden können, um Rundungsfehler zu vermeiden. Überprüfen Sie jedoch, ob Überläufe vorliegen
quelle
quelle