formations/python/formation/specialmethods.txt

230 lines
4.9 KiB
Plaintext

Programmation python courante
================================
.. _namespaces:
les espaces de nommage
-----------------------
Packages et modules::
package/
__init__.py
module1.py
subpackage/
__init__.py
module2.py
A utilser pour organiser votre projet
Permet de minimiser les risques de conflits de nome
Permet de diminuer les entrées dans le :envvar:`PYTHONPATH`
::
import package.module1
from package.subpackage import module2
from package.subpackage.module2 import name
- le fichier `__init__.py`
- `reload(module)` au prompt
- dangereux : l'import "*", utiliser l'attribut spécial `__all__` pour l'import
sélectif
::
from os import *
lance un module en tant que script :
::
if __name__ == "__main__":
main()
Organisation modulaire
- construire des composants élémentaires
- combiner ces composants
- utiliser une structure pyramidale : les composants sont les éléments de
composants plus complexes.
- découplage de l'ensemble en composants indépendants (gros programmes réalisables)
- donner de la structure (rendre les gros programmes compréhensibles)
- spécifier les liens entre les composants (rendre les programmes maintenables)
- identifier les sous-composants indépendants (rendre les programmes réutilisables)
- forcer l'abstraction (augmenter la sureté du programme)
Les méthodes spéciales
-----------------------
méthodes spéciales correspondants aux interfaces des types de bases :
.. function:: __init__(self, *args, **kwargs)
le constructeur de l'instance d'objet
.. function:: __add__(self, other)
correspond à la notation `+`
exemple :
.. literalinclude:: snippets/specialmethods.py
>>> from specialmethods import *
>>> z = Zone("titi", 10)
>>> z2 = Zone("tutu", 40)
>>> z > z2
False
>>> z + z2
<specialmethods.Zone object at 0x7f02d95fb190>
>>> z3 = z + z2
>>> z3.name
'tititutu'
>>> z3.level
50
>>>
Attributs et accesseurs
---------------------------
python est un langage à attributs, c'est-à-dire que le protocole d'accès
aux attributs est règlable.
>>> class C(object):
... classattr = "a class attribute"
...
>>> cobj = C()
>>> cobj.classattr
'a class attribute'
>>> cobj.insattr = "an instance attribute"
>>> cobj.insattr
'an instance attribute'
>>> C.__dict__['classattr']
'a class attribute'
>>> cobj.__dict__['insattr']
'an instance attribute'
les attributs ne sont pas systématiquement encapsulées en python.
pour contrôler l'accès aux attributs, on utilise les méthodes spéciales::
__getattr__(self, name)
__setattr__(self, name, value)
class AnObject(object):
......
def __setattr__(self, name, val):
if name == 'src': #do something
# this will assign the real object.name,
#despite __setattr__
self.__dict__[name]=val
def __getattr__(self, name):
# ...
try:
func = getattr(obj, "method")
except AttributeError:
... deal with missing method ...
else:
result = func(args)
func = getattr(obj, "method", None)
if callable(func):
func(args)
.. todo:: émulation de defaultdict
Dict with a default value
--------------------------
il est possible d'hériter des types de base
>>> a = dict.defaultdict(default=0)
>>> a
{}
>>> a[1] = 2
>>> print a
{1: 2}
>>> a[0]
0
>>> a.keys()
[1]
>>> a["machin"]
0
::
class defaultdict(dict):
def __init__(self, default=None):
dict.__init__(self)
self.default = default
def __getitem__(self, key):
try:
return dict.__getitem__(self, key)
except KeyError:
return self.default
def __getitem__(self, key):
if key in self:
return dict.__getitem__(self, key)
else:
return self.default
def get(self, key, *args):
if not args:
args = (self.default,)
return dict.get(self, key, *args)
- un **attribut** spécial : `__slots__`
permet de fixer les attributs possibles d'une classe
::
>>> class Bar(object):
... __slots__ = ("a","b","c")
...
>>> b = Bar()
>>> b.a = "toto"
>>> b.a
'toto'
>>> b.d = "titi"
Traceback (most recent call last):
File "<stdin>", line 1, in ?
AttributeError: 'Bar' object has no attribute 'd'
>>> class Point(object):
... __slots__ = 'x', 'y'
...
>>> p = Point()
>>> p.x = 2
>>> p.y = 3
>>> p.z = 4
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Point' object has no attribute 'z'
>>>
- notation `|` et notation `>`
::
class Test:
nombre = 1
def __or__(self, other):
return self.nombre + other.nombre
def __lshift__(self, other):
self.nombre = self.nombre + other.nombre
t1 = Test()
t2 = Test()
t2.nombre = 2
print t1 | t2
t1 << t2
print t1.nombre