Skip to content

5. 类与对象

类是创建对象的模板。对象被称为类的实例

  

5.1. 一个对象类


程序 (classes_01)

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

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

#   any variable can have attributes by construction
obj1=Objet()
obj1.attr1="un"
obj1.attr2=100
#  displays the
print "objet1=[{0},{1}]".format(obj1.attr1,obj1.attr2)
#   modify object
obj1.attr2+=100
#  displays the
print "objet1=[{0},{1}]".format(obj1.attr1,obj1.attr2)
#   assigns object1 reference to object2
obj2=obj1
#   modify obj2
obj2.attr2=0
#   displays both objects
print "objet1=[{0},{1}]".format(obj1.attr1,obj1.attr2)
print "objet2=[{0},{1}]".format(obj2.attr1,obj2.attr2)

注:

  • 第 4 行:另一种形式的注释。以三个 """ 开头,可跨多行;
  • 第3-4行:一个空对象类;
  • 第7行:Object类的实例化;
  • 第17行:引用复制。变量obj1和obj2是指向同一个对象的两个指针(引用)。

结果

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

5.2. Person 类


程序 (classes_02)

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

class Personne:
    #    class attributes
    #    undeclared - can be created dynamically

    #    method
    def identite(self):
        #    a priori, uses non-existent attributes
        return "[{0},{1},{2}]".format(self.prenom,self.nom,self.age)

#    ---------------------------------- main
#  attributes are public and can be created dynamically
p=Personne()
p.prenom="Paul"
p.nom="Langevin"
p.age=48
#    method call
print "personne={0}\n".format(p.identite())

注:

  • 第 3-10 行:包含方法的类;
  • 第8行:类中的每个方法都必须将self对象(指当前对象)作为其第一个参数。

结果

personne=[Paul,Langevin,48]

5.3. 带有构造函数的 Person 类


程序 (classes_03)

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

class Personne:

    #   manufacturer
    def __init__(self,prenom,nom,age):
        self.prenom=prenom;
        self.nom=nom;
        self.age=age;

    #   method
    def identite(self):
        #   a priori, uses non-existent attributes
        return "[{0},{1},{2}]".format(self.prenom,self.nom,self.age)

#   ---------------------------------- main
#   a Person object
p=Personne("Paul","Langevin",48)
#   method call
print "personne={0}\n".format(p.identite())

注:

  • 第 6 行:类的构造函数名为 __init__。与其他方法一样,其第一个参数是 self;
  • 第 18 行:使用类构造函数创建了一个 Person 对象。

结果

personne=[Paul,Langevin,48]

5.4. 在构造函数中包含有效性检查的Person类


程序 (classes_04)

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

import re

# -------------------
#    a proprietary exception class
class MyError(Exception):
    pass

class Personne:

    #    manufacturer
    def __init__(self,prenom="x",nom="x",age=0):
         #  first name must be non-empty
        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]
        #  name must be non-empty
        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]
        #  age must be valid
        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)

#    ---------------------------------- main
#    a Person object
try:
    p=Personne("  Paul  ","  Langevin  ",48)
    print "personne={0}".format(p)
except MyError, erreur:
    print erreur
#    another object Nobody
try:
    p=Personne("  xx  ","  yy  ","  zz")
    print "personne={0}".format(p)
except MyError, erreur:
    print erreur
#    another person
try:
    p=Personne()
    print "personne={0}".format(p)
except MyError, erreur:
    print erreur

注:

  • 第 7-8 行:一个从 Exception 类派生的 MyError 类。它并未为后者添加任何功能,仅用于提供自定义异常;
  • 第 13 行:构造函数的参数具有默认值。因此,操作 p = Person() 等同于 p = Person("x", "x", 0);
  • 第 15–19 行:检查 first_name 参数。该参数不能为空。若为空,则抛出 MyError 异常并附带错误信息;
  • 第 21–25 行:last_name 参数的检查同上;
  • 第 27–31 行:年龄验证;
  • 第 33–34 行:__str__ 函数取代了之前名为 identite 的方法;
  • 第 38–42 行:实例化 Person 对象并显示其身份信息;
  • 第 39 行:实例化;
  • 第 40 行:显示。该操作需要将人 p 作为字符串显示。如果该方法存在,Python 解释器会自动调用 p.__str__() 方法。该方法的作用与 Java 或 .NET 语言中的 toString() 方法相同;
  • 第 41–42 行:处理可能抛出的 MyError 异常,并显示与该异常相关的错误信息;
  • 第 44–48 行:与上述操作相同,但针对使用错误参数创建的第二个 Person 实例;
  • 第 50–54 行:与上述情况相同,针对使用默认参数实例化的第三个 Person 对象。

结果

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

5.5. 添加一个充当第二个构造函数的方法


程序 (classes_05)

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

import re

# -------------------
#    a proprietary exception class
class MyError(Exception):
    pass

class Personne:
    #    class attributes
    #    undeclared - can be created dynamically

    #    manufacturer
    def __init__(self,prenom="x",nom="x",age=0):
         #  first name must be non-empty
        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]
        #  name must be non-empty
        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]
            #  age must be valid
        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):
        #  initializes the current object with a person p
        self.__init__(p.prenom,p.nom,p.age)

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

#    ---------------------------------- main
#    a Person object
try:
    p0=Personne("  Paul  ","  Langevin  ",48)
    print "personne={0}".format(p0)
except MyError, erreur:
    print erreur
#    another object Nobody
try:
    p1=Personne("  xx  ","  yy  ","  zz")
    print "personne={0}".format(p1)
except MyError, erreur:
    print erreur
#    another person
p2=Personne()
try:
    p2.initWithPersonne(p0)
    print "personne={0}".format(p2)
except MyError, erreur:
    print erreur

注:

  • 与之前的脚本相比,区别在于第35至37行。我们添加了 initWithPerson 方法该方法会调用 __init__ 构造函数。与类型化语言不同,这里无法通过参数或返回值的性质来区分同名方法。因此,无法定义多个构造函数来根据不同的参数(在本例中是 Person 类型的对象)创建对象。

结果

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

5.6. 一个 Person 对象的列表


程序 (classes_06)

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

class Personne:
    ...

#   ---------------------------------- main
#   create a list of person objects
groupe=[Personne("Paul","Langevin",48), Personne("Sylvie","Lefur",70)]
#  identity of these persons
for i in range(len(groupe)):
  print "groupe[{0}]={1}".format(i,groupe[i])

注:

  • 第3-5行:已描述的Person

结果

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

5.7. 创建一个从 Person 类派生的类


程序 (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)


#    ---------------------------------- main
#  create a list of Personne objects and derivatives
groupe=[Enseignant("Paul","Langevin",48,"anglais"), Personne("Sylvie","Lefur",70)]
#  identity of these persons
for i in range(len(groupe)):
  print "groupe[{0}]={1}".format(i,groupe[i])

注:

  • 第5-6行:Person类已定义;
  • 第 8 行:声明 Teacher 类为 Person 类的子类
  • 第 10 行:派生类 Teacher 的构造函数必须调用父类 Person 的构造函数;
  • 第 21-22 行:为了显示 group[i],解释器使用了方法 group[i].__str__()。所使用的 __str__() 方法是 group[i] 的实际类的该方法如下所示。

结果

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

5.8. 创建一个从 Person 类派生的第二个类


程序 (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)

#    ---------------------------------- main
#  create a list of Personne objects and derivatives
groupe=[Enseignant("Paul","Langevin",48,"anglais"), Personne("Sylvie","Lefur",70), Etudiant("Steve","Boer",22,"iup2 qualite")]
#  identity of these persons
for i in range(len(groupe)):
  print "groupe[{0}]={1}".format(i,groupe[i])

注:

  • 此脚本与前一个类似。

结果

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