2009-11-13 26 views
38

Chaque si souvent ici je vois le code de quelqu'un et ce qui semble être un « one-liner », qui étant une déclaration d'une ligne qui effectue de façon standard une traditionnelle « if » ou « pour » œuvres en boucle.Les instructions 'if'/'for' d'une ligne sont-elles de bon style Python?

J'ai googlé trouver autour et ne peut pas vraiment ce genre de ceux que vous pouvez effectuer? Quelqu'un peut-il conseiller et de préférence donner quelques exemples?

Par exemple, pourrais-je faire cela en une ligne:

example = "example" 
if "exam" in example: 
    print "yes!" 

Ou:

for a in someList: 
    list.append(splitColon.split(a)) 
+1

Vous ne savez pas ce que vous cherchez ... pouvez-vous expliquer un peu plus? –

+0

Python ne possède-t-il pas ces trucs lambda étranges qui vous permettent de mettre beaucoup plus sur une ligne? Je ne vais pas les utiliser, bien sûr. Je préfère l'ancienne façon de faire les choses :-) – paxdiablo

+1

Je n'ai pas encore regardé lambda. Chaque fois que je vois ce mot dans une question, je clique rapidement sur un signet! – Federer

Répondre

50

Eh bien,

if "exam" in "example": print "yes!" 

Est-ce une amélioration? n °. Vous pouvez même ajouter d'autres déclarations au corps du if -clause en les séparant par un point-virgule. Je recommande contre que si.

+5

les points-virgules sont vitaux :-) – paxdiablo

+0

non seulement imprimerait "oui" serait mieux comme nous le savons "" examen "dans" exemple "'est vrai –

+8

Anurag: Il y a peut-être une raison pour laquelle Stephan a utilisé le mot" exemple "dans ce segment de code. – jmucchiello

18

Plus généralement, toutes les conditions suivantes sont syntaxiquement valides:

if condition: 
    do_something() 


if condition: do_something() 

if condition: 
    do_something() 
    do_something_else() 

if condition: do_something(); do_something_else() 

... etc.

+2

enfin des points-virgules .. que je cherchais! – holms

+0

Pour être clair, n'utilisez pas de point-virgule comme celui-ci! J'essayais juste de répondre complètement à la question. –

+0

une raison pour cela? Cela simplifie ma vie sur certaines instructions if, suivies des instructions print, suivies de sys.exit() – holms

3

Vous pouvez faire tout cela en une ligne en omettant la variable example:

if "exam" in "example": print "yes!" 
6

Python vous permet de mettre la clause en retrait sur la même ligne si elle est seule ligne:

if "exam" in example: print "yes!" 

def squared(x): return x * x 

class MyException(Exception): pass 
+1

L'exemple n'est pas défini. Il a besoin de citations. –

+2

Quelle partie de l'exemple n'avez-vous pas compris? Chaque fragment de code n'a pas besoin de déclarer toutes ses variables. – jmucchiello

11

un exemple d'une fonctionnalité de langage qui est non seulement de la ligne suppression des sauts, mais toujours pas convaincu que c'est plus claire que la version plus détaillée

a = 1 si x> 15 autre 2

7
for a in someList: 
    list.append(splitColon.split(a)) 

Vous pouvez réécrire le ci-dessus:

newlist = [splitColon.split(a) for a in someList] 
+2

+1 pour la compréhension de la liste – cschol

+0

Dans le premier cas, vous utilisez 'list' et dans la seconde vous utilisez' newlist'. Y a-t-il une raison pour le changement? – cregox

+1

@Cawas, oh, en effet. L'OP a utilisé "list" dans son code. Ce n'est pas une bonne pratique pour * ombrer * les noms de fonction ou de type intégrés, c'est-à-dire la "liste". C'est pourquoi j'ai utilisé "newlist" dans ma réponse. –

38

J'ai trouvé que dans la plupart des cas qui font des clauses de bloc sur une ligne C'est une mauvaise idée.

Il, encore une fois comme une généralité, réduire la qualité de la forme du code. Forme de code de haute qualité est une fonctionnalité de langage clé pour python.

Dans certains cas, python offrira des façons todo choses sur une ligne qui sont nettement plus pythonique. Des choses telles que ce que Nick D mentionné à la compréhension de la liste:

newlist = [splitColon.split(a) for a in someList] 

bien, sauf si vous avez besoin d'une liste réutilisable spécifiquement vous pouvez envisager d'utiliser un générateur à la place

listgen = (splitColon.split(a) for a in someList) 

note la plus grande différence entre les deux est que vous ne pouvez pas répéter sur un générateur, mais il est plus efficace à utiliser.

Il est également construit dans l'opérateur ternaire dans les versions modernes de python qui vous permettent de faire des choses comme

string_to_print = "yes!" if "exam" in "example" else "" 
print string_to_print 

ou

iterator = max_value if iterator > max_value else iterator 

Certaines personnes peuvent trouver ces plus lisible et utilisable que le similaire if (condition): bloc.

En ce qui concerne le code, il s'agit du style de code et de la norme avec l'équipe sur laquelle vous travaillez. C'est le plus important, mais en général, je déconseille les blocs de ligne car la forme du code en python est très importante.

+0

J'ai trouvé l'opérateur ternaire utile pour des cas tels que 'logging.info (" Found% d% s ", num_results," result "si num_results == 1 sinon" results ")'. – Dennis

+2

En fait, j'aime vraiment le ternaire de python. Une fois que vous y êtes habitué, il est beaucoup plus lisible que la plupart des langues. Il rend l'historique '? : 'semble assez archaïque. –

+0

Merci, cela m'a vraiment aidé! –

0

Plongez dans python a un peu où il parle de ce qu'il appelle le and-or trick, ce qui semble être un moyen efficace pour entasser la logique complexe dans une seule ligne. Fondamentalement, il simule l'opérateur ternaire en c, en vous donnant un moyen de tester la vérité et de retourner une valeur basée sur cela. Par exemple:

>>> (1 and ["firstvalue"] or ["secondvalue"])[0] 
"firstvalue" 
>>> (0 and ["firstvalue"] or ["secondvalue"])[0] 
"secondvalue" 
+1

Attention: cela ne simule pas * l'opérateur ternaire de C. '1? 0: 2' est égal à '0', mais' 1 et 0 ou 2' est égal à '2'. Il est beaucoup plus sûr d'utiliser une autre construction qui est faite précisément dans ce but: '0 if 1 else 2' (qui * donnera * 0 '). – Stephan202

+0

(Le problème ici est que '0' est évalué à 'Faux'. La raison pour laquelle votre code * fonctionne *, c'est parce que' 'firstvalue '' évalue à 'True'.) – Stephan202

+0

Cette astuce est antérieure à l'opérateur ternaire, et est une approximation au mieux, étant donné ses problèmes avec les valeurs dont la valeur booléenne est False. – PaulMcG

3

Les anciennes versions de Python ne permettraient pas une simple déclaration unique après for ...:if ...: ou bloc similaire déclarations liminaires.

Je vois que l'on peut avoir plusieurs instructions simples sur la même ligne que l'une de celles-ci. Cependant, il existe diverses combinaisons qui ne fonctionnent pas. Par exemple, nous pouvons:

for i in range(3): print "Here's i:"; print i 

... mais, d'autre part, nous ne pouvons pas:

for i in range(3): if i % 2: print "That's odd!" 

Nous pouvons:

x=10 
while x > 0: print x; x-=1 

... mais nous pouvons 't:

x=10; while x > 0: print x; x-=1 

... et ainsi de suite.

Dans tous les cas, tous ces éléments sont considérés comme extrêmement NON-pythoniques. Si vous écrivez un code comme celui-ci, alors l'expérience de Pythonistas aura probablement une vision faible de vos compétences.

Il est marginalement acceptable de combiner plusieurs instructions sur une ligne dans certains cas. Par exemple:

x=0; y=1 

... ou même:

if some_condition(): break 

... pour de simples breakcontinue et même return déclarations ou assigments.

En particulier si l'on a besoin d'utiliser une série de elif on pourrait utiliser quelque chose comme:

if  keystroke == 'q': break 
elif keystroke == 'c': action='continue' 
elif keystroke == 'd': action='delete' 
# ... 
else:      action='ask again' 

... vous pourriez ne pas agacer trop vos collègues. (Cependant, les chaînes de elif comme ce cri doivent être refactorisées dans une table de répartition ...un dictionnaire qui pourrait ressembler plus:

dispatch = { 
    'q': foo.break, 
    'c': foo.continue, 
    'd': foo.delete 
    } 


# ... 
while True: 
    key = SomeGetKey() 
    dispatch.get(key, foo.try_again)() 
0

Ceci est un exemple de "si d'autre" avec des actions.

>>> def fun(num): 
    print 'This is %d' % num 
>>> fun(10) if 10 > 0 else fun(2) 
this is 10 
OR 
>>> fun(10) if 10 < 0 else 1 
1