Compact manière d'écrire (a + b == c ou a + c == b ou b + c == a)
Est-il plus compact ou pythonic façon d'écrire l'expression booléenne
a + b == c or a + c == b or b + c == a
Je suis venu avec
a + b + c in (2*a, 2*b, 2*c)
mais c'est un peu étrange.
a + b + c == max(a, b, c)
ne serait pasTrue
à moins que les deux plus petites valeurs de la somme à0
.- Plus compact? Peut-être. Plus Pythonic? Peu probable.
- Il semble que vous avez trois mutuellement exclusifs conditions - c'est sans doute pourquoi vous êtes
or
-ing eux. Semble que si il sont mutuellement exclusifs, vous ne seriez pas en mesure de les combiner et d'en simplifier l'expression. - Faites votre future auto une faveur et de les garder dans la forme originale: C'est la seule qui indique immédiatement le but de cette. Ne pas le modifier. “Simple est mieux que d'être compliqué.”, “La lisibilité compte.”. “Si la mise en œuvre est difficile à expliquer, c'est une mauvaise idée.”
- Pythonic == illisible?
- Pas un python personne mais n'a pas de python ont quelques frais de la liste des fonctions? Je voudrais essayer de la liste de toutes les permutations de
[a,b,c]
et de trouver un endroit où le dernier est la somme des autres, ou quelque chose comme ça. - Peut-être il peut être plus pythonic si vous dites d'abord dans la langue, ce que cette comparaison de la cible.
- Ils ne sont pas mutuellement exclusives. Voir a = 0, b = 0, c = 0 😉
- J'aime ce que vous est venu avec le meilleur.
- Ce que @phresnel dit. Au lieu d'essayer de "simplifier" l'expression, de l'envelopper dans une fonction avec un nom descriptif.
- Sinon, affecter la valeur de la comparaison d'une variable avec un nom descriptif. Dépend, quoi de plus logique 🙂
- J'ai lu une fois que vous devriez écrire votre code source, comme si elle sera maintenue par un fou armé d'une hache plus tard. Je pense que le fou armé d'une hache préférez votre première version. Et @Alex Varga besoin de regarder par-dessus son épaule pour le fou armé d'une hache!
- est (0,0,0) le seul trio qui sera
True
pour les trois conditions? - Oui, le problème peut être vu comme un système homogène d'équations linéaires et comme il y a 3 variables et 3 de l'indépendance linéaire des équations (en d'autres termes de la matrice est de plein rang), la seule solution qui satisfait à tous les trois est (0,0,0). Si vous avez besoin seulement 2 conditions sont remplies en même temps, il y aurait une infinité de solutions reposant sur une seule ligne dans 3D carthesian de l'espace. En changeant les conditions, vous obtiendrez 3 lignes que tous se coupent en (0,0,0)
- Attention. Si
a
,b
,c
sont des nombres à virgule flottante, puisa + b == c or a + c == b or b + c == a
n'est pas équivalent àa + b + c in (2*a, 2*b, 2*c)
, en général. Par exemple, aveca = 1 + 2*sys.float_info.epsilon
,b = 1
, etc = 2
, l'expression est évaluée àFalse
, tandis que le second évalue àTrue
.
Vous devez vous connecter pour publier un commentaire.
Si l'on regarde le Zen de Python, c'est moi qui souligne:
Les plus Pythonic solution 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 savoir Python pour comprendre ce code! C'est que facile. C'est, sans réserve, la meilleure solution. Tout le reste est de la masturbation intellectuelle.
En outre, c'est probablement la solution la plus performante, car il est le seul de toutes les propositions que les courts-circuits. Si
a + b == c
, une seule addition et la comparaison est effectuée.Résoudre les trois égalités pour un:
Python a une
any
fonction qui fait unor
sur tous les éléments d'une séquence. Ici, j'ai converti votre déclaration dans un 3-élément d'un tuple.Noter que
or
est le court-circuit, donc, si le calcul de l'individu conditions est cher, il pourrait être préférable de conserver l'original de votre construction.any()
etall()
de court-circuit trop.any
court même.any
etall
"court-circuit" le processus de examen l'objet iterable qu'ils sont donnés; mais, si c'est itérable est une séquence plutôt qu'un générateur, puis il a été déjà été pleinement évalués avant l'appel de la fonction se produit.any
, un seul tiret de la):
dans leif
déclaration), ce qui aide beaucoup pour des raisons de lisibilité lorsque les mathématiques sont impliqués(: 1, 2, 3 :)
ou(? 1, 2, 3)
.Si vous savez que vous avez seulement à faire avec des nombres positifs, cela fonctionne, et il est assez propre:
Comme je l'ai dit, cela ne fonctionne que pour les nombres positifs; mais si vous savoir ils vont être positif, c'est très lisible solution de l'OMI, même directement dans le code plutôt que dans une fonction.
Vous pourriez faire, ce qui pourrait faire un peu de calcul répété; mais vous ne spécifiez pas les performances de votre objectif:
Ou sans
permutations()
et la possibilité de la répétition des calculs:Je serais probablement mis, ou toute autre solution, dans une fonction. Ensuite, vous pouvez simplement et proprement appeler la fonction dans votre code.
Personnellement sauf à ce que j'avais besoin de plus de souplesse dans le code, je voudrais juste utiliser la première méthode dans votre question. C'est simple et efficace. Je peux toujours le mettre dans une fonction:
C'est assez Pythonic, et c'est très probablement le moyen le plus efficace de le faire (l'extra appel de fonction à part); bien que vous ne devriez pas trop vous inquiéter au sujet de la performance de toute façon, à moins que c'est en fait à l'origine d'un problème.
Si vous allez seulement à l'aide de trois variables, alors votre initiale de la méthode:
Est déjà très pythonic.
Si vous prévoyez sur l'utilisation de plusieurs variables, alors la méthode de votre raisonnement avec:
Est très intelligent, mais permet de réfléchir à la raison. Pourquoi ce travail?
Le biais de certains de l'arithmétique simple, nous voyons que:
Et ce sera le cas, soit a,b, ou c, ce qui signifie que oui, il sera égal à
2*a
,2*b
, ou2*c
. Ce sera vrai pour un nombre quelconque de variables.Donc une bonne façon d'écrire rapidement ce serait tout simplement avoir une liste de vos variables et vérifier leur somme par rapport à une liste de l'doublé valeurs.
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 des 'n' de nouvelles variables, de ne pas écrire " n " équations
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'OP est extrait de code (je l'avais fait appel de manière significative moins lisible).it's less Pythonic
.n
équations, pas(n-1)!
.sum(values) in [2*x for x in values]
.any(sum(values) == 2*x for x in values)
, de cette façon, vous n'auriez pas à faire tout le doublement de l'avant, tout aussi nécessaire.Le code suivant peut être utilisé de manière itérative comparer chaque élément avec la somme des autres, ce qui est calculé à partir de la somme de l'ensemble de la liste, à l'exclusion de cet élément.
[]
crochets à partir de la deuxième ligne, ce sera même de court-circuit comme l'original avecor
...any(a + b + c == 2*x for x in [a, b, c])
, assez proche de l'OP suggestionN'essayez pas de les simplifier. Au lieu de cela, nom ce que vous faites avec une fonction:
Remplacer la condition avec quelque chose "d'intelligent" pourrait faire plus court, mais il ne va pas le rendre plus lisible. Laissant la façon dont il est n'est pas très lisible soit cependant, parce qu'il est difficile de savoir pourquoi vous êtes à la vérification de ces trois conditions d'un coup d'oeil. Cela rend absolument limpide ce que vous êtes en contrôle pour le.
Ce qui concerne la performance, cette approche ajoute la surcharge d'un appel de fonction, mais de ne jamais sacrifier la lisibilité pour les performances sauf si vous avez trouvé un goulot d'étranglement vous devez absolument corriger. Et toujours une large mesure, comme certains intelligente implémentations sont capables d'optimisation de loin et inline certains appels de fonction dans certaines circonstances.
Python 3:
S'adapte au nombre de variables:
Cependant, en général je suis d'accord que si vous avez plus de trois variables, la version originale est plus lisible.
[x for x in range(pow(2,30)) if x != ((x * 2)/ pow(2,1))]
Si la somme des deux termes est égale à la troisième terme, l'un des facteurs sera de zéro, l'ensemble du produit zéro.
(a+b<>c) && (a+c<>b) && (b+c<>a) == false
Que diriez-vous simplement:
Noter que cela ne fonctionnera pas si les variables ne sont pas signés.
Du point de vue de l'optimisation du code (au moins sur plate-forme x86) cela semble être la solution la plus efficace.
Moderne compilateurs inline à la fois abs() appels de fonction et d'éviter de signer des tests et suivantes branche conditionnelle à l'aide d'un intelligent séquence de CDQ, XOR, et SOUS les instructions. Le ci-dessus du code de haut niveau sera donc représenté avec seulement de faibles temps de latence, à haut débit ALU instructions et seulement deux conditions.
fabs()
peut être utilisé pourfloat
types ;).De la solution fournie par Alex Varga "a (b+c, b-c, c-b)" est compact et mathématiquement belle, mais je n'aurais pas fait d'écrire le code de cette façon parce que le prochain développeur à venir ne serait pas immédiatement comprendre le but de ce code.
Marque Rançon de la solution de
est plus clair, mais pas beaucoup plus succincte que
Lors de l'écriture de code que quelqu'un d'autre à regarder, ou que je vais avoir à regarder un long moment plus tard, quand j'ai oublié ce que je pensais quand je l'ai écrit, d'être trop court ou intelligent tend à faire plus de mal que de bien. Le Code doit être lisible. Si succincts est bon, mais pas aussi succincte que la prochaine programmeur ne peut pas le comprendre.
Demande est plus compact OU plus pythonic - j'ai essayé ma main à plus compact.
donné
C'est 2 personnages moins que l'original
test avec:
en outre, compte tenu:
C'est l'équivalent
g()
vous devez définir pour que cela fonctionne. Compte tenu de tout cela, je dirais que c'est nettement plus grande.Je veux vous présenter ce que je considère comme le plus pythonic réponse:
Le cas général, la non-optimisé:
En termes de Zen de Python, je pense que l'ont souligné les rapports sont plus suivies que d'autres réponse:
Comme une vieille habitude de ma programmation, je pense que placer complexe de l'expression à droite dans une clause peut le rendre plus lisible comme ça:
Plus
()
:Et je pense également que l'utilisation de multi-lignes peuvent faire plus de sens comme ça:
De manière générique,
si, de manipuler une variable d'entrée est OK pour vous,
si vous souhaitez exploiter à l'aide de peu de bidouilles, vous pouvez utiliser "!", ">> 1" et "<< 1"
J'ai évité la division si elle permet d'éviter deux multiplications pour éviter d'arrondir les erreurs. Cependant, vérifiez pour les dépassements