5. 类与对象
类是用于生成对象的模板。对象被称为类的实例。
![]() |
5.1. 一个对象类
程序 (classes_01)
# -*- coding=utf-8 -*-
class Objet:
"""une classe Objet vide"""
# 任何变量在构造时都可能具有属性
obj1=Objet()
obj1.attr1="un"
obj1.attr2=100
# 显示对象
print "objet1=[{0},{1}]".format(obj1.attr1,obj1.attr2)
# 修改对象
obj1.attr2+=100
# 显示对象
print "objet1=[{0},{1}]".format(obj1.attr1,obj1.attr2)
# 将对象1的引用赋值给对象2
obj2=obj1
# 修改对象2
obj2.attr2=0
# 显示这两个对象
print "objet1=[{0},{1}]".format(obj1.attr1,obj1.attr2)
print "objet2=[{0},{1}]".format(obj2.attr1,obj2.attr2)
注:
- 第4行:另一种形式的注释。这种以三个“#”开头的注释可以跨多行;
- 第3-4行:一个空对象类;
- 第7行:实例化类Objet;
- 第17行:引用复制。变量obj1和obj2是指向同一对象的两个指针(引用)。
结果
5.2. 一个 Person 类
程序 (classes_02)
# -*- coding=utf-8 -*-
class Personne:
# 类属性
# 未声明 - 可动态创建
# 方法
def identite(self):
# 表面上看,使用了不存在的属性
return "[{0},{1},{2}]".format(self.prenom,self.nom,self.age)
# ---------------------------------- main
# 属性为 public 且可动态创建
p=Personne()
p.prenom="Paul"
p.nom="Langevin"
p.age=48
# 调用方法
print "personne={0}\n".format(p.identite())
注:
- 第 3-10 行:一个包含一个方法的类;
- 第8行:类的所有方法的首个参数必须是对象self,该对象表示当前对象。
结果
5.3. 带有构造函数的 Personne 类
程序 (classes_03)
# -*- coding=utf-8 -*-
class Personne:
# 构造函数
def __init__(self,prenom,nom,age):
self.prenom=prenom;
self.nom=nom;
self.age=age;
# 方法
def identite(self):
# 表面上看,使用了不存在的属性
return "[{0},{1},{2}]".format(self.prenom,self.nom,self.age)
# ---------------------------------- main
# 一个 Personne 对象
p=Personne("Paul","Langevin",48)
# 调用方法
print "personne={0}\n".format(p.identite())
注:
- 第 6 行:类的构造函数名为 __init__。与其他方法一样,其第一个参数是 self;
- 第 18 行:使用该类的构造函数创建了一个 Personne 对象。
结果
5.4. Personne 类,其构造函数中包含有效性检查
程序 (classes_04)
# -*- coding=utf-8 -*-
import re
# -------------------
# 一个专有异常类
class MyError(Exception):
pass
class Personne:
# 构造函数
def __init__(self,prenom="x",nom="x",age=0):
# 名字字段不能为空
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]
# 姓氏不能为空
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]
# 年龄必须有效
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)
# ---------------------------------- 主
# 一个 Personne 对象
try:
p=Personne(" Paul "," Langevin ",48)
print "personne={0}".format(p)
except MyError, erreur:
print erreur
# 另一个 Personne 对象
try:
p=Personne(" xx "," yy "," zz")
print "personne={0}".format(p)
except MyError, erreur:
print erreur
# 另一位人员
try:
p=Personne()
print "personne={0}".format(p)
except MyError, erreur:
print erreur
注:
- 第 7-8 行:一个从类 Exception 派生的类 MyError。它并未为后者添加任何功能,仅用于定义一个专属异常;
- 第13行:构造函数的参数具有默认值。因此,操作 p=Personne() 等同于 p=Personne("x","x",0);
- 第15-19行:分析参数prenom。该参数必须不为空。若不满足此条件,则抛出MyError异常并显示错误信息;
- 第21-25行:姓名参数的处理方式同上;
- 第27-31行:验证年龄;
- 第 33-34 行:函数 __str__ 取代了之前名为 identite 的方法;
- 第38-42行:实例化一个人,然后显示其身份信息;
- 第 39 行:实例化;
- 第 40 行:显示。该操作要求将对象 p 以字符串形式显示出来。 Python解释器会自动调用方法p.__str__()(如果该方法存在)。该方法的作用与Java或.NET语言中的方法toString()相同;
- 第41-42行:处理可能出现的MyError类型异常。随后显示与该异常相关的错误信息;
- 第44-48行:针对使用错误参数实例化的第二个人物,处理方式相同;
- 第50-54行:第三个使用默认参数实例化的人员,处理方式同上。
结果
5.5. 添加一个充当第二个构造函数的方法
程序 (classes_05)
# -*- coding=utf-8 -*-
import re
# -------------------
# 一个拥有者异常类
class MyError(Exception):
pass
class Personne:
# 类的属性
# 未声明 - 可动态创建
# 构造函数
def __init__(self,prenom="x",nom="x",age=0):
# 名字字段不能为空
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]
# 姓必须不为空
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]
# 年龄必须有效
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):
# 使用人员 p 初始化当前对象
self.__init__(p.prenom,p.nom,p.age)
def __str__(self):
return "[{0},{1},{2}]".format(self.prenom,self.nom,self.age)
# ---------------------------------- main
# 一个 Personne 对象
try:
p0=Personne(" Paul "," Langevin ",48)
print "personne={0}".format(p0)
except MyError, erreur:
print erreur
# 另一个 Personne 对象
try:
p1=Personne(" xx "," yy "," zz")
print "personne={0}".format(p1)
except MyError, erreur:
print erreur
# 另一个Personne对象
p2=Personne()
try:
p2.initWithPersonne(p0)
print "personne={0}".format(p2)
except MyError, erreur:
print erreur
注:
- 与前一个脚本的区别在于第35-37行。我们添加了方法 initWithPersonne。该方法调用了构造函数 __init__。 与类型化语言不同,本语言无法通过参数或返回值的性质来区分同名方法。因此,无法通过不同的参数(此处为 Personne 类型的对象)来创建多个构造函数。
结果
5.6. 一个 Personne 对象列表
程序 (classes_06)
# -*- coding=utf-8 -*-
class Personne:
...
# ---------------------------------- 主
# 创建人员对象列表
groupe=[Personne("Paul","Langevin",48), Personne("Sylvie","Lefur",70)]
# 这些人员的身份
for i in range(len(groupe)):
print "groupe[{0}]={1}".format(i,groupe[i])
注:
- 第3-5行:已描述的类 Personne
结果
5.7. 创建一个从 Personne 类派生的类
程序 (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)
# ---------------------------------- 主
# 创建“Person”对象及其派生对象的列表
groupe=[Enseignant("Paul","Langevin",48,"anglais"), Personne("Sylvie","Lefur",70)]
# 这些人员的身份
for i in range(len(groupe)):
print "groupe[{0}]={1}".format(i,groupe[i])
注:
- 第 5-6 行:已定义的类 Personne;
- 第 8 行:声明类 Enseignant 为 Personne 类的派生类;
- 第10行:派生类Enseignant的构造函数必须调用父类Personne的构造函数;
- 第 21-22 行:为了显示 groupe[i],解释器使用方法 groupe[i].__str__()。 所使用的 __str__() 方法属于 groupe[i] 的实际类,如下面的结果所示。
结果
5.8. 创建一个从 Personne 类派生的第二个类
程序 (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)
# ---------------------------------- 主
# 创建“Person”对象及其派生对象的列表
groupe=[Enseignant("Paul","Langevin",48,"anglais"), Personne("Sylvie","Lefur",70), Etudiant("Steve","Boer",22,"iup2 qualite")]
# 这些人的身份
for i in range(len(groupe)):
print "groupe[{0}]={1}".format(i,groupe[i])
注:
- 此脚本与前一个类似。
结果
