Quelles sont les fonctionnalités moins connues mais utiles du langage de programmation Python?
.get
_ valeurimport this
__missing__
_ items.pth
_try/except/else
print()
fonctionwith
list
avec sum()
.La fonction intégrée sum()
peut être utilisée pour __add__
list
s, offrant ainsi un moyen pratique d'aplatir un list
de list
s:
_Python 2.7.1 (r271:86832, May 27 2011, 21:41:45)
[GCC 4.2.1 (Apple Inc. build 5664)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> l = [[1, 2, 3], [4, 5], [6], [7, 8, 9]]
>>> sum(l, [])
[1, 2, 3, 4, 5, 6, 7, 8, 9]
_
C'est un tueur de Alex Martelli . Toutes les instances de l'état Borg
share. Cela supprime la nécessité d'utiliser le modèle singleton (les instances importent peu lorsque l'état est partagé) et est plutôt élégant (mais est plus compliqué avec de nouvelles classes).
La valeur de foo
peut être réaffectée à tout moment et tout sera mis à jour, vous pouvez même réaffecter le dict entier. Borg est le nom parfait, lisez plus ici .
class Borg:
__shared_state = {'foo': 'bar'}
def __init__(self):
self.__dict__ = self.__shared_state
# rest of your class here
C'est parfait pour partager un eventlet.GreenPool afin de contrôler la concurrence.
Attributs Top Secret
>>> class A(object): pass
>>> a = A()
>>> setattr(a, "can't touch this", 123)
>>> dir(a)
['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', "can't touch this"]
>>> a.can't touch this # duh
File "<stdin>", line 1
a.can't touch this
^
SyntaxError: EOL while scanning string literal
>>> getattr(a, "can't touch this")
123
>>> setattr(a, "__class__.__name__", ":O")
>>> a.__class__.__name__
'A'
>>> getattr(a, "__class__.__name__")
':O'
Attributs ajoutés dynamiquement
Cela peut être utile si vous envisagez d'ajouter des attributs à vos classes simplement en les appelant. Cela peut être fait en remplaçant la fonction membre __getattribute__
qui est appelée lorsque l'opérande point est utilisé. Voyons un exemple de classe fictive:
_class Dummy(object):
def __getattribute__(self, name):
f = lambda: 'Hello with %s'%name
return f
_
Lorsque vous instanciez un objet factice et effectuez un appel de méthode, vous obtenez les éléments suivants:
_>>> d = Dummy()
>>> d.b()
'Hello with b'
_
Enfin, vous pouvez même définir l'attribut sur votre classe afin qu'il puisse être défini de manière dynamique. Cela peut être utile si vous travaillez avec Python cadres Web et souhaitez effectuer des requêtes en analysant le nom de l'attribut.
J'ai un Gist sur github avec ce code simple et son équivalent sur Ruby créé par un ami.
Prends soin de toi!
>>> node = namedtuple('node', "a b")
>>> node(1,2) + node(5,6)
(1, 2, 5, 6)
>>> (node(1,2), node(5,6))
(node(a=1, b=2), node(a=5, b=6))
>>>
Quelques expériences supplémentaires pour répondre aux commentaires:
>>> from collections import namedtuple
>>> from operator import *
>>> mytuple = namedtuple('A', "a b")
>>> yourtuple = namedtuple('Z', "x y")
>>> mytuple(1,2) + yourtuple(5,6)
(1, 2, 5, 6)
>>> q = [mytuple(1,2), yourtuple(5,6)]
>>> q
[A(a=1, b=2), Z(x=5, y=6)]
>>> reduce(operator.__add__, q)
(1, 2, 5, 6)
Donc, namedtuple
est un intéressant sous-type de Tuple
.
Création d'un dictionnaire de deux séquences contenant des données associées
In [15]: t1 = (1, 2, 3)
In [16]: t2 = (4, 5, 6)
In [17]: dict (Zip(t1,t2))
Out[17]: {1: 4, 2: 5, 3: 6}
threading.enumerate () donne accès à tous les objets Thread du système et sys._current_frames () renvoie les cadres de pile actuels de tous les threads du système. Combinez donc ces deux éléments pour obtenir le vidage de la pile de style Java:
def dumpstacks(signal, frame):
id2name = dict([(th.ident, th.name) for th in threading.enumerate()])
code = []
for threadId, stack in sys._current_frames().items():
code.append("\n# Thread: %s(%d)" % (id2name[threadId], threadId))
for filename, lineno, name, line in traceback.extract_stack(stack):
code.append('File: "%s", line %d, in %s' % (filename, lineno, name))
if line:
code.append(" %s" % (line.strip()))
print "\n".join(code)
import signal
signal.signal(signal.SIGQUIT, dumpstacks)
Faites cela au début d’un programme multi-thread python et vous aurez accès à tout moment à l’état actuel des threads en envoyant un SIGQUIT. Vous pouvez également choisir signal.SIGUSR1 ou signal.SIGUSR2.
pdb - Le Python Debugger
En tant que programmeur, l'une des premières choses dont vous avez besoin pour développer des programmes sérieux est un débogueur. Python possède un module intégré disponible en tant que module appelé pdb (pour "Python DeBugger", bien sûr!).
inspect le module est également une fonctionnalité intéressante.
Le rechargement des modules permet un style de "codage en direct". Mais les instances de classe ne sont pas mises à jour. Voici pourquoi et comment le contourner. Rappelez-vous, tout, oui, tout est un objet.
>>> from a_package import a_module
>>> cls = a_module.SomeClass
>>> obj = cls()
>>> obj.method()
(old method output)
Maintenant, vous modifiez la méthode dans a_module.py et souhaitez mettre à jour votre objet.
>>> reload(a_module)
>>> a_module.SomeClass is cls
False # Because it just got freshly created by reload.
>>> obj.method()
(old method output)
Voici un moyen de le mettre à jour (mais considérez-le avec des ciseaux):
>>> obj.__class__ is cls
True # it's the old class object
>>> obj.__class__ = a_module.SomeClass # pick up the new class
>>> obj.method()
(new method output)
Ceci est "en cours d'exécution avec des ciseaux" car l'état interne de l'objet peut être différent de celui attendu par la nouvelle classe. Cela fonctionne pour des cas vraiment simples, mais au-delà, pickle
est votre ami. Il est toujours utile de comprendre pourquoi cela fonctionne, cependant.
Les opérateurs peuvent être appelés en tant que fonctions:
from operator import add
print reduce(add, [1,2,3,4,5,6])
récursion infinie dans la liste
>>> a = [1,2]
>>> a.append(a)
>>> a
[1, 2, [...]]
>>> a[2]
[1, 2, [...]]
>>> a[2][2][2][2][2][2][2][2][2] == a
True
... que dict.get()
a un valeur par défaut de None, évitant ainsi KeyErrors:
In [1]: test = { 1 : 'a' }
In [2]: test[2]
---------------------------------------------------------------------------
<type 'exceptions.KeyError'> Traceback (most recent call last)
<ipython console> in <module>()
<type 'exceptions.KeyError'>: 2
In [3]: test.get( 2 )
In [4]: test.get( 1 )
Out[4]: 'a'
In [5]: test.get( 2 ) == None
Out[5]: True
et même pour spécifier ceci "sur les lieux":
In [6]: test.get( 2, 'Some' ) == 'Some'
Out[6]: True
Et vous pouvez utiliser setdefault(
) pour avoir une valeur définie et renvoyée si elle n'existe pas:
>>> a = {}
>>> b = a.setdefault('foo', 'bar')
>>> a
{'foo': 'bar'}
>>> b
'bar
Les barres obliques inverses dans les chaînes brutes peuvent toujours échapper aux guillemets. Regarde ça:
>>> print repr(r"aaa\"bbb")
'aaa\\"bbb'
Notez que les barres obliques inverses et les guillemets doubles sont présents dans la dernière chaîne.
Par conséquent, vous ne pouvez pas terminer une chaîne brute avec une barre oblique inverse:
>>> print repr(r"C:\")
SyntaxError: EOL while scanning string literal
>>> print repr(r"C:\"")
'C:\\"'
Cela est dû au fait que les chaînes brutes ont été implémentées pour faciliter l'écriture d'expressions régulières et non pour écrire les chemins Windows. Lisez une longue discussion à ce sujet sur le site Gotcha - barres obliques inverses dans les noms de fichiers Windows .
Les objets de petit intères (-5 .. 256) n'ont jamais été créés deux fois:
>>> a1 = -5; b1 = 256
>>> a2 = -5; b2 = 256
>>> id(a1) == id(a2), id(b1) == id(b2)
(True, True)
>>>
>>> c1 = -6; d1 = 257
>>> c2 = -6; d2 = 257
>>> id(c1) == id(c2), id(d1) == id(d2)
(False, False)
>>>
Edition: Les objets de liste ne sont jamais détruits (uniquement les objets dans les listes). Python possède un tableau dans lequel il conserve jusqu'à 80 listes vides. Lorsque vous détruisez un objet de liste - python le place dans ce tableau et lorsque vous créez une nouvelle liste - python, la dernière liste insérée provient de ce tableau:
>>> a = [1,2,3]; a_id = id(a)
>>> b = [1,2,3]; b_id = id(b)
>>> del a; del b
>>> c = [1,2,3]; id(c) == b_id
True
>>> d = [1,2,3]; id(d) == a_id
True
>>>
Tranches en lvalues. Ce tamis d'Eratosthenes produit une liste qui a le nombre premier ou 0. Les éléments sont supprimés avec l'attribution de tranche dans la boucle.
def eras(n):
last = n + 1
sieve = [0,0] + list(range(2, last))
sqn = int(round(n ** 0.5))
it = (i for i in xrange(2, sqn + 1) if sieve[i])
for i in it:
sieve[i*i:last:i] = [0] * (n//i - i + 1)
return filter(None, sieve)
Pour travailler, la tranche de gauche doit se voir attribuer une liste de droite de la même longueur.
Arrondir les entiers: Python a la fonction round, qui renvoie les nombres de type double:
>>> print round(1123.456789, 4)
1123.4568
>>> print round(1123.456789, 2)
1123.46
>>> print round(1123.456789, 0)
1123.0
Cette fonction a une merveilleuse propriété magique:
>>> print round(1123.456789, -1)
1120.0
>>> print round(1123.456789, -2)
1100.0
Si vous avez besoin d'un entier, utilisez int pour convertir le type:
>>> print int(round(1123.456789, -2))
1100
>>> print int(round(8359980, -2))
8360000
Merci Gregor .
Manipulation de la limite de récursivité
Obtenir ou définir la profondeur maximale de récursivité avec sys.getrecursionlimit () & sys.setrecursionlimit ().
Nous pouvons le limiter pour éviter un débordement de pile causé par une récursion infinie.
Vous pouvez remplacer la mro d'une classe avec une métaclasse
>>> class A(object):
... def a_method(self):
... print("A")
...
>>> class B(object):
... def b_method(self):
... print("B")
...
>>> class MROMagicMeta(type):
... def mro(cls):
... return (cls, B, object)
...
>>> class C(A, metaclass=MROMagicMeta):
... def c_method(self):
... print("C")
...
>>> cls = C()
>>> cls.c_method()
C
>>> cls.a_method()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'C' object has no attribute 'a_method'
>>> cls.b_method()
B
>>> type(cls).__bases__
(<class '__main__.A'>,)
>>> type(cls).__mro__
(<class '__main__.C'>, <class '__main__.B'>, <class 'object'>)
C'est probablement caché pour une bonne raison. :)
Possibilité de remplacer même des éléments tels que la suppression de fichiers, l'ouverture de fichiers, etc. - manipulation directe de la bibliothèque de langues. C'est un avantage énorme quand test. Vous n'avez pas à tout emballer dans des conteneurs compliqués. Remplacez simplement une fonction/méthode et partez. Ceci est également appelé singe-patcher.
tranches et mutabilité
Copier des listes
>>> x = [1,2,3]
>>> y = x[:]
>>> y.pop()
3
>>> y
[1, 2]
>>> x
[1, 2, 3]
Remplacement des listes
>>> x = [1,2,3]
>>> y = x
>>> y[:] = [4,5,6]
>>> x
[4, 5, 6]
Nouvelle liaison des paramètres de fonction imbriquée
def create_printers(n):
for i in xrange(n):
def printer(i=i): # Doesn't work without the i=i
print i
yield printer
Python 2.x ignore les virgules s'il se trouve après le dernier élément de la séquence:
>>> a_Tuple_for_instance = (0,1,2,3,)
>>> another_Tuple = (0,1,2,3)
>>> a_Tuple_for_instance == another_Tuple
True
Une virgule finale fait en sorte qu'un élément entre parenthèses soit traité comme une séquence:
>>> a_Tuple_with_one_element = (8,)
Les méthodes ou fonctions intégrées n'implémentent pas le protocole de descripteur, ce qui rend impossible la réalisation de tâches comme celle-ci:
>>> class C(object):
... id = id
...
>>> C().id()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: id() takes exactly one argument (0 given)
Cependant, vous pouvez créer un petit descripteur de liaison qui rend cela possible:
>>> from types import MethodType
>>> class bind(object):
... def __init__(self, callable):
... self.callable = callable
... def __get__(self, obj, type=None):
... if obj is None:
... return self
... return MethodType(self.callable, obj, type)
...
>>> class C(object):
... id = bind(id)
...
>>> C().id()
7414064
Vous pouvez décorer des fonctions avec des classes - en remplaçant la fonction par une instance de classe:
class countCalls(object):
""" decorator replaces a function with a "countCalls" instance
which behaves like the original function, but keeps track of calls
>>> @countCalls
... def doNothing():
... pass
>>> doNothing()
>>> doNothing()
>>> print doNothing.timesCalled
2
"""
def __init__ (self, functionToTrack):
self.functionToTrack = functionToTrack
self.timesCalled = 0
def __call__ (self, *args, **kwargs):
self.timesCalled += 1
return self.functionToTrack(*args, **kwargs)
Je ne sais pas où (ou si) cela se trouve dans la documentation Python, mais pour python 2.x (au moins 2.5 et 2.6, ce que je viens d'essayer), le print
déclaration peut être appelée avec parenthenses. Cela peut être utile si vous voulez pouvoir facilement porter du code Python 2. 2.x sur Python 3.x.
Exemple: print('We want Moshiach Now')
devrait imprimer We want Moshiach Now
travailler en python 2.5, 2.6 et 3.x.
De même, l'opérateur not
peut être appelé avec des parenthenses dans Python 2 et 3: not False
et not(False)
doivent tous deux renvoyer True
.
Les parenthèses peuvent également fonctionner avec d'autres instructions et opérateurs.
EDIT: Ce n'est PAS une bonne idée de placer des parenthenses autour des opérateurs not
(et probablement de tout autre opérateur), car cela peut créer des situations surprenantes, comme ça (c'est parce que les parenthenses sont vraiment autour du 1
):
>>> (not 1) == 9
False
>>> not(1) == 9
True
Cela peut aussi fonctionner, pour certaines valeurs (je pense que ce n'est pas un nom d'identifiant valide), comme ceci: not'val'
doit renvoyer False
, et print'We want Moshiach Now'
devrait renvoyer We want Moshiach Now
. (mais not552
lèverait un NameError puisqu'il s'agit d'un nom d'identifiant valide).
Dict Compréhensions
>>> {i: i**2 for i in range(5)}
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
Trop paresseux pour initialiser tous les champs d'un dictionnaire? Aucun problème:
Dans Python> 2.3:
from collections import defaultdict
Dans Python <= 2.3:
def defaultdict(type_):
class Dict(dict):
def __getitem__(self, key):
return self.setdefault(key, type_())
return Dict()
Dans n'importe quelle version:
d = defaultdict(list)
for stuff in lots_of_stuff:
d[stuff.name].append(stuff)
UPDATE:
Merci Ken Arnold . J'ai réimplémenté une version plus sophistiquée de defaultdict. Il devrait se comporter exactement comme celui de la bibliothèque standard .
def defaultdict(default_factory, *args, **kw):
class defaultdict(dict):
def __missing__(self, key):
if default_factory is None:
raise KeyError(key)
return self.setdefault(key, default_factory())
def __getitem__(self, key):
try:
return dict.__getitem__(self, key)
except KeyError:
return self.__missing__(key)
return defaultdict(*args, **kw)
Objets Monkeypatching
Chaque objet de Python a un membre __dict__
, qui stocke les attributs de l'objet. Donc, vous pouvez faire quelque chose comme ça:
class Foo(object):
def __init__(self, arg1, arg2, **kwargs):
#do stuff with arg1 and arg2
self.__dict__.update(kwargs)
f = Foo('arg1', 'arg2', bar=20, baz=10)
#now f is a Foo object with two extra attributes
Cela pourrait être exploité pour ajouter à la fois des attributs et des fonctions aux objets. Cela peut également être exploité pour créer un type struct
rapide.
class struct(object):
def __init__(**kwargs):
self.__dict__.update(kwargs)
s = struct(foo=10, bar=11, baz="i'm a string!')
Outil d'analyse comparative intégré simple
La bibliothèque standard Python est livrée avec un module d’analyse comparative très simple à utiliser appelé "timeit". Vous pouvez même l'utiliser à partir de la ligne de commande pour voir laquelle de plusieurs constructions de langage est la plus rapide.
Par exemple.,
% python -m timeit 'r = range(0, 1000)' 'for i in r: pass'
10000 loops, best of 3: 48.4 usec per loop
% python -m timeit 'r = xrange(0, 1000)' 'for i in r: pass'
10000 loops, best of 3: 37.4 usec per loop
Set Compréhensions
>>> {i**2 for i in range(5)}
set([0, 1, 4, 16, 9])
En plus de ce qui a été mentionné précédemment par haridsv :
>>> foo = bar = baz = 1
>>> foo, bar, baz
(1, 1, 1)
il est également possible de faire ceci:
>>> foo, bar, baz = 1, 2, 3
>>> foo, bar, baz
(1, 2, 3)
Liste des compréhensions
Comparez le plus traditionnel (sans compréhension de liste):
foo = []
for x in xrange(10):
if x % 2 == 0:
foo.append(x)
à:
foo = [x for x in xrange(10) if x % 2 == 0]
Voici 2 oeufs de Pâques:
Un dans python lui-même:
>>> import __hello__
Hello world...
Et un autre dans le module Werkzeug
, qui est un peu compliqué à révéler, le voici:
En regardant le code source de Werkzeug
, dans werkzeug/__init__.py
, une ligne devrait attirer votre attention:
'werkzeug._internal': ['_easteregg']
Si vous êtes un peu curieux, vous devriez jeter un coup d'œil à la werkzeug/_internal.py
. Vous y trouverez une fonction _easteregg()
qui prend une application wsgi en argument, elle contient également des bases64. données codées et 2 fonctions imbriquées, qui semblent faire quelque chose de spécial si un argument nommé macgybarchakku
est trouvé dans la chaîne de requête.
Donc, pour révéler cet oeuf de Pâques, il semble que vous ayez besoin d'envelopper une application dans la fonction _easteregg()
, allons:
from werkzeug import Request, Response, run_simple
from werkzeug import _easteregg
@Request.application
def application(request):
return Response('Hello World!')
run_simple('localhost', 8080, _easteregg(application))
Maintenant, si vous exécutez l'application et visitez http: // localhost: 8080 /? Macgybarchakk , vous devriez voir l'oeuf de Pâques.
Si vous utilisez des descripteurs sur vos classes, Python contourne complètement __dict__
pour cette clé, ce qui en fait un endroit agréable pour stocker ces valeurs:
>>> class User(object):
... def _get_username(self):
... return self.__dict__['username']
... def _set_username(self, value):
... print 'username set'
... self.__dict__['username'] = value
... username = property(_get_username, _set_username)
... del _get_username, _set_username
...
>>> u = User()
>>> u.username = "foo"
username set
>>> u.__dict__
{'username': 'foo'}
Cela aide à garder dir()
clean.
L'idiome Pythonic x = ... if ... else ...
est de loin supérieur à x = ... and ... or ...
et voici pourquoi:
Bien que la déclaration
x = 3 if (y == 1) else 2
Est équivalent à
x = y == 1 and 3 or 2
si vous utilisez le langage x = ... and ... or ...
, vous risquez un jour d'être piqué par cette situation délicate:
x = 0 if True else 1 # sets x equal to 0
et n'est donc pas équivalent à
x = True and 0 or 1 # sets x equal to 1
Pour plus d'informations sur la manière appropriée de procéder, voir Fonctionnalités cachées de Python .
Exposition de tampons mutables
Utilisation du Python protocole de tampon pour exposer les tampons modifiables orientés octets dans Python (2.5/2.6) .
(Désolé, pas de code ici. Nécessite l'utilisation de l'API C de bas niveau ou du module d'adaptateur existant).
getattr
prend un troisième paramètregetattr(obj, attribute_name, default)
est comme:
try:
return obj.attribute
except AttributeError:
return default
sauf que attribute_name
peut être n'importe quelle chaîne.
Cela peut être vraiment utile pour frappe de canard . Peut-être que vous avez quelque chose comme:
class MyThing:
pass
class MyOtherThing:
pass
if isinstance(obj, (MyThing, MyOtherThing)):
process(obj)
(btw, isinstance(obj, (a,b))
signifie isinstance(obj, a) or isinstance(obj, b)
.)
Lorsque vous créez un nouveau type d’objet, vous devez l’ajouter à ce tuple où qu’il se produise. (Cette construction pose également des problèmes lors du rechargement de modules ou de l'importation du même fichier sous deux noms. Cela se produit plus que ce que les gens aiment bien admettre.) Mais vous pourriez plutôt dire:
class MyThing:
processable = True
class MyOtherThing:
processable = True
if getattr(obj, 'processable', False):
process(obj)
Ajoutez l'héritage et cela s'améliore encore: tous vos exemples d'objets pouvant être traités peuvent hériter de
class Processable:
processable = True
mais vous n'avez pas à convaincre tout le monde d'hériter de votre classe de base, il vous suffit de définir un attribut.
__ getattr __ ()
getattr
est un moyen vraiment agréable de créer des classes génériques, ce qui est particulièrement utile si vous écrivez une API. Par exemple, dans FogBugz Python API , getattr
permet de transmettre de manière transparente les appels de méthode au service Web:
class FogBugz:
...
def __getattr__(self, name):
# Let's leave the private stuff to Python
if name.startswith("__"):
raise AttributeError("No such attribute '%s'" % name)
if not self.__handlerCache.has_key(name):
def handler(**kwargs):
return self.__makerequest(name, **kwargs)
self.__handlerCache[name] = handler
return self.__handlerCache[name]
...
Lorsque quelqu'un appelle FogBugz.search(q='bug')
, il n'appelle pas une méthode search
. Au lieu de cela, getattr
gère l'appel en créant une nouvelle fonction qui englobe la méthode makerequest
, qui crée la demande HTTP appropriée à l'API Web. Toutes les erreurs seront envoyées par le service Web et renvoyées à l'utilisateur.
La première classe de tout ("tout est objet") et le chaos que cela peut causer.
>>> x = 5
>>> y = 10
>>>
>>> def sq(x):
... return x * x
...
>>> def plus(x):
... return x + x
...
>>> (sq,plus)[y>x](y)
20
La dernière ligne crée un tuple contenant les deux fonctions, puis évalue y> x (True) et l’utilise comme un index du tuple (en le convertissant en un entier int, 1), puis appelle cette fonction avec le paramètre y et affiche le résultat.
Si vous renvoyez un objet avec un index (une liste, par exemple), vous pouvez ajouter des crochets supplémentaires à la fin du message. si le contenu était appelable, plus de parenthèses, etc. Pour plus de perversion, utilisez le résultat du code comme ceci comme expression dans un autre exemple (c'est-à-dire remplacez y> x par ce code):
(sq,plus)[y>x](y)[4](x)
Cela présente deux facettes de Python - la philosophie du "tout est un objet" poussée à l'extrême, et les méthodes par lesquelles une utilisation incorrecte ou mal conçue de la syntaxe du langage peut conduire à un code spaghetti complètement illisible et non maintenable cela correspond à une seule expression.
Tuple décompactant pour les boucles, les compréhensions de liste et les expressions de générateur:
>>> l=[(1,2),(3,4)]
>>> [a+b for a,b in l ]
[3,7]
Utile dans cet idiome pour itérer des paires (clé, données) dans des dictionnaires:
d = { 'x':'y', 'f':'e'}
for name, value in d.items(): # one can also use iteritems()
print "name:%s, value:%s" % (name,value)
impressions:
name:x, value:y
name:f, value:e
Avec un volume de travail minime, le module de filetage devient incroyablement facile à utiliser. Ce décorateur modifie une fonction afin qu'elle s'exécute dans son propre thread, renvoyant une instance de classe d'espace réservé au lieu de son résultat habituel. Vous pouvez rechercher la réponse en cochant placeolder.result ou l'attendre en appelant placeholder.awaitResult ().
def threadify(function):
"""
exceptionally simple threading decorator. Just:
>>> @threadify
... def longOperation(result):
... time.sleep(3)
... return result
>>> A= longOperation("A has finished")
>>> B= longOperation("B has finished")
A doesn't have a result yet:
>>> print A.result
None
until we wait for it:
>>> print A.awaitResult()
A has finished
we could also wait manually - half a second more should be enough for B:
>>> time.sleep(0.5); print B.result
B has finished
"""
class thr (threading.Thread,object):
def __init__(self, *args, **kwargs):
threading.Thread.__init__ ( self )
self.args, self.kwargs = args, kwargs
self.result = None
self.start()
def awaitResult(self):
self.join()
return self.result
def run(self):
self.result=function(*self.args, **self.kwargs)
return thr
Python a des exceptions pour des choses très inattendues:
Importations
Cela vous permet d'importer une alternative s'il manque une lib
try:
import json
except ImportError:
import simplejson as json
Itération
Les boucles for le font en interne et attrapent StopIteration:
iter([]).next()
Traceback (most recent call last):
File "<pyshell#4>", line 1, in <module>
iter(a).next()
StopIteration
Assertion
>>> try:
... assert []
... except AssertionError:
... print "This list should not be empty"
This list should not be empty
Bien que cela soit plus détaillé pour une vérification, plusieurs vérifications combinant des exceptions et des opérateurs booléens avec le même message d'erreur peuvent être abrégées de cette façon.
Il n'y a pas de secrets dans Python;)
Combinez le déballage avec la fonction d'impression:
# in 2.6 <= python < 3.0, 3.0 + the print function is native
from __future__ import print_function
mylist = ['foo', 'bar', 'some other value', 1,2,3,4]
print(*mylist)
Méthode de remplacement pour l'instance d'objet
Vous pouvez remplacer les méthodes d'instances d'objet déjà créées. Il vous permet de créer une instance d'objet avec différentes fonctionnalités (exceptionnelles):
>>> class C(object):
... def fun(self):
... print "C.a", self
...
>>> inst = C()
>>> inst.fun() # C.a method is executed
C.a <__main__.C object at 0x00AE74D0>
>>> instancemethod = type(C.fun)
>>>
>>> def fun2(self):
... print "fun2", self
...
>>> inst.fun = instancemethod(fun2, inst, C) # Now we are replace C.a by fun2
>>> inst.fun() # ... and fun2 is executed
fun2 <__main__.C object at 0x00AE74D0>
Comme nous pouvons, C.a
a été remplacé par fun2()
dans inst
instance (self
n'a pas changé).
Alternativement, nous pouvons utiliser le module new
, mais il est déprécié depuis Python 2.6:
>>> def fun3(self):
... print "fun3", self
...
>>> import new
>>> inst.fun = new.instancemethod(fun3, inst, C)
>>> inst.fun()
fun3 <__main__.C object at 0x00AE74D0>
Node: Cette solution ne doit pas être utilisée comme remplacement général du mécanisme d'héritage! Mais cela peut être très pratique dans certaines situations spécifiques (débogage, moquage).
Attention: Cette solution ne fonctionnera pas pour les types intégrés ni pour les nouvelles classes de style utilisant des slots.
Profitant de la nature dynamique de python pour avoir une configuration de fichiers d’applications dans la syntaxe python. Par exemple, si vous aviez les éléments suivants dans un fichier de configuration:
{
"name1": "value1",
"name2": "value2"
}
Ensuite, vous pourriez trivialement le lire comme:
config = eval(open("filename").read())
Accéder aux éléments du dictionnaire en tant qu'attributs (propriétés). donc si a1 = AttrDict () a la clé 'nom' -> au lieu de a1 ['nom'], nous pouvons facilement accéder à l'attribut name de a1 en utilisant -> a1.name
class AttrDict(dict):
def __getattr__(self, name):
if name in self:
return self[name]
raise AttributeError('%s not found' % name)
def __setattr__(self, name, value):
self[name] = value
def __delattr__(self, name):
del self[name]
person = AttrDict({'name': 'John Doe', 'age': 66})
print person['name']
print person.name
person.name = 'Frodo G'
print person.name
del person.age
print person
Méthodes spéciales
Identifiant Unicode en Python3:
>>> 'Unicode字符_تكوين_Variable'.isidentifier()
True
>>> Unicode字符_تكوين_Variable='Python3 rules!'
>>> Unicode字符_تكوين_Variable
'Python3 rules!'
n module exporte TOUT dans son espace de noms
Y compris les noms importés d'autres modules!
# this is "answer42.py"
from operator import *
from inspect import *
Maintenant, testez ce qui est importable depuis le module.
>>> import answer42
>>> answer42.__dict__.keys()
['gt', 'imul', 'ge', 'setslice', 'ArgInfo', 'getfile', 'isCallable', 'getsourcelines', 'CO_OPTIMIZED', 'le', 're', 'isgenerator', 'ArgSpec', 'imp', 'lt', 'delslice', 'BlockFinder', 'getargspec', 'currentframe', 'CO_NOFREE', 'namedtuple', 'rshift', 'string', 'getframeinfo', '__file__', 'strseq', 'iconcat', 'getmro', 'mod', 'getcallargs', 'isub', 'getouterframes', 'isdatadescriptor', 'modulesbyfile', 'setitem', 'truth', 'Attribute', 'div', 'CO_NESTED', 'ixor', 'getargvalues', 'ismemberdescriptor', 'getsource', 'isMappingType', 'eq', 'index', 'xor', 'sub', 'getcomments', 'neg', 'getslice', 'isframe', '__builtins__', 'abs', 'getmembers', 'mul', 'getclasstree', 'irepeat', 'is_', 'getitem', 'indexOf', 'Traceback', 'findsource', 'ModuleInfo', 'ipow', 'TPFLAGS_IS_ABSTRACT', 'or_', 'joinseq', 'is_not', 'itruediv', 'getsourcefile', 'dis', 'os', 'iand', 'countOf', 'getinnerframes', 'pow', 'pos', 'and_', 'lshift', '__name__', 'sequenceIncludes', 'isabstract', 'isbuiltin', 'invert', 'contains', 'add', 'isSequenceType', 'irshift', 'types', 'tokenize', 'isfunction', 'not_', 'istraceback', 'getmoduleinfo', 'isgeneratorfunction', 'getargs', 'CO_GENERATOR', 'cleandoc', 'classify_class_attrs', 'EndOfBlock', 'walktree', '__doc__', 'getmodule', 'isNumberType', 'ilshift', 'ismethod', 'ifloordiv', 'formatargvalues', 'indentsize', 'getmodulename', 'inv', 'Arguments', 'iscode', 'CO_NEWLOCALS', 'formatargspec', 'iadd', 'getlineno', 'imod', 'CO_VARKEYWORDS', 'ne', 'idiv', '__package__', 'CO_VARARGS', 'attrgetter', 'methodcaller', 'truediv', 'repeat', 'trace', 'isclass', 'ior', 'ismethoddescriptor', 'sys', 'isroutine', 'delitem', 'stack', 'concat', 'getdoc', 'getabsfile', 'ismodule', 'linecache', 'floordiv', 'isgetsetdescriptor', 'itemgetter', 'getblock']
>>> from answer42 import getmembers
>>> getmembers
<function getmembers at 0xb74b2924>
>>>
C'est une bonne raison de ne pas utiliser from x import *
et de définir __all__ =
.
insérer vs ajouter
pas une fonctionnalité, mais peut être intéressant
supposons que vous souhaitiez insérer des données dans une liste, puis l'inverser. la chose la plus facile est
count = 10 ** 5
nums = []
for x in range(count):
nums.append(x)
nums.reverse()
alors vous pensez: que diriez-vous d'insérer les nombres depuis le début, à la place? alors:
count = 10 ** 5
nums = []
for x in range(count):
nums.insert(0, x)
mais il s'avère être 100 fois plus lent! si nous fixons count = 10 ** 6, ce sera 1 000 fois plus lent; c'est parce que insert est O (n ^ 2), alors que append est O (n).
la raison de cette différence est que insert doit déplacer chaque élément d'une liste chaque fois qu'il est appelé; simplement ajouter à la fin de la liste que des éléments
Vous pouvez affecter plusieurs variables à la même valeur
>>> foo = bar = baz = 1
>>> foo, bar, baz
(1, 1, 1)
Utile pour initialiser plusieurs variables sur Aucune, de manière compacte.
Simulation de l'opérateur tertiaire à l'aide de et et ou.
et et ou les opérateurs dans python renvoient les objets eux-mêmes plutôt que des booléens. Ainsi:
In [18]: a = True
In [19]: a and 3 or 4
Out[19]: 3
In [20]: a = False
In [21]: a and 3 or 4
Out[21]: 4
Cependant, Py 2.5 semble avoir ajouté un opérateur tertiaire explicite
In [22]: a = 5 if True else '6'
In [23]: a
Out[23]: 5
Eh bien, cela fonctionne si vous êtes sûr que votre vraie clause n’est pas évaluée à False. exemple:
>>> def foo():
... print "foo"
... return 0
...
>>> def bar():
... print "bar"
... return 1
...
>>> 1 and foo() or bar()
foo
bar
1
Pour bien faire les choses, il vous faut juste un peu plus:
>>> (1 and [foo()] or [bar()])[0]
foo
0
Cependant, ce n'est pas aussi joli. si votre version de python le prend en charge, utilisez l'opérateur conditionnel.
>>> foo() if True or bar()
foo
0
Imprimer des chaînes multilignes, une page à la fois
Fonctionnalité pas vraiment utile cachée dans la classe site._Printer
dont l'objet license
est une instance. Ce dernier, lorsqu'il est appelé, imprime la licence Python. On peut créer un autre objet du même type en passant une chaîne - par ex. le contenu d'un fichier - comme second argument, et appelez-le:
type(license)(0,open('textfile.txt').read(),0)()
Cela imprimerait le contenu du fichier divisé en un certain nombre de lignes à la fois:
...
file row 21
file row 22
file row 23
Hit Return for more, or q (and Return) to quit:
Tout est dynamique
"Il n'y a pas de temps de compilation". Tout dans Python correspond à l'exécution. Un module est "défini" en exécutant la source du module de haut en bas, exactement comme un script, et l'espace de nom résultant est l'espace attribut du module. De même, une classe est "définie" en exécutant le corps de la classe de haut en bas, et l'espace de noms résultant est l'espace attribut de la classe. Un corps de classe peut contenir du code complètement arbitraire, y compris des instructions d'importation, des boucles et d'autres instructions de classe. Créer une classe, une fonction ou même un module "dynamiquement", comme on le demande parfois, n'est pas difficile; en fait, il est impossible d'éviter, puisque tout est "dynamique".
Les variables qui commencent, mais ne se terminent pas, par un double soulignement deviennent privées, et pas seulement par convention. En réalité, __var se transforme en _Classname__var, où Classname est la classe dans laquelle la variable a été créée. Ils ne sont pas hérités et ne peuvent pas être annulés.
>>> class A:
... def __init__(self):
... self.__var = 5
... def getvar(self):
... return self.__var
...
>>> a = A()
>>> a.__var
Traceback (most recent call last):
File "", line 1, in
AttributeError: A instance has no attribute '__var'
>>> a.getvar()
5
>>> dir(a)
['_A__var', '__doc__', '__init__', '__module__', 'getvar']
>>>
Le fait que TOUT soit un objet, et en tant que tel, est extensible. Je peux ajouter des variables de membre en tant que métadonnées à une fonction que je définis:
>>> def addInts(x,y):
... return x + y
>>> addInts.params = ['integer','integer']
>>> addInts.returnType = 'integer'
Cela peut être très utile pour écrire des tests unitaires dynamiques, par exemple.
bien que peu pythonique, vous pouvez écrire dans un fichier avec print
print>>outFile, 'I am Being Written'
Ce formulaire est parfois appelé "chevron
write()
décrite ci-dessus. Avec cette forme étendue, les expressions suivantes sont imprimées dans cet objet fichier. Si la première expression est évaluée àNone
, alorssys.stdout
est utilisé comme fichier de sortie.
Objets en contexte booléen
Les n-uplets, les listes, les dict, les chaînes et bien d'autres objets vides sont équivalents à False dans un contexte booléen (et non-vides sont équivalents à True).
empty_Tuple = ()
empty_list = []
empty_dict = {}
empty_string = ''
empty_set = set()
if empty_Tuple or empty_list or empty_dict or empty_string or empty_set:
print 'Never happens!'
Cela permet aux opérations logiques de renvoyer l'un de ses opérandes au lieu de True/False, ce qui est utile dans certaines situations:
s = t or "Default value" # s will be assigned "Default value"
# if t is false/empty/none
Si vous avez renommé une classe dans votre application dans laquelle vous chargez des fichiers sauvegardés par l'utilisateur via Pickle et qu'une des classes renommées est stockée dans l'ancienne sauvegarde de l'utilisateur, vous ne pourrez pas charger ce fichier.
Cependant, ajoutez simplement une référence à la définition de votre classe et tout va bien:
par exemple, avant:
class Bleh:
pass
maintenant,
class Blah:
pass
le fichier sauvegardé de votre utilisateur contient donc une référence à Bleh, qui n'existe pas en raison du renommage. Le correctif?
Bleh = Blah
facile!
Support fonctionnel.
Générateurs et expressions de générateur, en particulier.
Ruby a refait ce courant, mais Python peut le faire aussi bien. Pas aussi omniprésent dans les bibliothèques que dans Ruby, ce qui est dommage, mais j'aime mieux la syntaxe, c'est plus simple.
Parce qu'ils ne sont pas aussi omniprésents, je ne vois pas autant d'exemples de leur utilité, mais ils m'ont permis d'écrire du code plus propre et plus efficace.
Il existe un idiome commun dans Python consistant à désigner des méthodes et d'autres membres de la classe qui ne sont pas destinés à faire partie de l'API externe de la classe en leur attribuant des noms commençant par des traits de soulignement. C'est pratique et fonctionne très bien dans la pratique, mais cela donne une fausse impression que Python ne supporte pas l'encapsulation vraie de code privé et/ou de données. En fait, Python vous donne automatiquement fermetures lexicales , ce qui facilite grandement l'encapsulation des données de manière beaucoup plus efficace lorsque la situation le justifie vraiment. Voici un exemple artificiel d'une classe qui utilise cette technique:
class MyClass(object):
def __init__(self):
privateData = {}
self.publicData = 123
def privateMethod(k):
print privateData[k] + self.publicData
def privilegedMethod():
privateData['foo'] = "hello "
privateMethod('foo')
self.privilegedMethod = privilegedMethod
def publicMethod(self):
print self.publicData
Et voici un exemple artificiel de son utilisation:
>>> obj = MyClass()
>>> obj.publicMethod()
123
>>> obj.publicData = 'World'
>>> obj.publicMethod()
World
>>> obj.privilegedMethod()
hello World
>>> obj.privateMethod()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'MyClass' object has no attribute 'privateMethod'
>>> obj.privateData
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'MyClass' object has no attribute 'privateData'
La clé est que privateMethod
et privateData
ne sont pas du tout des attributs d'obj. Ils ne peuvent donc pas être consultés de l'extérieur et ne sont pas affichés dans dir()
ou similaire. Ce sont des variables locales dans le constructeur, complètement inaccessibles en dehors de __init__
. Cependant, en raison de la magie des fermetures, il s’agit en réalité de variables par instance ayant la même durée de vie que l’objet auquel elles sont associées, même s’il n’est pas possible d’y accéder de l’extérieur sauf (dans cet exemple) en invoquant privilegedMethod
. Souvent, ce type d’encapsulation très stricte est excessif, mais il peut parfois être très utile de garder une API ou un espace de noms parfaitement propre.
Dans Python 2.x, le seul moyen d'avoir un état privé mutable est d'utiliser un objet mutable (tel que dict dans cet exemple). Beaucoup de gens ont remarqué à quel point cela pouvait être agaçant. Python 3.x supprimera cette restriction en introduisant le mot clé nonlocal
décrit dans PEP 3104 .
Un moyen simple de tester si une clé est dans un dict:
>>> 'key' in { 'key' : 1 }
True
>>> d = dict(key=1, key2=2)
>>> if 'key' in d:
... print 'Yup'
...
Yup
** Using sets to reference contents in sets of frozensets**
Comme vous le savez probablement, les ensembles sont modifiables et ne peuvent donc pas être utilisés. Il est donc nécessaire d’utiliser frozensets si vous souhaitez créer un ensemble d’ensembles (ou d’utiliser des ensembles comme clés de dictionnaire):
>>> fabc = frozenset('abc')
>>> fxyz = frozenset('xyz')
>>> mset = set((fabc, fxyz))
>>> mset
{frozenset({'a', 'c', 'b'}), frozenset({'y', 'x', 'z'})}
Cependant, il est possible de tester l'adhésion et de supprimer/supprimer des membres en utilisant uniquement des ensembles ordinaires:
>>> abc = set('abc')
>>> abc in mset
True
>>> mset.remove(abc)
>>> mset
{frozenset({'y', 'x', 'z'})}
Pour citer les docs Python Standard Library:
Notez que l'argument
elem
des méthodes__contains__()
,remove()
etdiscard()
peut être un ensemble. Pour prendre en charge la recherche d'un groupe de frozens équivalent, le jeuelem
est muté temporairement pendant la recherche, puis restauré. Au cours de la recherche, l'ensembleelem
ne doit pas être lu ou muté car il n'a pas de valeur explicite.
Malheureusement, et peut-être étonnamment, il n'en va pas de même pour les dictionnaires:
>>> mdict = {fabc:1, fxyz:2}
>>> fabc in mdict
True
>>> abc in mdict
Traceback (most recent call last):
File "<interactive input>", line 1, in <module>
TypeError: unhashable type: 'set'
La fonction intégrée getattr:
>>> class C():
def getMontys(self):
self.montys = ['Cleese','Palin','Idle','Gilliam','Jones','Chapman']
return self.montys
>>> c = C()
>>> getattr(c,'getMontys')()
['Cleese', 'Palin', 'Idle', 'Gilliam', 'Jones', 'Chapman']
>>>
Utile si vous souhaitez répartir une fonction en fonction du contexte. Voir des exemples dans Plonger dans Python ( Here )
En ce qui concerne l'implémentation par Nick Johnson de Property class (juste une démonstration de descripteurs, bien sûr, pas un remplaçant pour le prédéfini), j'inclurais un séparateur qui soulève un AttributeError:
class Property (objet): def __init __ (self, fget): self.fget = fget def __get __ (self, obj , tapez): si obj est None: retourner soi-même retourner soi-même.fget (obj) def __set __ (soi, obj, valeur): raise AttributeError, 'Attribut en lecture seule'
L'inclusion du setter en fait un descripteur de données par opposition à un descripteur de méthode/non-donnée. Un descripteur de données a la priorité sur les dictionnaires d'instance. Désormais, une instance ne peut pas avoir un objet différent assigné au nom de la propriété et les tentatives d’attribution à la propriété déclencheront une erreur d’attribut.
>>> float('infinity')
inf
>>> float('NaN')
nan
Plus d'informations:
Ce n'est pas vraiment une fonctionnalité cachée mais quelque chose qui pourrait être utile.
pour parcourir en boucle les éléments d'une liste
for x, y in Zip(s, s[1:]):
spam
en Python standardIl est utilisé à des fins de test.
Je l'ai choisi de ctypes
tutoriel . Essayez vous-même:
>>> import __hello__
Hello world...
>>> type(__hello__)
<type 'module'>
>>> from __phello__ import spam
Hello world...
Hello world...
>>> type(spam)
<type 'module'>
>>> help(spam)
Help on module __phello__.spam in __phello__:
NAME
__phello__.spam
FILE
c:\python26\<frozen>
Si vous utilisez exec
dans une fonction, les règles de recherche de variable changent radicalement. Les fermetures ne sont plus possibles mais Python autorise des identifiants arbitraires dans la fonction. Cela vous donne une "locale modifiable" et peut être utilisé pour importer des identifiants. En revanche, chaque recherche est plus lente, car les variables se retrouvent dans un dict plutôt que dans des fentes du cadre:
>>> def f():
... exec "a = 42"
... return a
...
>>> def g():
... a = 42
... return a
...
>>> import dis
>>> dis.dis(f)
2 0 LOAD_CONST 1 ('a = 42')
3 LOAD_CONST 0 (None)
6 DUP_TOP
7 EXEC_STMT
3 8 LOAD_NAME 0 (a)
11 RETURN_VALUE
>>> dis.dis(g)
2 0 LOAD_CONST 1 (42)
3 STORE_FAST 0 (a)
3 6 LOAD_FAST 0 (a)
9 RETURN_VALUE
Gestion de la mémoire
Python alloue dynamiquement de la mémoire et utilise un garbage collection pour récupérer de l'espace inutilisé. Une fois qu'un objet est hors de portée et qu'aucune autre variable ne le référence, il sera récupéré. Je n'ai pas à m'inquiéter des dépassements de mémoire tampon et de la croissance lente des processus du serveur. La gestion de la mémoire est également une caractéristique d'autres langages dynamiques, mais Python le fait si bien.
Bien sûr, nous devons faire attention aux références circulaires et conserver les références aux objets qui ne sont plus nécessaires, mais les références faibles aident beaucoup ici.
Classes en tant qu'objets de première classe (illustrés par une définition de classe dynamique)
Notez également l’utilisation de la fermeture. Si cet exemple particulier ressemble à une "bonne" approche d'un problème, réexaminez-le soigneusement ... plusieurs fois :)
def makeMeANewClass(parent, value):
class IAmAnObjectToo(parent):
def theValue(self):
return value
return IAmAnObjectToo
Klass = makeMeANewClass(str, "fred")
o = Klass()
print isinstance(o, str) # => True
print o.theValue() # => fred
Jamais utilisé xrange (INT) au lieu de range (INT) .... Il utilise moins de mémoire et ne dépend pas vraiment de la taille de l'entier. Yey !! N'est-ce pas bon?
Pas du tout une particularité cachée mais quand même sympa:
import os.path as op
root_dir = op.abspath(op.join(op.dirname(__file__), ".."))
Enregistre beaucoup de caractères lors de la manipulation des chemins!
mapreduce en utilisant map et réduire les fonctions
créez un produit simple de cette manière:
def sumprod(x,y):
return reduce(lambda a,b:a+b, map(lambda a, b: a*b,x,y))
exemple:
In [2]: sumprod([1,2,3],[4,5,6])
Out[2]: 32
>>> x=[1,1,2,'a','a',3]
>>> y = [ _x for _x in x if not _x in locals()['_[1]'] ]
>>> y
[1, 2, 'a', 3]
"locals () ['_ [1]']" est le "nom secret" de la liste en cours de création. Très utile lorsque l'état de la liste en cours de création affecte les décisions de construction ultérieures.
Pas de fonction de programmation, mais utile en cas d'utilisation de Python avec bash
ou Shell scripts
.
python -c"import os; print(os.getcwd());"
Voir le documentation python ici . Des éléments supplémentaires à noter lors de l'écriture plus longue Python des scripts peuvent être vus dans cette discussion .
Les extensions de position et de mot-clé de Python peuvent être utilisées à la volée, et pas seulement à partir d'une liste stockée.
l=lambda x,y,z:x+y+z
a=1,2,3
print l(*a)
print l(*[a[0],2,3])
C'est généralement plus utile avec des choses comme ceci:
a=[2,3]
l(*(a+[3]))
Débogage interactif de scripts (et chaînes de doctest)
Je ne pense pas que cela soit aussi connu que cela puisse être, mais ajoutez cette ligne à un script python:
import pdb; pdb.set_trace()
le débogueur de PDB apparaît avec le curseur d’exécution à cet endroit du code. Ce qui est encore moins connu, je pense, est que vous pouvez utiliser cette même ligne dans un doctest:
"""
>>> 1 in (1,2,3)
Becomes
>>> import pdb; pdb.set_trace(); 1 in (1,2,3)
"""
Vous pouvez ensuite utiliser le débogueur pour extraire l’environnement doctest. Vous ne pouvez pas vraiment parcourir un doctest car les lignes sont exécutées de manière autonome, mais c'est un excellent outil pour déboguer les globs et l'environnement doctest.
commands.getoutput
Si vous voulez obtenir le résultat d’une fonction qui renvoie directement à stdout
ou stderr
comme c’est le cas avec _os.system
_, commands.getoutput
vient à la rescousse. L'ensemble du module est juste fait de génial.
_>>> print commands.getoutput('ls')
myFile1.txt myFile2.txt myFile3.txt myFile4.txt myFile5.txt
myFile6.txt myFile7.txt myFile8.txt myFile9.txt myFile10.txt
myFile11.txt myFile12.txt myFile13.txt myFile14.txt module.py
_
Dans Python 2, vous pouvez générer une représentation sous forme de chaîne d'une expression en l'enfermant avec des backticks:
>>> `sorted`
'<built-in function sorted>'
Ceci est parti dans python 3.X.
Vous pouvez construire une fonction kwargs à la demande:
kwargs = {}
kwargs[str("%s__icontains" % field)] = some_value
some_function(**kwargs)
L'appel str () est en quelque sorte nécessaire, puisque python se plaint sinon qu'il ne s'agit pas d'une chaîne. Je ne sais pas pourquoi;) J'utilise ceci pour des filtres dynamiques dans le modèle d'objet Djangos:
result = model_class.objects.filter(**kwargs)
certaines fonctionnalités intéressantes avec réduire et opérateur.
>>> from operator import add,mul
>>> reduce(add,[1,2,3,4])
10
>>> reduce(mul,[1,2,3,4])
24
>>> reduce(add,[[1,2,3,4],[1,2,3,4]])
[1, 2, 3, 4, 1, 2, 3, 4]
>>> reduce(add,(1,2,3,4))
10
>>> reduce(mul,(1,2,3,4))
24
Voici une fonction utile que j'utilise lors du débogage des erreurs de type
def typePrint(object):
print(str(object) + " - (" + str(type(object)) + ")")
Il imprime simplement l'entrée suivie du type, par exemple
>>> a = 101
>>> typePrint(a)
101 - (<type 'int'>)
Multipliez une chaîne pour la faire répéter
print "SO"*5
donne
SOSOSOSOSO