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
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
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
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
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
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
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
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
