Skip to content

5. Klasy i obiekty

Klasa jest formą, na podstawie której tworzone są obiekty. Mówi się, że obiekt jest instancją klasy.

  

5.1. Klasa Objet


Program (classes_01)


# -*- coding=utf-8 -*-

class Objet:
    """une classe Objet vide"""

# każda zmienna może mieć atrybuty z definicji
obj1=Objet()
obj1.attr1="un"
obj1.attr2=100
# wyświetla obiekt
print "objet1=[{0},{1}]".format(obj1.attr1,obj1.attr2)
# modyfikuje obiekt
obj1.attr2+=100
# wyświetla obiekt
print "objet1=[{0},{1}]".format(obj1.attr1,obj1.attr2)
# przypisuje odwołanie obiekt1 do obiekt2
obj2=obj1
# modyfikuje obiekt 2
obj2.attr2=0
# wyświetla oba obiekty
print "objet1=[{0},{1}]".format(obj1.attr1,obj1.attr2)
print "objet2=[{0},{1}]".format(obj2.attr1,obj2.attr2)

Uwagi:

  • wiersz 4: inna forma komentarza. Komentarz poprzedzony trzema znakami „ może się rozciągać na kilka wierszy;
  • wiersze 3–4: pusta klasa obiektowa;
  • wiersz 7: instancja klasy Objet;
  • wiersz 17: kopiowanie referencji. Zmienne obj1 i obj2 są dwoma wskaźnikami (referencjami) do tego samego obiektu.

Wyniki

1
2
3
4
objet1=[un,100]
objet1=[un,200]
objet1=[un,0]
objet2=[un,0]

5.2. Klasa Osoba


Program (classes_02)


# -*- coding=utf-8 -*-

class Personne:
    # atrybuty klasy
    # niezadeklarowane – mogą być tworzone dynamicznie

    # metoda
    def identite(self):
        # z założenia wykorzystuje nieistniejące atrybuty
        return "[{0},{1},{2}]".format(self.prenom,self.nom,self.age)

# ---------------------------------- main
# atrybuty są publiczne i mogą być tworzone dynamicznie
p=Personne()
p.prenom="Paul"
p.nom="Langevin"
p.age=48
# wywołanie metody
print "personne={0}\n".format(p.identite())

Uwagi:

  • wiersze 3–10: klasa z jedną metodą;
  • wiersz 8: każda metoda klasy musi mieć jako pierwszy parametr obiekt self, który oznacza bieżący obiekt.

Wyniki

personne=[Paul,Langevin,48]

5.3. Klasa Personne z konstruktorem


Program (classes_03)


# -*- coding=utf-8 -*-

class Personne:
    
    # konstruktor
    def __init__(self,prenom,nom,age):
        self.prenom=prenom;
        self.nom=nom;
        self.age=age;

    # metoda
    def identite(self):
        # z założenia wykorzystuje nieistniejące atrybuty
        return "[{0},{1},{2}]".format(self.prenom,self.nom,self.age)

# ---------------------------------- main
# obiekt typu Personne
p=Personne("Paul","Langevin",48)
# wywołanie metody
print "personne={0}\n".format(p.identite())

Uwagi:

  • wiersz 6: konstruktor klasy nosi nazwę __init__. Podobnie jak w przypadku innych metod, jego pierwszym parametrem jest self;
  • wiersz 18: obiekt Personne jest tworzony za pomocą konstruktora klasy.

Wyniki

personne=[Paul,Langevin,48]

5.4. Klasa Personne z kontrolami poprawności w konstruktorze


Program (classes_04)


# -*- coding=utf-8 -*-

import re

# -------------------
# własna klasa wyjątku
class MyError(Exception):
    pass

class Personne:
    
    # konstruktor
    def __init__(self,prenom="x",nom="x",age=0):
         # imię musi być niepuste
        match=re.match(r"^\s*(\S+)\s*$",prenom)
        if not match:
            raise MyError("Le prenom ne peut etre vide")
        else:
            self.prenom=match.groups()[0]
        # nazwisko nie może być puste
        match=re.match(r"^\s*(\S+)\s*$",nom)
        if not match:
            raise MyError("Le nom ne peut etre vide")
        else:
            self.nom=match.groups()[0]
        # wiek musi być prawidłowy
        match=re.match(r"^\s*(\d+)\s*$",str(age))
        if not match:
            raise MyError("l'age doit etre un entier positif")
        else:
            self.age=match.groups()[0]

    def __str__(self):
        return "[{0},{1},{2}]".format(self.prenom,self.nom,self.age)
      
# ---------------------------------- ręka
# obiekt Osoba
try:
    p=Personne("  Paul  ","  Langevin  ",48)
    print "personne={0}".format(p)
except MyError, erreur:
    print erreur
# inny obiekt typu Osoba
try:
    p=Personne("  xx  ","  yy  ","  zz")
    print "personne={0}".format(p)
except MyError, erreur:
    print erreur
# inna osoba
try:
    p=Personne()
    print "personne={0}".format(p)
except MyError, erreur:
    print erreur

Uwagi:

  • wiersze 7–8: klasa MyError wywodząca się z klasy Exception. Nie dodaje ona żadnych nowych funkcji do tej ostatniej. Została utworzona wyłącznie w celu posiadania własnego wyjątku;
  • wiersz 13: konstruktor ma domyślne wartości dla swoich parametrów. W związku z tym operacja p=Personne() jest równoważna wyrażeniu p=Personne("x","x",0);
  • wiersze 15–9: analizujemy parametr prenom. Musi on być niepusty. Jeśli tak nie jest, zgłaszamy wyjątek MyError wraz z komunikatem o błędzie;
  • wiersze 21–25: to samo dotyczy nazwiska;
  • wiersze 27–31: sprawdzanie wieku;
  • wiersze 33–34: funkcja __str__ zastępuje metodę, która wcześniej nosiła nazwę identite;
  • wiersze 38–42: instancjonowanie osoby, a następnie wyświetlenie jej tożsamości;
  • wiersz 39: utworzenie instancji;
  • wiersz 40: wyświetlenie. Operacja wymaga wyświetlenia osoby p w postaci ciągu znaków. Interpreter języka Python automatycznie wywołuje wówczas metodę p.__str__(), o ile istnieje. Metoda ta pełni tę samą rolę, co metoda toString() w języku Java lub w językach .NET;
  • wiersze 41–42: obsługa ewentualnego wyjątku typu MyError. Wyświetla wówczas komunikat o błędzie związany z tym wyjątkiem;
  • wiersze 44–48: to samo dotyczy drugiej osoby utworzonej z błędnymi parametrami;
  • wiersze 50–54: to samo dotyczy trzeciej osoby utworzonej przy użyciu parametrów domyślnych.

Wyniki

1
2
3
personne=[Paul,Langevin,48]
l'age doit etre un entier positif
personne=[x,x,0]

5.5. Dodano metodę pełniącą rolę drugiego konstruktora


Program (classes_05)


# -*- coding=utf-8 -*-

import re

# -------------------
# klasa wyjątków będąca właścicielem
class MyError(Exception):
    pass

class Personne:
    # atrybuty klasy
    # niezadeklarowane – mogą być tworzone dynamicznie
    
    # konstruktor
    def __init__(self,prenom="x",nom="x",age=0):
         # imię musi być niepuste
        match=re.match(r"^\s*(\S+)\s*$",prenom)
        if not match:
            raise MyError("Le prenom ne peut etre vide")
        else:
            self.prenom=match.groups()[0]
        # nazwisko nie może być puste
        match=re.match(r"^\s*(\S+)\s*$",nom)
        if not match:
            raise MyError("Le nom ne peut etre vide")
        else:
            self.nom=match.groups()[0]
            # wiek musi być prawidłowy
        match=re.match(r"^\s*(\d+)\s*$",str(age))
        if not match:
            raise MyError("l'age doit etre un entier positif")
        else:
            self.age=match.groups()[0]

    def initWithPersonne(self,p):
        # inicjuje bieżący obiekt z osobą p
        self.__init__(p.prenom,p.nom,p.age)

    def __str__(self):
        return "[{0},{1},{2}]".format(self.prenom,self.nom,self.age)
      
# ---------------------------------- main
# obiekt Osoba
try:
    p0=Personne("  Paul  ","  Langevin  ",48)
    print "personne={0}".format(p0)
except MyError, erreur:
    print erreur
# inny obiekt typu Osoba
try:
    p1=Personne("  xx  ","  yy  ","  zz")
    print "personne={0}".format(p1)
except MyError, erreur:
    print erreur
# kolejna osoba
p2=Personne()
try:
    p2.initWithPersonne(p0)
    print "personne={0}".format(p2)
except MyError, erreur:
    print erreur

Uwagi:

  • różnica w stosunku do poprzedniego skryptu znajduje się w wierszach 35–37. Dodano metodę initWithPersonne. Metoda ta wywołuje konstruktor __init__. Nie ma możliwości, tak jak w językach typowanych, posiadania metod o tej samej nazwie, rozróżnianych na podstawie charakteru ich parametrów lub wyniku. Nie ma zatem możliwości posiadania wielu konstruktorów, które tworzyłyby obiekt na podstawie różnych parametrów, w tym przypadku obiekt typu Personne.

Wyniki

1
2
3
personne=[Paul,Langevin,48]
l'age doit etre un entier positif
personne=[Paul,Langevin,48]

5.6. Lista obiektów typu Personne


Program (classes_06)


# -*- coding=utf-8 -*-

class Personne:
    ...

# ---------------------------------- główna
# utworzenie listy obiektów „osoba”
groupe=[Personne("Paul","Langevin",48), Personne("Sylvie","Lefur",70)]
# tożsamość tych osób
for i in range(len(groupe)):
  print "groupe[{0}]={1}".format(i,groupe[i])

Uwagi:

  • wiersze 3–5: opisana już klasa Personne

Wyniki

groupe[0]=[Paul,Langevin,48]
groupe[1]=[Sylvie,Lefur,70]

5.7. Utworzenie klasy pochodnej od klasy Osoba


Program (classes_07)


# -*- coding=utf-8 -*-

import re

class Personne:
    ...

class Enseignant(Personne):
    def __init__(self,prenom="x",nom="x",age=0,discipline="x"):
        Personne.__init__(self,prenom,nom,age)
        self.discipline=discipline

    def __str__(self):
        return "[{0},{1},{2},{3}]".format(self.prenom,self.nom,self.age,self.discipline)
  

# ---------------------------------- główna
# utworzenie listy obiektów „Osoba” i pochodnych
groupe=[Enseignant("Paul","Langevin",48,"anglais"), Personne("Sylvie","Lefur",70)]
# tożsamość tych osób
for i in range(len(groupe)):
  print "groupe[{0}]={1}".format(i,groupe[i])

Uwagi:

  • wiersze 5–6: już zdefiniowana klasa Personne;
  • wiersz 8: deklaruje klasę Enseignant jako klasę pochodną klasy „Osoba”;
  • wiersz 10: konstruktor klasy pochodnej Enseignant musi wywołać konstruktor klasy nadrzędnej Personne;
  • wiersze 21–22: aby wyświetlić grupę[i], interpreter wykorzystuje metodę grupa[i].__str__(). Zastosowana metoda __str__() pochodzi z rzeczywistej klasy groupe[i], co widać na poniższych wynikach.

Wyniki

groupe[0]=[Paul,Langevin,48,anglais]
groupe[1]=[Sylvie,Lefur,70]

5.8. Utworzenie drugiej klasy pochodnej od klasy Personne


Program (classes_08)


# -*- coding=utf-8 -*-

import re

class Personne:
    ...

class Enseignant(Personne):
    ...
  
class Etudiant(Personne):
    def __init__(self,prenom="x",nom="x",age=0,formation="x"):
        Personne.__init__(self,prenom,nom,age)
        self.formation=formation

    def __str__(self):
        return "[{0},{1},{2},{3}]".format(self.prenom,self.nom,self.age,self.formation)

# ---------------------------------- główna
# utworzenie listy obiektów typu „Osoba” i pochodnych
groupe=[Enseignant("Paul","Langevin",48,"anglais"), Personne("Sylvie","Lefur",70), Etudiant("Steve","Boer",22,"iup2 qualite")]
# tożsamość tych osób
for i in range(len(groupe)):
  print "groupe[{0}]={1}".format(i,groupe[i])

Uwagi:

  • ten skrypt jest analogiczny do poprzedniego.

Wyniki

groupe[0]=[Paul,Langevin,48,anglais]
groupe[1]=[Sylvie,Lefur,70]
groupe[2]=[Steve,Boer,22,iup2 qualite]