Quels conseils généraux avez-vous pour jouer au golf en Python? Je cherche des idées qui puissent être appliquées aux problèmes de code-golf et qui soient aussi au moins quelque peu spécifiques à Python (par exemple, "supprimer les commentaires" n'est pas une réponse).
Merci de poster un pourboire par réponse.
Réponses:
Utilisez
a=b=c=0
au lieu dea,b,c=0,0,0
.Utilisez
a,b,c='123'
au lieu dea,b,c='1','2','3'
.la source
Les conditions peuvent être longues. Dans certains cas, vous pouvez remplacer un simple conditionnel par
(a,b)[condition]
. Sicondition
est vrai, alorsb
est retourné.Comparer
Pour ça
la source
a if a<b else b
eta<b and a or b
(lambda(): b, lambda(): a)[a < b]()
faites votre propre court-circuit avec lambdasP and A or B
pour tout A qui donnebool(A)=False
. Mais(P and [A] or [B])[0]
fera le travail. Voir diveintopython.net/power_of_introspection/and_or.html pour référence.Une bonne chose que j'ai faite une fois est:
au lieu de:
Les opérateurs de comparaison de Python basculent.
En utilisant tout ce qui est comparable dans Python 2, vous pouvez également éviter l'
and
opérateur de cette façon. Par exemple, sia
,b
,c
etd
sont des nombres entiers,peut être raccourci d'un caractère à:
Cela utilise que chaque liste est plus grande que n'importe quel entier.
Si
c
etd
sont des listes, cela devient encore meilleur:la source
3>a>1<b<5
[$a => $b]->[$b <= $a]
:)if(a<b)+(c>d):foo()
*
. Anor
serait+
foo()if 3>a>1<b<5
Si vous utilisez une fonction intégrée à plusieurs reprises, il pourrait être plus efficace de lui attribuer un nouveau nom si vous utilisez des arguments différents:
la source
Parfois, votre code Python nécessite 2 niveaux d’indentation. La chose évidente à faire est d'utiliser un et deux espaces pour chaque niveau d'indentation.
Cependant, Python 2 considère que les caractères de tabulation et d'espace sont des niveaux d'indentation différents.
Cela signifie que le premier niveau d'indentation peut être d'un espace et le second peut être un caractère de tabulation.
Par exemple:
Où
\t
est le caractère de tabulation.la source
TabError: inconsistent use of tabs and spaces in indentation.
Utilisez la substitution de chaîne et
exec
les mots-clés longslambda
sont souvent répétés dans votre code.La chaîne cible est très souvent
'lambda '
longue de 7 octets. Supposons que votre extrait de code contienne desn
occurrences de'lambda '
et qu'ils
dure longtemps. Ensuite:plain
option ests
octets longs.replace
option ests - 6n + 29
octets longs.%
option ests - 5n + 22 + len(str(n))
octets longs.À partir d'un tracé d' octets enregistrés
plain
pour ces trois options, nous pouvons voir que:exec"..."%(('lambda ',)*5)
enregistre 2 octets et constitue votre meilleure option.exec"...".replace('`','lambda ')
est votre meilleure option.Pour les autres cas, vous pouvez indexer le tableau ci-dessous:
Par exemple, si la chaîne
lambda x,y:
(longueur 11) apparaît 3 fois dans votre code, vous feriez mieux d'écrireexec"..."%(('lambda x,y:',)*3)
.la source
replace
est énorme.=>
c'est juste la chaîne= lambda
. Par exemple,f=>:0
seraitf = lambda: 0
.Utilisez le découpage étendu pour sélectionner une chaîne parmi plusieurs
contre
Dans ce cas booléen à deux cordes, on peut aussi écrire
pour
Contrairement à l'entrelacement, cela fonctionne pour les chaînes de n'importe quelle longueur, mais peut avoir des problèmes de priorité d'opérateur s'il
b
s'agit plutôt d'une expression.la source
for x in ("foo","bar","baz"): print x
x
sont rendues. La partie jouée au golf est le"fbboaaorz"[x::3]
vs.["foo","bar","baz"][x]
Comment lax
valeur est dérivée serait une autre partie de votre solution de golf.Utilisez
`n`
pour convertir un entier en chaîne au lieu destr(n)
:la source
Stocker les tables de consultation sous forme de nombres magiques
Supposons que vous vouliez coder en dur une table de recherche booléenne, par exemple, lequel des douze premiers nombres anglais contient un
n
.Ensuite, vous pouvez implémenter cette table de recherche de manière concise en tant que:
avec le résultat
0
ou1
étant égal àFalse
àTrue
.L'idée est que le nombre magique stocke la table sous la forme d'une chaîne de bits
bin(3714)
=0b111010000010
, avec len
troisième chiffre (à partir de la fin) correspondant à la troisièmen
entrée de la table. On accède à lan
e entrée en décalant un peu le nombre d’n
espaces à droite et en prenant le dernier chiffre par&1
.Cette méthode de stockage est très efficace. Comparer aux alternatives
Vous pouvez avoir vos entrées multibits de magasin de table de recherche qui peuvent être extraites comme
extraire le bloc de quatre bits correspondant.
la source
Réduire deux boucles numériques en une
Supposons que vous parcouriez les cellules d'une
m*n
grille. Au lieu de deuxfor
boucles imbriquées , une pour la ligne et une des colonnes, il est généralement plus court d'utiliser une seule boucle pour parcourir lesm*n
cellules de la grille. Vous pouvez extraire la ligne et la colonne de la cellule à l'intérieur de la boucle.Code d'origine:
Code de golf:
En effet, vous itérer sur le produit cartésien des deux plages, codant pour la paire
(i,j)
commex=i*n+j
. Vous avez économisé unrange
appel coûteux et un niveau d'indentation dans la boucle. L'ordre des itérations est inchangé.Utilisez
//
plutôt que/
dans Python 3. Si vous vous référez ài
etj
plusieurs fois, il peut être plus rapide d’affecter leurs valeursi=k/n
,j=k%n
à l’intérieur de la boucle.la source
for i in range(m*n*o): do_stuff(i/n/o,i%(n*o)/o,i%o)
n
boucles: repl.it/EHwaitertools.product
peut être beaucoup plus concis que des boucles imbriquées, en particulier lors de la génération de produits cartésiens.a1, a2, b1, b2
sont des exemples du produit cartésien de'ab'
et'12'
Sauf si le jeton suivant commence par
e
ouE
. Vous pouvez supprimer l'espace après un numéro.Par exemple:
Devient:
L'utilisation de ceci dans des instructions compliquées d'une ligne peut sauver un nombre considérable de caractères.
EDIT: comme @marcog l’a souligné,
4or a
cela fonctionnera, mais pasa or4
parce que cela est confondu avec un nom de variable.la source
if(i,j)==(4,4):
est encore plus court et dans ce cas particulierif i==j==4:
4or a
fonctionne, mais pasa or4
0or
également ne fonctionne pas (0o
est un préfixe pour les nombres octaux).0 or x
on va toujours y retournerx
. Pourriez aussi bien couper le0 or
.0or
est bien dans le cadre d'un nombre plus long cependant.10 or x
est équivalent à10or x
.Pour un entier
n
, vous pouvez écriren+1
comme-~n
n-1
comme~-n
parce que le bit bascule
~x
est égal-1-x
. Ceci utilise le même nombre de caractères, mais peut indirectement couper des espaces ou des parenthèses pour la priorité des opérateurs.Comparer:
Les opérateurs
~
et unaire-
sont plus élevés que la priorité*
,/
,%
, à la différence binaire+
.la source
-~-x
enregistre un octet contre(1-x)
.a+b+1
pouvez écrire de manière plus concisea-~b
.n-i-1
est justen+~i
.Un bon moyen de convertir une liste itérable en une liste sur Python 3 :
imaginez que vous en ayez un, comme
Mais vous avez besoin d'une liste:
C'est très utile de faire une liste de caractères d'une chaîne
la source
*s,='abcde'
puiss
écraser mon python3 interactif avec un segfault :([*'abcde']
.Au lieu de
range(x)
, vous pouvez utiliser l'*
opérateur sur une liste de tout, si vous n'avez pas réellement besoin d'utiliser la valeur dei
:par opposition à
Si vous devez le faire plus de deux fois, vous pouvez affecter n'importe quelle variable à une variable et multiplier cette variable par la plage souhaitée:
Note : c'est souvent plus long que
exec"pass;"*8
ça, donc cette astuce ne devrait être utilisée que quand ce n'est pas une option.la source
[1]*8
est plus court querange(8)
, vous obtenez également de gagner un espace parce quefor i in[...
c'est légal tant que çafor i in range...
ne l'est pas".exec"pass;"*8
est nettement plus courte.r=1
,r*8
est 8, et vous ne pouvez pas parcourir un nombre. Je suppose que tu voulais direr=[1]
Vous pouvez utiliser le bon vieux smiley extraterrestre pour inverser les séquences:
la source
Déballage itératif étendu ("Affectation étoilée", Python 3 uniquement)
La meilleure façon de l'expliquer consiste à utiliser un exemple:
Nous avons déjà vu une utilisation pour cela: transformer une liste itérable en une liste dans Python 3 :
Voici quelques utilisations supplémentaires.
Obtenir le dernier élément d'une liste
Dans certaines situations, cela peut également être utilisé pour obtenir le premier élément à économiser sur les parenthèses:
Assigner une liste vide et d'autres variables
Supprimer le premier ou le dernier élément d'une liste non vide
Celles-ci sont plus courtes que les alternatives
L=L[1:]
etL.pop()
. Le résultat peut également être enregistré dans une liste différente.Astuces courtoisie de @grc
la source
a=1;L=[]
tellement de fois. Il est étonnant que vous puissiez enregistrer des caractères sur quelque chose d'aussi simple que cela.a,*L=1,
), mais cela sauve toujours un caractère :)a,*_,b=L
définir des littéraux en Python2.7
Vous pouvez écrire des ensembles comme celui-ci.
S={1,2,3}
Cela signifie également que vous pouvez vérifier l’appartenance à la{e}&S
place de cellee in S
qui enregistre un caractère.la source
if
s car il n'y a pas d'espaces (if{e}&S:
)not in
par{e}-S
ce tourPendant des siècles, cela me dérangeait de ne pas pouvoir trouver un moyen rapide d’obtenir l’alphabet complet. Si vous en utilisez
range
suffisammentR=range
dans votre programme, alorsest plus court que le naïf
, mais sinon c'est plus long d'un seul personnage. Cela me hantait que l'intelligent qui nécessitait une connaissance des valeurs ascii finissait par être plus bavard que simplement taper toutes les lettres.
Jusqu'à ce que je voie cette réponse pour l'alphabet de ma fille . Je ne peux pas suivre suffisamment l'historique de montage pour savoir si ce génie était l'oeuvre de l'OP ou s'il s'agissait d'une suggestion de la part d'un commentateur, mais c'est (je crois) le moyen le plus rapide de créer un éditable des 26 lettres. dans l'alphabet romain.
Si l'affaire n'a pas d'importance, vous pouvez supprimer un autre personnage en utilisant des majuscules:
J'utilise
map
beaucoup trop, je ne sais pas comment cela ne m'est jamais arrivé.la source
string.lowercase
- c’est pour cela qu’il est.ord('z')
)? En plus de la même longueur ... De plus, si vous avez besoin de caractères alphanumériques, remplacez-lestr.isalpha
dans la version de @ quintopia parstr.isalnum
. (Mais si vous n'avez besoin que d'une casse, la chaîne entière de 36 caractères ne dépasse pasfilter(str.isalnum,map(chr,range(90)))
.)R
, ma version est plus courte que la version originale:'%c'*26%tuple(R(97,123))
(seulement 24 caractères) si vous l'orthographiez,range
elle est aussi longue que l'alphabet - la version majuscule est plus courteBien que python ne possède pas d'instructions switch, vous pouvez les émuler avec des dictionnaires. Par exemple, si vous vouliez un commutateur comme celui-ci:
Vous pouvez utiliser des
if
déclarations, ou ceci:ou ca:
ce qui est mieux si tous les chemins de code sont des fonctions avec les mêmes paramètres.
Pour prendre en charge une valeur par défaut, procédez comme suit:
(ou ca:)
Un autre avantage est que si vous avez des redondances, vous pouvez simplement les ajouter après la fin du dictionnaire:
Et si vous vouliez simplement utiliser un commutateur pour renvoyer une valeur:
Vous pouvez simplement faire ceci:
la source
dict(s1=v1,s2=v2,...,sn=vn)
au lieu de{'s1':v1,'s2':v2,...,'sn':vn}
sauvegarder 2 * n-4 octets et vaut mieux si n> = 3Lorsque vous avez deux valeurs booléennes
a
etb
, si vous voulez savoir si les deuxa
etb
sont vraies, utilisez*
plutôtand
:contre
si l'une des valeurs est false, elle sera évaluée comme
0
dans cette instruction et une valeur entière n'est vraie que si elle est différente de zéro.la source
&
:a=b=False
,a&b
+
pouror
si vous pouvez garantira != -b
|
fonctionne dans toutes les situations.*
à la place deand
/&&
enregistre quelques octets dans de nombreuses langues.Exploiter les représentations de chaîne Python 2
Python 2 vous permet de convertir un objet
x
en représentation de chaîne`x`
pour un coût de 2 caractères seulement. Utilisez cette option pour les tâches plus faciles à effectuer sur la chaîne de l'objet que sur l'objet lui-même.Rejoindre des personnages
Avec une liste de caractères
l=['a','b','c']
, on peut produire en''.join(l)
tant que`l`[2::5]
, ce qui enregistre un octet.La raison est que
`l`
est"['a', 'b', 'c']"
(avec des espaces), on peut donc extraire les lettres avec une tranche de liste, en commençant que le second caractère zéro indexéa
, et en prenant chaque cinquième caractère à partir de là. Cela ne fonctionne pas pour joindre des chaînes multi-caractères ou des caractères d'échappement représentés comme'\n'
.Concaténer les chiffres
De même, étant donné une liste de chiffres non vide
l=[0,3,5]
, vous pouvez les concaténer dans une chaîne en'035'
tant que`l`[1::3]
.Cela évite de faire quelque chose comme
map(str,l)
. Notez qu'il doit s'agir de chiffres simples et que les flottants ne peuvent pas être1.0
mélangés. Cela échoue également sur la liste vide]
.Vérifier les négatifs
Maintenant, pour une tâche non-chaîne. Supposons que vous ayez une liste
l
de nombres réels et que vous souhaitiez vérifier si elle contient des nombres négatifs, produisant ainsi un booléen.Tu peux faire
qui vérifie la présence d’un signe négatif dans la chaîne rep. Ce plus court que l'un des
Pour le second,
min(l)<0
échouerait sur la liste vide, vous devez donc vous couvrir.la source
str(l)[2::5]
vaut 12 octets, contre 19 pour''.join(map(str,l))
. Une situation réelle où cela est arrivé (oùl
était une déclaration de générateur, pas une liste) m'a sauvé juste un octet ... qui en vaut toujours la peine!Une fonction d'une ligne peut être réalisée avec lambda:
peut être converti en (notez l'espace manquant
3and
et10or
)la source
c=lambda a:a+[-5,10][a<3]
. l'astuce et / ou l'astuce est plus utile lorsque vouselse:
peut être supprimé en tantreturn
qu'arrêt de l'exécution de la fonction. Ainsi, tout ce qui suit n'est exécuté que si laif
condition a échoué, autrement dit si laelse
condition est vraie. Ainsi,else
peut être omis en toute sécurité. (Expliqué en détail pour les néophytes)c=lambda a:a-5+15*(a<3)
les boucles allant jusqu’à 4 éléments peuvent être mieux pour fournir un tuple au lieu d’utiliser une plage
contre
la source
Ceil et sol
Si vous souhaitez obtenir le résultat arrondi pour une division, comme vous le feriez
//
pour le sol, vous pouvez utilisermath.ceil(3/2)
15 ou le nombre beaucoup plus court-(-3//2)
pour 8 octets.la source
n//1+1
lieu de ceil, mais cela signifie que ceil (n) = n + 1, mais cela devrait fonctionner pour toutes les valeurs non entièresround(x)
est(x+.5)//1
, +1 octet mais celui-ci commence par un(
, et six
est une somme consistant en une constante, il peut être utile.Utiliser
+=
au lieu deappend
etextend
peut être réduit à:
B,
crée ici un tuple à un élément qui peut être utilisé pour s'étendreA
comme[B]
dansA+=[B]
.peut être réduit à:
la source
return 0
oureturn 1
est équivalent àreturn False
oureturn True
.-x
plutôt quex*-1
.--8.32
plutôt que-8.32*-1
. Ou tout simplement8.32
...A+=B
B
est untuple
.Choisir l'un des deux nombres en fonction d'une condition
Vous savez déjà utiliser la sélection de liste
[x,y][b]
avec un booléenb
pour l'expression ternairey if b else x
. Les variablesx
,y
etb
peuvent également être des expressions, même si elles sont évaluéesx
ety
sont évaluées même si elles ne sont pas sélectionnées.Voici quelques optimisations possibles quand
x
ety
sont des nombres.[0,y][b] -> y*b
[1,y][b] -> y**b
[x,1][b] -> b or x
[x,x+1][b] -> x+b
[x,x-1][b] -> x-b
[1,-1][b] -> 1|-b
[x,~x][b] -> x^-b
[x,y][b] -> x+z*b
(ouy-z*b
), où z = yx.Vous pouvez également basculer
x
ety
si vous pouvez réécrireb
pour être sa négation à la place.la source
Utilisez ~ pour indexer à partir du dos d'une liste
Si
L
est une liste, utilisezL[~i]
pour obtenir lei
ième élément à l'arrière.C'est le
i
ième élément de l'inverse deL
. Le complément de bit~i
est égal à-i-1
, et corrige donc l'erreur de décalage par unL[-i]
.la source
PEP448 - Généralisations de supplémentaires
Avec la sortie de Python 3.5 , la manipulation de listes, de tuples, de décors et de dict est devenue encore plus golfeuse.
Transformer un itérable en un ensemble / une liste
Comparez les paires:
Plus court! Notez cependant que si vous souhaitez simplement convertir quelque chose en liste et l'affecter à une variable, la décompression itérative étendue normale est plus courte:
Une syntaxe similaire fonctionne pour les tuples:
ce qui ressemble à un décompression itérative prolongée, mais avec l'astérisque et une virgule de l'autre côté.
Rejoindre des listes / tuples
La décompression est légèrement plus courte que la concaténation si vous devez ajouter une liste / un nuplet aux deux côtés:
Imprimer le contenu de plusieurs listes
Ce n’est pas limité à
print
, mais c’est bien d’où viendra la plus grande partie du kilométrage parcouru. PEP448 permet maintenant le décompactage multiple, comme suit:Mise à jour de plusieurs éléments du dictionnaire
Cela n'arrivera probablement pas très souvent, mais la syntaxe peut être utilisée pour économiser sur la mise à jour de dictionnaires si vous mettez à jour au moins trois éléments:
Cela annule fondamentalement tout besoin de
dict.update
.la source
Changer
import *
enimport*
Si vous ne l'avez pas entendu,
import*
sauve des caractères!est seulement 1 caractère plus long que
import math as m
et vous arrivez à supprimer toutes les instances dem.
Même une utilisation ponctuelle est un économiseur!
la source
si la valeur de i est inutile:
ou
la source
for i in[0]*x:s+=input()
pour économiser un autre espace. En outre, vous pouvez supprimer l'espace entre l'exec et le premier guillemet à obtenirexec's+=input();'*x
for i in[0]*x:s+=input()