19. Classes

19.1. Définition d’une classe

>>> class MyClass:
        pass

19.2. Variable de classe

>>> class MyClass:
...     value = "foobar"
...
...     def hello(self):
...         return ('Hello world')
...

19.3. Instanciation d’un objet

>>> my_object = MyClass()
>>> my_object
<__main__.MyClass instance at 0x10fed1cb0>

19.4. Accès à un attribut

>>> my_object.value
"foobar"

19.5. Création et modification d’un attribut

>>> my_object.other_value = 123
>>> my_object.other_value
123

19.6. Appel d’une méthode (invocation)

>>> my_object.hello()
'Hello world'
>>> my_object.value
'foobar'

19.7. Initialisation

>>> class MyClass:
...     def __init__(self):
...         self.value = "foobar"
...
...
...
>>> my_object = MyClass()
>>> my_object.value
'foobar'

19.8. Initialisation avec paramètres

>>> class Circle:
...     def __init__(self, radius):
...         self.radius = radius
...
...     def area(self):
...         return 3.14 * self.radius ** 2
...
...
...
>>> circle = Circle(10)
>>> c.area
<bound method Circle.area of <__main__.Circle instance at 0x10fd7de18>>
>>> circle.area()
314.0

Notez l’appel à self.radius

19.9. Avec une variable de classe

>>> class Circle:
...     pi = 3.14
...     def __init__(self):
...         self.radius = 10
...     def area(self):
...         return self.pi * self.radius**2
...
...
...
>>> c= Circle()
        >>> c.area()
314.0

19.10. Méthodes statiques

>>> class Foo:
...     @staticmethod
...     def display(): #pas de self
...         print ('bar')
...
...
...
>>> Foo.display()
bar

19.11. Un example de méthode statique

>>> class Shape:
...     all_shapes =[]
...
...     def __init__(self, name):
...         self.name = name
...         self.__class__.all_shapes.append(self)
...     @staticmethod
...     def count():
...         return len(Shape.all_shapes)
...
...
...
>>> my_rectangle = Shape('rectangle')
>>> my_sqaure = Shape('square')
>>> my_circle = Shape('circle')
>>> Shape.count()
3

19.12. Class Methods

>>> class Shape:
        ...     all_shapes =[]
        ...
        ...     def __init__(self, name):
        ...         self.name = name
        ...         self.__class__.all_shapes.append(self)
        ...     @classmethod
        ...     def count(cls):
        ...         return len(cls.all_shapes)
        ...
        ...
        ...
        >>> my_rectangle = Shape('rectangle')
        >>> my_sqaure = Shape('square')
        >>> my_circle = Shape('circle')
        >>> Shape.count()

La classe est passée implicitement

19.13. Héritage

>>> class Shape:
...     def __init__(self, x, y):
...         self.x = x
...         self.y = y
...
>>> class Circle(Shape):
...     def __init__(self,x, y, radius):
...         self.x = x
...         self.y = y
...         self.radius = radius
...
...
...
>>> c=Circle(1,2, 20)

19.14. New style classes

>>> class Shape(object):

19.15. Héritage avec super()

>>> class Shape(object):
...     def __init__(self, x, y):
...         self.x = x
...         self.y = y
...
...
...
>>> class Circle(Shape):#python 2.X
...     def __init__(self,x, y, radius):
...         super(Circle, self).__init__(x, y)
...
...
...
>>> c = Circle(1,2,3)
>>> class Square(Shape):# python 3.X
...     def __init__(self,x,y,side):
...         super().__init__(x,y)
...                     self.side = side

19.16. Monkey patching

Remplacer un attribut à la volée.

>>> def what():
...     return "a monkeypatch"
...
...
>>> c.what = what
>>> c.what()
'a monkeypatch'

A éviter autant que possible.

19.17. Variables privées

>>> class Foo(object):
...     def __init__(self):
...         self.name = "bar"
...         self.__private = "baz"
...
...     def print_private(self):
...         print (self.__private)
...
...
...
>>> f=Foo()
>>> f.print_private()
baz
>>> f.name
'bar'
>>> f.__private
Traceback (most recent call last):
  File "<input>", line 1, in <module>
AttributeError: 'Foo' object has no attribute '__private'

19.18. Name Mangling

>>> dir(f)
['_Foo__private', '__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__',
 '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__s
tr__', '__subclasshook__', '__weakref__', 'name', 'print_private']
>>> f._Foo__private
'baz'

__private –> “_Foo__private”

19.19. Getters et setters

Pas de getter et setters en python

class Length(object):
        def __init__(self):
                self._length_inches = 0
        @property
        def length(self):
                return self._length_inches * 2.54
        @length.setter
        def length(self, new_length):
                self._length_inches = new_length / 2.54
        @property
        def inchlength(self):
                return self._length_inches

        @inchlength.setter
        def inchlength(self, new_length):
                self._length_inches = new_length

l = Length()
l.length = 10

print(l.length)
print(l.inchlength)
l.inchlength= 44
print(l.inchlength)
print(l.length)

On peut utiliser getter, setter, deleter

class C(object):
    def __init__(self):
        self._x = None

    @property
    def x(self):
        """I'm the 'x' property."""
        return self._x

    @x.setter
    def x(self, value):
        self._x = value

    @x.deleter
    def x(self):
        del self._x

19.20. Destructeurs

On s’en sert rarement. On utilise la méthode __del__()

>>> class A(object):
...     def __del__(self):
...         print ('destruction')
...
...
...
>>> def foo():
...     a = A()
...
...
>>> foo()
destruction

19.21. Context manager: with

file = open(« /tmp/foo.txt ») data = file.read() file.close()

Avec with

with open(« /tmp/foo.txt ») as file: data = file.read()

Implémentation: méthodes __enter__ et __exit__

>>> class Sample:
...     def __enter__(self):
...         print "In __enter__()"
...         return "Foo"
...
...     def __exit__(self, type, value, trace):
...         print "In __exit__()"
...
>>> def get_sample():
...     return Sample()
...
...
>>> with get_sample() as sample:
...     print ('sample: ', sample)
...
...
In __enter__()
('sample: ', 'Foo')
In __exit__()