@wwii Ils ne s'excluent pas mutuellement. Voir a = 0, b = 0, c = 0;)
Honza Brabec
1
Ce que @phresnel a dit. Au lieu d'essayer de «simplifier» l'expression, enveloppez-la dans une fonction avec un nom descriptif.
Céphalopode
Réponses:
206
Si nous regardons le Zen de Python, soulignons le mien:
Le Zen de Python, par Tim Peters
Beau est mieux que laid.
L'explicite vaut mieux que l'implicite. Le simple vaut mieux que le complexe.
Complexe vaut mieux que compliqué.
Plat vaut mieux que niché.
Clairsemé vaut mieux que dense. La lisibilité compte.
Les cas spéciaux ne sont pas assez spéciaux pour enfreindre les règles.
Bien que l'aspect pratique l'emporte sur la pureté.
Les erreurs ne devraient jamais passer silencieusement.
À moins d'être explicitement réduit au silence.
Face à l'ambiguïté, refusez la tentation de deviner. Il devrait y avoir une - et de préférence une seule - façon évidente de le faire.
Bien que cette manière ne soit pas évidente au début, sauf si vous êtes néerlandais.
C'est mieux que jamais.
Bien que jamais ne soit souvent mieux quedès maintenant. Si l'implémentation est difficile à expliquer, c'est une mauvaise idée. Si la mise en œuvre est facile à expliquer, cela peut être une bonne idée.
Les espaces de noms sont une excellente idée - faisons-en plus!
La solution la plus pythonique est celle qui est la plus claire, la plus simple et la plus facile à expliquer:
a + b == c or a + c == b or b + c == a
Mieux encore, vous n'avez même pas besoin de connaître Python pour comprendre ce code! C'est aussi simple que ça . C'est, sans réserve, la meilleure solution. Tout le reste est de la masturbation intellectuelle.
De plus, il s'agit probablement de la solution la plus performante, car c'est la seule parmi toutes les propositions qui court-circuite. Si a + b == c, une seule addition et comparaison est effectuée.
Mieux encore, ajoutez des parenthèses pour rendre l'intention claire.
Bryan Oakley
3
L'intention est déjà claire sans parenthèses. Les parenthèses rendraient la lecture plus difficile - pourquoi l'auteur utilise-t-il des parenthèses alors que la priorité couvre déjà cela?
Miles Rout
1
Une autre remarque sur le fait d'essayer d'être trop intelligent: vous pouvez introduire des bogues imprévus en manquant des conditions que vous n'avez pas prises en compte. En d'autres termes, vous pensez peut-être que votre nouvelle solution compacte est équivalente, mais ce n'est pas le cas dans tous les cas. À moins qu'il n'y ait une raison impérieuse de coder autrement (performances, contraintes de mémoire, etc.), la clarté est reine.
Rob Craig
Cela dépend de ce à quoi sert la formule. Regardez «Explicite vaut mieux qu'implicite», il se peut que l'approche «trier d'abord» exprime plus clairement ce que fait le programme, ou l'un des autres. Je ne pense pas que nous puissions juger à partir de la question.
Quiconque lit ce code vous maudira probablement d'être "intelligent".
Karoly Horvath
5
@SilvioMayolo La même chose est vraie de l'original
Izkata
1
@AlexVarga, "Ce que je voulais dire, c'est que j'ai répondu à sa question". Tu l'as fait; il utilise 30% de caractères en moins (mettant des espaces entre les opérateurs). Je n'essayais pas de dire que votre réponse était fausse, mais simplement de commenter à quel point elle est idiomatique (pythonique). Bonne réponse.
Paul Draper
54
Python a une anyfonction qui fait un orsur tous les éléments d'une séquence. Ici, j'ai converti votre déclaration en un tuple à 3 éléments.
any((a + b == c, a + c == b, b + c == a))
Notez qu'il ors'agit d'un court-circuit, donc si le calcul des conditions individuelles est coûteux, il peut être préférable de conserver votre conception d'origine.
@ TigerhawkT3 Pas dans ce cas cependant; les trois expressions seront évaluées avant que le tuple n'existe, et le tuple existera avant anymême de s'exécuter.
poke
13
Ah, je vois. Je suppose que ce n'est que lorsqu'il y a un générateur ou un itérateur paresseux similaire.
TigerhawkT3
4
anyet all«court-circuiter» le processus d' examen de l'itérable qui leur est donné; mais si cet itérable est une séquence plutôt qu'un générateur, alors il a déjà été entièrement évalué avant que l'appel de fonction ne se produise .
Karl Knechtel
Cela présente l'avantage qu'il est facile de se diviser sur plusieurs lignes (double indentation des arguments any, simple indentation ):dans l' ifinstruction), ce qui aide beaucoup à la lisibilité lorsque les mathématiques sont impliquées
Izkata
40
Si vous savez que vous ne traitez qu'avec des nombres positifs, cela fonctionnera et est assez propre:
a, b, c = sorted((a, b, c))if a + b == c:
do_stuff()
Comme je l'ai dit, cela ne fonctionne que pour les nombres positifs; mais si vous savez qu'ils vont être positifs, c'est une solution IMO très lisible, même directement dans le code plutôt que dans une fonction.
Vous pourriez faire ceci, ce qui pourrait faire un peu de calcul répété; mais vous n'avez pas spécifié les performances comme objectif:
from itertools import permutations
if any(x + y == z for x, y, z in permutations((a, b, c),3)):
do_stuff()
Ou sans permutations()et possibilité de calculs répétés:
if any(x + y == z for x, y, z in[(a, b, c),(a, c, b),(b, c, a)]:
do_stuff()
Je mettrais probablement ceci, ou toute autre solution, dans une fonction. Ensuite, vous pouvez simplement appeler proprement la fonction dans votre code.
Personnellement, à moins que j'aie besoin de plus de flexibilité du code, j'utiliserais simplement la première méthode de votre question. C'est simple et efficace. Je pourrais encore le mettre dans une fonction:
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()
C'est assez pythonique, et c'est probablement le moyen le plus efficace de le faire (l'appel de fonction supplémentaire de côté); bien que vous ne devriez pas trop vous soucier des performances de toute façon, à moins que cela ne cause réellement un problème.
surtout si nous pouvons supposer que a, b, c sont tous non négatifs.
cphlewis
Je trouve l'expression «ne fonctionne pas toujours» un peu déroutante. La première solution ne fonctionne que si vous savez avec certitude que vos chiffres ne sont pas négatifs. Par exemple avec (a, b, c) = (-3, -2, -1) vous avez a + b! = C mais b + c = a. Cas similaires avec (-1, 1, 2) et (-2, -1, 1).
numéro d'utilisateur
@usernumber, vous savez, je l'ai remarqué plus tôt; Je ne sais pas pourquoi je ne l'ai pas réparé.
Cyphase
Votre meilleure solution ne fonctionne pas pour une grande classe d'entrées, alors que la suggestion du PO fonctionne pour toutes les entrées. En quoi «ne pas travailler» est-il plus pythonique que «travailler»?
Barry
3
Ooh, claque. " Si vous savez que vous avez seulement affaire à des nombres positifs , cela fonctionnera et c'est assez propre". Tous les autres fonctionnent pour tous les nombres, mais si vous savez que vous n'avez affaire qu'à des nombres positifs , celui du haut est très lisible / Pythonic IMO.
Cyphase
17
Si vous n'utilisez que trois variables, votre méthode initiale:
a + b == c or a + c == b or b + c == a
Est déjà très pythonique.
Si vous prévoyez d'utiliser plus de variables, votre méthode de raisonnement avec:
a + b + c in(2*a,2*b,2*c)
Est très intelligent mais réfléchissons à pourquoi. Pourquoi ça marche?
Eh bien, grâce à une simple arithmétique, nous voyons que:
a + b = c
c = c
a + b + c == c + c ==2*c
a + b + c ==2*c
Et cela devra être vrai pour a, b, c, ce qui signifie que oui il sera égal 2*a, 2*bou 2*c. Cela sera vrai pour n'importe quel nombre de variables.
Donc, une bonne façon d'écrire cela rapidement serait d'avoir simplement une liste de vos variables et de vérifier leur somme par rapport à une liste des valeurs doublées.
values =[a,b,c,d,e,...]
any(sum(values)in[2*x for x in values])
De cette façon, pour ajouter plus de variables dans l'équation, tout ce que vous avez à faire est de modifier votre liste de valeurs par 'n' nouvelles variables, et non d'écrire 'n' équations
Qu'en est- il a=-1, b=-1, c=-2, puis a+b=c, mais a+b+c = -4et 2*max(a,b,c)est-2
Eric Renouf
Merci c'est vrai, j'aurais besoin d'utiliser des abdos. Faire cet ajustement maintenant.
ThatGuyRussell
2
Après l'avoir agrémenté d'une demi-douzaine d' abs()appels, c'est Pythonic que l'extrait de l'OP (je l'appellerais en fait beaucoup moins lisible).
TigerhawkT3
C'est très vrai, je vais ajuster cela maintenant
ThatGuyRussell
1
@ThatGuyRussell Afin de court-circuiter, vous voudriez utiliser un générateur ... quelque chose comme any(sum(values) == 2*x for x in values), de cette façon, vous n'auriez pas à faire tout le doublement à l'avant, tout aussi nécessaire.
Barry
12
Le code suivant peut être utilisé pour comparer de manière itérative chaque élément avec la somme des autres, qui est calculée à partir de la somme de la liste entière, à l'exclusion de cet élément.
Bien :) Je pense que si vous supprimez les []supports de la deuxième ligne, cela va même court-circuiter comme l'original avec or...
psmears
1
ce qui est fondamentalement any(a + b + c == 2*x for x in [a, b, c])assez proche de la suggestion du PO
njzk2
C'est similaire, mais cette méthode s'étend à n'importe quel nombre de variables. J'ai incorporé la suggestion de @psmears sur les courts-circuits.
Arcanum
10
N'essayez pas de le simplifier. À la place, nommez ce que vous faites avec une fonction:
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):...
Remplacer la condition par quelque chose de "intelligent" pourrait la raccourcir, mais cela ne la rendra pas plus lisible. Le laisser tel quel n'est pas non plus très lisible, car il est difficile de savoir pourquoi vous vérifiez ces trois conditions en un coup d'œil. Cela rend parfaitement clair ce que vous vérifiez.
En ce qui concerne les performances, cette approche ajoute la surcharge d'un appel de fonction, mais ne sacrifie jamais la lisibilité pour les performances, sauf si vous avez trouvé un goulot d'étranglement que vous devez absolument corriger. Et mesurez toujours, car certaines implémentations intelligentes sont capables d'optimiser et d'incorporer certains appels de fonction dans certaines circonstances.
Les fonctions ne doivent être écrites que si vous prévoyez d'utiliser le même code à plusieurs endroits ou si le code est complexe. Il n'y a aucune mention de la réutilisation du code dans la question d'origine, et l'écriture d'une fonction pour une seule ligne de code est non seulement exagérée, mais elle nuit en fait à la lisibilité.
Igor Levicki
5
Venant de l'école des choses FP, je dois à peu près être en désaccord complètement et déclarer que les fonctions à une ligne bien nommées sont parmi les meilleurs outils pour augmenter la lisibilité que vous trouverez. Créez une fonction chaque fois que les étapes que vous prenez pour faire quelque chose n'apportent pas immédiatement de clarté à ce que vous faites, car le nom de la fonction vous permet de spécifier ce qui est mieux que n'importe quel commentaire.
Jack
Quelle que soit l'école que vous invoquez, il est mauvais d'adhérer aveuglément à un ensemble de règles. Devoir passer à une autre partie de la source pour lire cette ligne de code cachée à l'intérieur d'une fonction juste pour pouvoir vérifier qu'elle fait réellement ce qu'elle dit dans le nom, puis devoir revenir à l'endroit d'un appel à assurez-vous que vous passez des paramètres corrects est un changement de contexte complètement inutile. À mon avis, cela nuit à la fois à la lisibilité et au flux de travail. Enfin, ni le nom d'une fonction ni les commentaires de code ne remplacent correctement la documentation du code.
Igor Levicki
9
Python 3:
(a+b+c)/2in(a,b,c)(a+b+c+d)/2in(a,b,c,d)...
Il s'adapte à n'importe quel nombre de variables:
arr =[a,b,c,d,...]
sum(arr)/2in arr
Cependant, en général, je conviens qu'à moins que vous n'ayez plus de trois variables, la version originale est plus lisible.
Cela renvoie des résultats incorrects pour certaines entrées en raison d'erreurs d'arrondi en virgule flottante.
pts
La division doit être évitée pour des raisons de performance et de précision.
Igor Levicki
1
@pts Aucune implémentation ne renverra-t-elle des résultats incorrects en raison de l'arrondi en virgule flottante? Even a + b == c
osundblad
@osundblad: Si a, b et c sont des entiers, alors (a + b + c) / 2 arrondit (et peut renvoyer des résultats incorrects), mais a + b == c est exact.
pts
3
la division par 2 diminue simplement l'exposant de un, donc il sera précis pour tout entier inférieur à 2 ^ 53 (la partie fractionnaire d'un flottant en python), et pour des entiers plus grands, vous pouvez utiliser décimal . Par exemple, pour vérifier les nombres entiers inférieurs à 2 ^ 30, exécutez[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
Si la somme de deux termes est égale au troisième terme, l'un des facteurs sera égal à zéro, ce qui rendra le produit entier nul.
Je pensais exactement la même chose mais je ne peux pas nier que sa proposition originale est bien plus propre ...
user541686
@Mehrdad - Certainement. Ce n'est vraiment pas différent de(a+b<>c) && (a+c<>b) && (b+c<>a) == false
mbeckish
C'est juste que la multiplication coûte plus cher que les expressions logiques et l'arithmétique de base.
Igor Levicki
@IgorLevicki - Oui, bien que ce soit un problème d'optimisation TRÈS prématuré. Cela va-t-il être effectué des dizaines de milliers de fois par seconde? Si oui, vous voudrez probablement regarder autre chose.
mbeckish
@mbeckish - Pourquoi pensez-vous que c'est prématuré? Le code doit être écrit avec l'optimisation à l'esprit, pas optimisé après coup. Un jour, un stagiaire copiera cet extrait de code et le collera dans une boucle critique de performances sur une plate-forme embarquée qui fonctionnera ensuite sur des millions d'appareils, ce qui ne sera pas nécessairement lent pour ce qu'il fait, mais gaspillera peut-être plus d'énergie de la batterie. L'écriture d'un tel code encourage simplement les mauvaises pratiques de codage. À mon avis, ce qu'OP aurait dû demander, c'est s'il existe un moyen d'optimiser cette expression logique.
Igor Levicki
6
Que diriez-vous simplement:
a == b + c or abs(a)== abs(b - c)
Notez que cela ne fonctionnera pas si les variables ne sont pas signées.
Du point de vue de l'optimisation du code (au moins sur la plate-forme x86), cela semble être la solution la plus efficace.
Les compilateurs modernes intégreront les deux appels de fonction abs () et éviteront les tests de signe et la branche conditionnelle ultérieure en utilisant une séquence intelligente d'instructions CDQ, XOR et SUB . Le code de haut niveau ci-dessus sera donc représenté avec uniquement des instructions ALU à faible latence, à haut débit et seulement deux conditions.
Et je pense que fabs()peut être utilisé pour les floattypes;).
jeu du
4
La solution fournie par Alex Varga "a in (b + c, bc, cb)" est compacte et mathématiquement belle, mais je n'écrirais pas réellement le code de cette façon parce que le prochain développeur à venir ne comprendrait pas immédiatement le but du code .
La solution de Mark Ransom de
any((a + b == c, a + c == b, b + c == a))
est plus clair mais pas beaucoup plus succinct que
a + b == c or a + c == b or b + c == a
Lors de l'écriture de code que quelqu'un d'autre devra regarder, ou que je devrai regarder longtemps plus tard quand j'aurai oublié ce que je pensais quand je l'ai écrit, être trop court ou intelligent a tendance à faire plus de mal que de bien. Le code doit être lisible. Si succinct est bon, mais pas si succinct que le prochain programmeur ne peut pas le comprendre.
Question honnête: pourquoi les gens supposent-ils toujours que le prochain programmeur sera un idiot incapable de lire le code? Personnellement, je trouve cette idée insultante. Si le code doit être écrit pour être manifestement évident pour chaque programmeur, cela implique que nous, en tant que profession, nous servons du plus petit dénominateur commun, le moins qualifié d'entre nous. Si nous continuons à faire cela, comment vont-ils un jour améliorer leurs compétences personnelles? Je ne vois pas cela dans d'autres professions. À quand remonte la dernière fois que vous avez vu un compositeur écrire une partition musicale simple pour que chaque musicien puisse la jouer quel que soit son niveau de compétence?
Igor Levicki
6
Le problème est que même les programmeurs ont une énergie mentale limitée, alors voulez-vous dépenser votre énergie mentale limitée sur l'algorithme et les aspects de plus haut niveau du programme, ou pour comprendre ce que signifie une ligne de code compliquée lorsqu'elle peut être exprimée plus simplement ? La programmation est difficile, alors ne vous compliquez pas inutilement, tout comme un coureur olympique ne ferait pas une course avec un sac à dos lourd simplement parce qu'il le peut. Comme le dit Steve McConell dans Code Complete 2, la lisibilité est l'un des aspects les plus importants du code.
Paul J Abernathy
2
La demande est plus compacte OU plus pythonique - j'ai essayé ma main à plus compacte.
donné
import functools, itertools
f = functools.partial(itertools.permutations, r =3)def g(x,y,z):return x + y == z
C'est 2 caractères de moins que l'original
any(g(*args)for args in f((a,b,c)))
tester avec:
assert any(g(*args)for args in f((a,b,c)))==(a + b == c or a + c == b or b + c == a)
Eh bien, c'est deux caractères plus courts que l'original, mais pas celui que l'OP a donné juste après, qu'il a dit qu'il utilise actuellement. L'original comprend également de nombreux espaces, ce que cela omet autant que possible. Il y a aussi la petite question de la fonction que g()vous devez définir pour que cela fonctionne. Compte tenu de tout cela, je dirais que c'est beaucoup plus important.
TigerhawkT3
@ TigerhawkT3, je l'ai interprété comme une demande d'expression / ligne plus courte. voir modifier pour une amélioration supplémentaire .
wwii
4
Très mauvais noms de fonctions, ne convient que pour un code golf.
0xc0de
@ 0xc0de - désolé, je ne joue pas. Adapté peut être assez subjectif et dépendant des circonstances - mais je m'en remettrai à la communauté.
wwii
Je ne vois pas comment est-ce plus compact quand il a plus de caractères que le code d'origine.
Igor Levicki
1
Je veux présenter ce que je considère comme la réponse la plus pythonique :
def one_number_is_the_sum_of_the_others(a, b, c):return any((a == b + c, b == a + c, c == a + b))
En termes de Zen de Python, je pense que les déclarations soulignées sont plus suivies que d'autres réponses:
Le Zen de Python, par Tim Peters
Beau est mieux que laid. L'explicite vaut mieux que l'implicite. Le simple vaut mieux que le complexe.
Complexe vaut mieux que compliqué.
Plat vaut mieux que niché.
Clairsemé vaut mieux que dense. La lisibilité compte.
Les cas spéciaux ne sont pas assez spéciaux pour enfreindre les règles.
Bien que l'aspect pratique l'emporte sur la pureté.
Les erreurs ne devraient jamais passer silencieusement.
À moins d'être explicitement réduit au silence.
Face à l'ambiguïté, refusez la tentation de deviner.
Il devrait y avoir une - et de préférence une seule - façon évidente de le faire.
Bien que cette manière ne soit pas évidente au début, sauf si vous êtes néerlandais.
C'est mieux que jamais.
Bien que jamais ne soit souvent mieux quedès maintenant.
Si l'implémentation est difficile à expliquer, c'est une mauvaise idée.
Si la mise en œuvre est facile à expliquer, cela peut être une bonne idée.
Les espaces de noms sont une excellente idée - faisons-en plus!
En tant que vieille habitude de ma programmation, je pense que placer une expression complexe à droite dans une clause peut la rendre plus lisible comme ceci:
a == b+c or b == a+c or c == a+b
Plus ():
((a == b+c)or(b == a+c)or(c == a+b))
Et aussi je pense que l'utilisation de multi-lignes peut aussi faire plus de sens comme ceci:
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
Les fonctions ne doivent être écrites que si vous prévoyez d'utiliser le même code à plusieurs endroits ou si le code est complexe. Il n'y a aucune mention de la réutilisation du code dans la question d'origine, et l'écriture d'une fonction pour une seule ligne de code est non seulement exagérée, mais elle nuit en fait à la lisibilité.
Igor Levicki
Je ne suis pas d'accord pour dire que cela nuit à la lisibilité; si vous choisissez un nom approprié, cela peut améliorer la lisibilité (mais je ne fais aucune représentation quant à la qualité du nom que j'ai choisi dans cette réponse). De plus, il peut être utile de donner un nom à un concept, ce que vous devrez faire tant que vous vous forcez à donner un bon nom à votre fonction. Les fonctions sont bonnes. Quant à savoir si la fonctionnalité est suffisamment complexe pour bénéficier de l'encapsulation dans une fonction, c'est un jugement subjectif.
Réponses:
Si nous regardons le Zen de Python, soulignons le mien:
La solution la plus pythonique est celle qui est la plus claire, la plus simple et la plus facile à expliquer:
Mieux encore, vous n'avez même pas besoin de connaître Python pour comprendre ce code! C'est aussi simple que ça . C'est, sans réserve, la meilleure solution. Tout le reste est de la masturbation intellectuelle.
De plus, il s'agit probablement de la solution la plus performante, car c'est la seule parmi toutes les propositions qui court-circuite. Si
a + b == c
, une seule addition et comparaison est effectuée.la source
Résoudre les trois égalités pour un:
la source
Python a une
any
fonction qui fait unor
sur tous les éléments d'une séquence. Ici, j'ai converti votre déclaration en un tuple à 3 éléments.Notez qu'il
or
s'agit d'un court-circuit, donc si le calcul des conditions individuelles est coûteux, il peut être préférable de conserver votre conception d'origine.la source
any()
etall()
court-circuit aussi.any
même de s'exécuter.any
etall
«court-circuiter» le processus d' examen de l'itérable qui leur est donné; mais si cet itérable est une séquence plutôt qu'un générateur, alors il a déjà été entièrement évalué avant que l'appel de fonction ne se produise .any
, simple indentation):
dans l'if
instruction), ce qui aide beaucoup à la lisibilité lorsque les mathématiques sont impliquéesSi vous savez que vous ne traitez qu'avec des nombres positifs, cela fonctionnera et est assez propre:
Comme je l'ai dit, cela ne fonctionne que pour les nombres positifs; mais si vous savez qu'ils vont être positifs, c'est une solution IMO très lisible, même directement dans le code plutôt que dans une fonction.
Vous pourriez faire ceci, ce qui pourrait faire un peu de calcul répété; mais vous n'avez pas spécifié les performances comme objectif:
Ou sans
permutations()
et possibilité de calculs répétés:Je mettrais probablement ceci, ou toute autre solution, dans une fonction. Ensuite, vous pouvez simplement appeler proprement la fonction dans votre code.
Personnellement, à moins que j'aie besoin de plus de flexibilité du code, j'utiliserais simplement la première méthode de votre question. C'est simple et efficace. Je pourrais encore le mettre dans une fonction:
C'est assez pythonique, et c'est probablement le moyen le plus efficace de le faire (l'appel de fonction supplémentaire de côté); bien que vous ne devriez pas trop vous soucier des performances de toute façon, à moins que cela ne cause réellement un problème.
la source
Si vous n'utilisez que trois variables, votre méthode initiale:
Est déjà très pythonique.
Si vous prévoyez d'utiliser plus de variables, votre méthode de raisonnement avec:
Est très intelligent mais réfléchissons à pourquoi. Pourquoi ça marche?
Eh bien, grâce à une simple arithmétique, nous voyons que:
Et cela devra être vrai pour a, b, c, ce qui signifie que oui il sera égal
2*a
,2*b
ou2*c
. Cela sera vrai pour n'importe quel nombre de variables.Donc, une bonne façon d'écrire cela rapidement serait d'avoir simplement une liste de vos variables et de vérifier leur somme par rapport à une liste des valeurs doublées.
De cette façon, pour ajouter plus de variables dans l'équation, tout ce que vous avez à faire est de modifier votre liste de valeurs par 'n' nouvelles variables, et non d'écrire 'n' équations
la source
a=-1
,b=-1
,c=-2
, puisa+b=c
, maisa+b+c = -4
et2*max(a,b,c)
est-2
abs()
appels, c'est Pythonic que l'extrait de l'OP (je l'appellerais en fait beaucoup moins lisible).any(sum(values) == 2*x for x in values)
, de cette façon, vous n'auriez pas à faire tout le doublement à l'avant, tout aussi nécessaire.Le code suivant peut être utilisé pour comparer de manière itérative chaque élément avec la somme des autres, qui est calculée à partir de la somme de la liste entière, à l'exclusion de cet élément.
la source
[]
supports de la deuxième ligne, cela va même court-circuiter comme l'original avecor
...any(a + b + c == 2*x for x in [a, b, c])
assez proche de la suggestion du PON'essayez pas de le simplifier. À la place, nommez ce que vous faites avec une fonction:
Remplacer la condition par quelque chose de "intelligent" pourrait la raccourcir, mais cela ne la rendra pas plus lisible. Le laisser tel quel n'est pas non plus très lisible, car il est difficile de savoir pourquoi vous vérifiez ces trois conditions en un coup d'œil. Cela rend parfaitement clair ce que vous vérifiez.
En ce qui concerne les performances, cette approche ajoute la surcharge d'un appel de fonction, mais ne sacrifie jamais la lisibilité pour les performances, sauf si vous avez trouvé un goulot d'étranglement que vous devez absolument corriger. Et mesurez toujours, car certaines implémentations intelligentes sont capables d'optimiser et d'incorporer certains appels de fonction dans certaines circonstances.
la source
Python 3:
Il s'adapte à n'importe quel nombre de variables:
Cependant, en général, je conviens qu'à moins que vous n'ayez plus de trois variables, la version originale est plus lisible.
la source
[x for x in range(pow(2,30)) if x != ((x * 2)/ pow(2,1))]
Si la somme de deux termes est égale au troisième terme, l'un des facteurs sera égal à zéro, ce qui rendra le produit entier nul.
la source
(a+b<>c) && (a+c<>b) && (b+c<>a) == false
Que diriez-vous simplement:
Notez que cela ne fonctionnera pas si les variables ne sont pas signées.
Du point de vue de l'optimisation du code (au moins sur la plate-forme x86), cela semble être la solution la plus efficace.
Les compilateurs modernes intégreront les deux appels de fonction abs () et éviteront les tests de signe et la branche conditionnelle ultérieure en utilisant une séquence intelligente d'instructions CDQ, XOR et SUB . Le code de haut niveau ci-dessus sera donc représenté avec uniquement des instructions ALU à faible latence, à haut débit et seulement deux conditions.
la source
fabs()
peut être utilisé pour lesfloat
types;).La solution fournie par Alex Varga "a in (b + c, bc, cb)" est compacte et mathématiquement belle, mais je n'écrirais pas réellement le code de cette façon parce que le prochain développeur à venir ne comprendrait pas immédiatement le but du code .
La solution de Mark Ransom de
est plus clair mais pas beaucoup plus succinct que
Lors de l'écriture de code que quelqu'un d'autre devra regarder, ou que je devrai regarder longtemps plus tard quand j'aurai oublié ce que je pensais quand je l'ai écrit, être trop court ou intelligent a tendance à faire plus de mal que de bien. Le code doit être lisible. Si succinct est bon, mais pas si succinct que le prochain programmeur ne peut pas le comprendre.
la source
La demande est plus compacte OU plus pythonique - j'ai essayé ma main à plus compacte.
donné
C'est 2 caractères de moins que l'original
tester avec:
de plus, étant donné:
C'est équivalent
la source
g()
vous devez définir pour que cela fonctionne. Compte tenu de tout cela, je dirais que c'est beaucoup plus important.Je veux présenter ce que je considère comme la réponse la plus pythonique :
Le cas général, non optimisé:
En termes de Zen de Python, je pense que les déclarations soulignées sont plus suivies que d'autres réponses:
la source
En tant que vieille habitude de ma programmation, je pense que placer une expression complexe à droite dans une clause peut la rendre plus lisible comme ceci:
Plus
()
:Et aussi je pense que l'utilisation de multi-lignes peut aussi faire plus de sens comme ceci:
la source
De manière générique,
si, manipuler une variable d'entrée est OK pour vous,
si vous souhaitez exploiter en utilisant des hacks de bits, vous pouvez utiliser "!", ">> 1" et "<< 1"
J'ai évité la division bien que cela permette d'éviter deux multiplications pour éviter les erreurs d'arrondi. Cependant, vérifiez les débordements
la source
la source