Les traits cachés de Python [fermé]
quelles sont les fonctionnalités moins connues mais utiles du langage de programmation Python?
- essayez de limiter les réponses à Python core.
- une caractéristique par réponse.
- donne un exemple et une brève description de la fonctionnalité, pas seulement un lien vers la documentation.
- étiqueter la caractéristique en utilisant un titre comme première ligne.
Liens rapides vers les réponses:
- "1519230920 Argument De" Déballage
- bretelles
- Opérateurs De Comparaison De Chaîne
- Décorateurs
- Argument par Défaut de Pièges / Dangers de la Mutable arguments par Défaut
- descripteurs
- Dictionnaire par défaut
.get
valeur - Docstring Tests
- Points De Suspension Découpage De La Syntaxe
- énumération
- Pour/else
- fonction comme argument iter ()
- Générateur d'expressions
-
import this
- À La Place Valeur D'Échange
- "1519230920 de la Liste des" étapes
-
__missing__
éléments - Multi-lignes " Regex
- , du nom de la chaîne de mise en forme
- liste Imbriquée/générateur interprétations de la
- de Nouveaux types à l'exécution
-
.pth
fichiers - ROT13 "Codage de 1519240920"
- Débogage Regex
- envoi aux générateurs
- "1519230920 Onglet" Achèvement Interactif Interprète
- Expression Ternaire
-
try/except/else
- déballage+
print()
fonction -
with
déclaration
30 réponses
opérateurs de comparaison chaînage:
>>> x = 5
>>> 1 < x < 10
True
>>> 10 < x < 20
False
>>> x < 10 < x*10 < 100
True
>>> 10 > x <= 9
True
>>> 5 == x > 4
True
dans le cas où vous pensez qu'il fait 1 < x
, qui sort comme True
, et puis comparer True < 10
, qui est aussi True
, alors non, ce n'est vraiment pas ce qui se passe (voir le dernier exemple.) Cela se traduit en fait par 1 < x and x < 10
, et x < 10 and 10 < x * 10 and x*10 < 100
, mais avec moins de Dactylographie et chaque terme n'est évalué qu'une seule fois.
obtenez l'arbre d'analyse Python regex pour déboguer votre regex.
les expressions régulières sont une grande caractéristique de python, mais les déboguer peut être pénible, et il est trop facile d'obtenir un regex erroné.
heureusement, python peut imprimer l'arbre regex parse, en passant le drapeau caché expérimental et non documenté re.DEBUG
(en fait, 128) à re.compile
.
>>> re.compile("^\[font(?:=(?P<size>[-+][0-9]{1,2}))?\](.*?)[/font]",
re.DEBUG)
at at_beginning
literal 91
literal 102
literal 111
literal 110
literal 116
max_repeat 0 1
subpattern None
literal 61
subpattern 1
in
literal 45
literal 43
max_repeat 1 2
in
range (48, 57)
literal 93
subpattern 2
min_repeat 0 65535
any None
in
literal 47
literal 102
literal 111
literal 110
literal 116
une fois que vous comprenez la syntaxe, vous pouvez repérer vos erreurs. On y voit que j'ai oublié d'échapper au []
dans [/font]
.
bien sûr, vous pouvez le combiner avec tous les drapeaux que vous voulez, comme commenté regexes:
>>> re.compile("""
^ # start of a line
\[font # the font tag
(?:=(?P<size> # optional [font=+size]
[-+][0-9]{1,2} # size specification
))?
\] # end of tag
(.*?) # text between the tags
\[/font\] # end of the tag
""", re.DEBUG|re.VERBOSE|re.DOTALL)
énumérer
envelopper un itérable avec enumerate et il donnera l'article avec son index.
par exemple:
>>> a = ['a', 'b', 'c', 'd', 'e']
>>> for index, item in enumerate(a): print index, item
...
0 a
1 b
2 c
3 d
4 e
>>>
, les Références:
la Création de générateurs d'objets
si vous écrivez
x=(n for n in foo if bar(n))
vous pouvez sortir le générateur et l'affecter à x. Maintenant, cela signifie que vous pouvez faire
for n in x:
L'avantage, c'est que vous n'avez pas besoin de stockage intermédiaire, dont vous aurez besoin si vous l'avez fait
x = [n for n in foo if bar(n)]
Dans certains cas, cela peut conduire à vitesse importante.
vous pouvez ajoutez de nombreuses instructions if à la fin du générateur, en reproduisant essentiellement les boucles emboîtées:
>>> n = ((a,b) for a in range(0,2) for b in range(4,6))
>>> for i in n:
... print i
(0, 4)
(0, 5)
(1, 4)
(1, 5)
iter() peut prendre un callable argument
par exemple:
def seek_next_line(f):
for c in iter(lambda: f.read(1),'\n'):
pass
la fonction iter(callable, until_value)
appelle à plusieurs reprises callable
et donne son résultat jusqu'à ce que until_value
soit retourné.
soyez prudent avec les arguments par défaut mutables
>>> def foo(x=[]):
... x.append(1)
... print x
...
>>> foo()
[1]
>>> foo()
[1, 1]
>>> foo()
[1, 1, 1]
à la place, vous devriez utiliser une valeur sentinelle indiquant "non indiqué" et remplacer par le mutable que vous voulez par défaut:
>>> def foo(x=None):
... if x is None:
... x = []
... x.append(1)
... print x
>>> foo()
[1]
>>> foo()
[1]
l'Envoi de valeurs dans le générateur de fonctions . Par exemple, ayant cette fonction:
def mygen():
"""Yield 5 until something else is passed back via send()"""
a = 5
while True:
f = (yield a) #yield a and possibly get f in return
if f is not None:
a = f #store the new value
vous pouvez:
>>> g = mygen()
>>> g.next()
5
>>> g.next()
5
>>> g.send(7) #we send this back to the generator
7
>>> g.next() #now it will yield 7 until we send something else
7
si vous n'aimez pas utiliser whitespace pour dénoter les portées, vous pouvez utiliser le C-style {} en émettant:
from __future__ import braces
L'étape de l'argument dans la tranche des opérateurs. Par exemple:
a = [1,2,3,4,5]
>>> a[::2] # iterate over the whole list in 2-increments
[1,3,5]
le cas spécial x[::-1]
est un idiome utile pour "X inversé".
>>> a[::-1]
[5,4,3,2,1]
décorateurs
décorateurs permettent d'envelopper une fonction ou une méthode dans une autre fonction qui peut ajouter des fonctionnalités, modifier des arguments ou des résultats, etc. Vous écrivez décorateurs une ligne au-dessus de la définition de la fonction, en commençant par un signe "at" (@).
exemple montre un print_args
décorateur qui imprime les arguments de la fonction décorée avant de l'appeler:
>>> def print_args(function):
>>> def wrapper(*args, **kwargs):
>>> print 'Arguments:', args, kwargs
>>> return function(*args, **kwargs)
>>> return wrapper
>>> @print_args
>>> def write(text):
>>> print text
>>> write('foo')
Arguments: ('foo',) {}
foo
Le pour les...syntaxe else (voir ) http://docs.python.org/ref/for.html )
for i in foo:
if i == 0:
break
else:
print("i was never 0")
le bloc "else" sera normalement exécuté à la fin de la boucle for, à moins que la coupure ne soit appelée.
le code ci-dessus pourrait être émulé comme suit:
found = False
for i in foo:
if i == 0:
found = True
break
if not found:
print("i was never 0")
à partir de 2.5 dicts ont une méthode spéciale __missing__
qui est invoquée pour les éléments manquants:
>>> class MyDict(dict):
... def __missing__(self, key):
... self[key] = rv = []
... return rv
...
>>> m = MyDict()
>>> m["foo"].append(1)
>>> m["foo"].append(2)
>>> dict(m)
{'foo': [1, 2]}
il y a aussi une sous-classe de dict dans collections
appelée defaultdict
qui fait à peu près la même chose mais appelle une fonction sans arguments pour les éléments non existants:
>>> from collections import defaultdict
>>> m = defaultdict(list)
>>> m["foo"].append(1)
>>> m["foo"].append(2)
>>> dict(m)
{'foo': [1, 2]}
je recommande de convertir de tels dicts en dicts réguliers avant de les passer à des fonctions qui ne s'attendent pas à de telles sous-classes. Beaucoup d'utilisations de code d[a_key]
et saisit des erreurs-clés pour vérifier s'il existe un élément qui ajouterait un nouvel élément au dict.
échange de valeurs en place
>>> a = 10
>>> b = 5
>>> a, b
(10, 5)
>>> a, b = b, a
>>> a, b
(5, 10)
le côté droit de la cession est une expression qui crée un nouveau tuple. Le côté gauche de la cession déballe immédiatement ce tuple (non référencé) des noms a
et b
.
après la cession, le nouveau tuple n'est pas référencé et marqué pour la collecte des ordures, et les valeurs liées à a
et b
ont été échanger.
comme noté dans la section tutoriel Python sur les structures de données ,
notez que l'assignation multiple est en fait juste une combinaison d'empaquetage tuple et de déballage séquentiel.
expressions régulières déchiffrables
en Python vous pouvez diviser une expression régulière sur plusieurs lignes, nommer vos correspondances et insérer des commentaires.
exemple de syntaxe verbeuse (de plongée en Python ):
>>> pattern = """
... ^ # beginning of string
... M{0,4} # thousands - 0 to 4 M's
... (CM|CD|D?C{0,3}) # hundreds - 900 (CM), 400 (CD), 0-300 (0 to 3 C's),
... # or 500-800 (D, followed by 0 to 3 C's)
... (XC|XL|L?X{0,3}) # tens - 90 (XC), 40 (XL), 0-30 (0 to 3 X's),
... # or 50-80 (L, followed by 0 to 3 X's)
... (IX|IV|V?I{0,3}) # ones - 9 (IX), 4 (IV), 0-3 (0 to 3 I's),
... # or 5-8 (V, followed by 0 to 3 I's)
... $ # end of string
... """
>>> re.search(pattern, 'M', re.VERBOSE)
exemple de correspondance de noms (de Regular Expression HOWTO )
>>> p = re.compile(r'(?P<word>\b\w+\b)')
>>> m = p.search( '(((( Lots of punctuation )))' )
>>> m.group('word')
'Lots'
vous pouvez aussi verbosely Ecrire un regex sans utiliser re.VERBOSE
grâce à la chaîne concaténation littérale.
>>> pattern = (
... "^" # beginning of string
... "M{0,4}" # thousands - 0 to 4 M's
... "(CM|CD|D?C{0,3})" # hundreds - 900 (CM), 400 (CD), 0-300 (0 to 3 C's),
... # or 500-800 (D, followed by 0 to 3 C's)
... "(XC|XL|L?X{0,3})" # tens - 90 (XC), 40 (XL), 0-30 (0 to 3 X's),
... # or 50-80 (L, followed by 0 to 3 X's)
... "(IX|IV|V?I{0,3})" # ones - 9 (IX), 4 (IV), 0-3 (0 to 3 I's),
... # or 5-8 (V, followed by 0 to 3 I's)
... "$" # end of string
... )
>>> print pattern
"^M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$"
argument de fonction déballage
vous pouvez déballer une liste ou un dictionnaire comme arguments de fonction en utilisant *
et **
.
par exemple:
def draw_point(x, y):
# do some magic
point_foo = (3, 4)
point_bar = {'y': 3, 'x': 2}
draw_point(*point_foo)
draw_point(**point_bar)
raccourci très utile car les listes, tuples et dicts sont largement utilisés comme conteneurs.
ROT13 est un encodage valide pour le code source, lorsque vous utilisez la déclaration de codage de droite en haut du fichier de code:
#!/usr/bin/env python
# -*- coding: rot13 -*-
cevag "Uryyb fgnpxbiresybj!".rapbqr("rot13")
la Création de nouveaux types dans une dynamique de manière
>>> NewType = type("NewType", (object,), {"x": "hello"})
>>> n = NewType()
>>> n.x
"hello"
qui est exactement le même que
>>> class NewType(object):
>>> x = "hello"
>>> n = NewType()
>>> n.x
"hello"
Probablement pas la chose la plus utile, mais bon à savoir.
Edit : nom fixe du nouveau type, devrait être NewType
pour être la même chose exacte qu'avec class
déclaration.
Modifier : Corrigé le titre pour plus de précision décrire la fonctionnalité.
Contexte, les gestionnaires et les with
" Déclaration
introduit dans PEP 343 , un context manager est un objet qui agit comme un contexte d'exécution pour une suite d'énoncés.
puisque la fonctionnalité utilise de nouveaux mots-clés, elle est introduite progressivement: elle est disponible en python 2.5 via la directive __future__
. Python 2.6 et au-dessus (y compris Python 3), Il est disponible par défaut.
j'ai utilisé le "avec" statement beaucoup parce que je pense que c'est une construction très utile, voici une démo rapide:
from __future__ import with_statement
with open('foo.txt', 'w') as f:
f.write('hello!')
ce qui se passe ici dans les coulisses, c'est que les méthodes avec" statement appellent les méthodes spéciales __enter__
et __exit__
sur l'objet file. Détails de l'Exception sont également passés __exit__
si tout exception a été déclenchée à partir de l'instruction du corps, permettant la gestion des exceptions pour y arriver.
ce que cela fait pour vous dans ce cas particulier, c'est qu'il garantit que le dossier est clos lorsque l'exécution tombe en dehors du champ d'application de la suite with
, peu importe si cela se produit normalement ou si une exception a été jetée. Il s'agit essentiellement d'une manière de supprimer le code de traitement d'exception commun.
autres cas d'usage courant: verrouillage avec des threads et des transactions de base de données.
les dictionnaires ont une méthode get ()
Les dictionnairesont une méthode " get ()". Si vous faites d['key'] et que key n'est pas là, vous obtenez une exception. Si vous ne d.get('key'), vous obtenez en retour Aucun si la " clé " n'est pas là. Vous pouvez ajouter un deuxième argument pour récupérer cet élément au lieu de None, par exemple: D. get ('key', 0).
c'est génial pour des choses comme additionner des nombres:
sum[value] = sum.get(value, 0) + 1
descripteurs
ils sont la magie derrière tout un tas de fonctionnalités Python.
lorsque vous utilisez un accès en pointillé pour rechercher un membre (par exemple, X. y), Python cherche d'abord le membre dans le dictionnaire d'instance. Si elle ne l'est pas, il le cherche dans la classe dictionnaire. Si il la trouve dans la classe dictionnaire, et l'objet implémente le protocole descripteur, au lieu de simplement retourner, Python exécute. Un descripteur est une classe qui met en œuvre les méthodes __get__
, __set__
, ou __delete__
.
Voici comment vous implémentez votre propre version (en lecture seule) de la propriété en utilisant des descripteurs:
class Property(object):
def __init__(self, fget):
self.fget = fget
def __get__(self, obj, type):
if obj is None:
return self
return self.fget(obj)
et que vous souhaitez utiliser comme un construit-dans la propriété():
class MyClass(object):
@Property
def foo(self):
return "Foo!"
les descripteurs sont utilisés en Python pour implémenter des propriétés, des méthodes liées, des méthodes statiques, des méthodes de classe et des fentes, entre autres choses. Comprendre le rend facile de voir pourquoi beaucoup de choses qui auparavant ressemblaient à des "excentricités" Python sont comme elles sont.
Raymond Hettinger a un excellent tutoriel qui fait un bien meilleur travail de les décrire que moi.
Cession Conditionnelle
x = 3 if (y == 1) else 2
C'est exactement ce que cela ressemble: "attribuer 3 x si y est 1, sinon l'affectation de 2 à x". Notez que les parens ne sont pas nécessaires, mais je les aime pour la lisibilité. Vous pouvez aussi l'enchaîner si vous avez quelque chose de plus compliqué:
x = 3 if (y == 1) else 2 if (y == -1) else 1
bien qu'à un certain point, il va un peu trop loin.
Notez que vous pouvez utiliser si ... d'autre, dans tout expression. Par exemple:
(func1 if y == 1 else func2)(arg1, arg2)
ici func1 sera appelé si y est 1 et func2, sinon. Dans les deux cas, la fonction correspondante sera appelée avec les arguments arg1 et arg2.
de la même manière, ce qui suit est également valable:
x = (class1 if y == 1 else class2)(arg1, arg2)
où les catégories 1 et 2 sont deux classes.
Doctest : documentation et essais unitaires en même temps.
exemple extrait de la documentation Python:
def factorial(n):
"""Return the factorial of n, an exact integer >= 0.
If the result is small enough to fit in an int, return an int.
Else return a long.
>>> [factorial(n) for n in range(6)]
[1, 1, 2, 6, 24, 120]
>>> factorial(-1)
Traceback (most recent call last):
...
ValueError: n must be >= 0
Factorials of floats are OK, but the float must be an exact integer:
"""
import math
if not n >= 0:
raise ValueError("n must be >= 0")
if math.floor(n) != n:
raise ValueError("n must be exact integer")
if n+1 == n: # catch a value like 1e300
raise OverflowError("n too large")
result = 1
factor = 2
while factor <= n:
result *= factor
factor += 1
return result
def _test():
import doctest
doctest.testmod()
if __name__ == "__main__":
_test()
mise en forme Nommée
% - formatage prend un dictionnaire(s'applique également %i / %s etc. validation.)
>>> print "The %(foo)s is %(bar)i." % {'foo': 'answer', 'bar':42}
The answer is 42.
>>> foo, bar = 'question', 123
>>> print "The %(foo)s is %(bar)i." % locals()
The question is 123.
et comme locals() est aussi un dictionnaire, vous pouvez simplement passer cela comme un dict et avoir des substitutions de % à partir de vos variables locales. Je pense que c'est mal vu, mais simplifie les choses..
Nouvelle Mise En Forme Du Style
>>> print("The {foo} is {bar}".format(foo='answer', bar=42))
pour ajouter plus de modules python (en particulier des modules tiers), la plupart des gens semblent utiliser des variables D'environnement PYTHONPATH ou ils ajoutent des liens symboliques ou des répertoires dans leurs répertoires site-paquets. Une autre façon consiste à utiliser *.la pth fichiers. Voici l'explication officielle de python doc:
"le moyen Le plus pratique [modifier le chemin de recherche de python] est d'ajouter un chemin fichier de configuration vers un répertoire c'est déjà sur Python chemin, généralement, à la .../ site-packages/ répertoire. Fichiers de configuration des chemins ont une extension .pth, et chacun ligne doit contenir un seul chemin qui sera ajouté à sys.chemin. (Parce les nouveaux chemins sont ajoutés à sys.chemin, modules dans le Ajouté les répertoires ne supplantent pas la norme module. Cela signifie que vous ne pouvez pas utiliser cette mécanisme d'installation fixe versions de modules standard.) "
Exception else clause:
try:
put_4000000000_volts_through_it(parrot)
except Voom:
print "'E's pining!"
else:
print "This parrot is no more!"
finally:
end_sketch()
l'utilisation de la clause else est préférable à l'ajout de code supplémentaire à la clause try parce qu'elle évite d'attraper accidentellement une exception qui n'a pas été soulevée par le code étant protégé par l'essai ... sauf instruction.
Re-déclenchement d'exceptions :
# Python 2 syntax
try:
some_operation()
except SomeError, e:
if is_fatal(e):
raise
handle_nonfatal(e)
# Python 3 syntax
try:
some_operation()
except SomeError as e:
if is_fatal(e):
raise
handle_nonfatal(e)
la déclaration' raise 'sans argument dans un gestionnaire d'erreurs dit à Python de relancer l'exception avec le traceback original intact , vous permettant de dire " Oh, désolé, désolé, Je ne voulais pas attraper ça, désolé, désolé."
si vous souhaitez imprimer, stocker ou jouer avec le traceback original, vous pouvez l'obtenir avec sys.exc_info(), et l'impression comme Python le ferait avec le module' traceback'.
messages principaux:)
import this
# btw look at this module's source :)
Le Zen de Python, par Tim Peters
beau est mieux que laid.
Explicite est mieux qu'implicites.
Simple vaut mieux que complexe.
Complexe est mieux que compliqué.
L'appartement est mieux que imbriqués.
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 la praticité bat la pureté.
Les erreurs ne doivent jamais passer silencieusement.
Sauf s'il est explicitement réduit au silence.
Face à l'ambiguïté, refusez la tentation de deviner. Il devrait y avoir un, et de préférence seulement une façon évidente de le faire.
Bien que ce ne soit pas évident au début, sauf si vous êtes Hollandais.
Est maintenant mieux que jamais.
Bien que n'est jamais souvent mieux que droit maintenant.
Si l'implémentation est difficile à expliquer, c'est une mauvaise idée.
Si l' la mise en œuvre est facile à expliquer, il peut être une bonne idée.
Les Namespaces sont une excellente idée -- faisons-en plus!
Interactive Interprète Onglet Achèvement
try:
import readline
except ImportError:
print "Unable to load readline module."
else:
import rlcompleter
readline.parse_and_bind("tab: complete")
>>> class myclass:
... def function(self):
... print "my function"
...
>>> class_instance = myclass()
>>> class_instance.<TAB>
class_instance.__class__ class_instance.__module__
class_instance.__doc__ class_instance.function
>>> class_instance.f<TAB>unction()
vous devrez également définir une variable d'environnement PYTHONSTARTUP.
liste imbriquée compréhensions et expressions génératrices:
[(i,j) for i in range(3) for j in range(i) ]
((i,j) for i in range(4) for j in range(i) )
ceux-ci peuvent remplacer d'énormes morceaux de code à boucle imbriquée.
surcharge de L'opérateur pour le set
builtin:
>>> a = set([1,2,3,4])
>>> b = set([3,4,5,6])
>>> a | b # Union
{1, 2, 3, 4, 5, 6}
>>> a & b # Intersection
{3, 4}
>>> a < b # Subset
False
>>> a - b # Difference
{1, 2}
>>> a ^ b # Symmetric Difference
{1, 2, 5, 6}
plus de détails de la bibliothèque standard référence: Set Types