一、类
(一)类、对象
Python是一种面向对象语言,面向对象有两个概念,分别是类和对象。
类是对多个对象的共同特征的抽象描述,可以说类是对象的模板。
对象是类的实例,用于描述现实中的个体。
(二)类的定义
根据类与对象的关系,我们知道创建对象之前需先定义类,类中可以定义数据成员和成员函数,前者用于描述对象特征,称为属性,后者用于描述对象行为,称为方法,类中的方法的第一个参数必须为self,这种方法也叫实例方法,只能通过类实例化的对象进行调用。
class 类的名称 属性名称=属性值 def 方法名称(self): #self是一个指向对象的默认参数,类中必须包含参数 self, 且为第一个参数。 方法体
例如,下列代码定义了一个类,名称为Way,该类包含一个属性number_way、一个方法world():
class Way: number_way = 3 def world(self): print("hello world!")
(三)对象的创建和使用
创建对象:
对象名称=类名称()
访问对象成员:
对象名称.属性
对象名称.方法()
例如,创建一个Way类的对象a,访问该对象成员:
class Way: number_way = 3 def world(self): print("hello world!") a = Way() print(a.number_way) a.world()
输出结果如下:
二、限制对象访问
(一)定义私有成员、方法
定义类中的属性和方法默认为公有属性和公有方法,该类中的对象可以任意访问类中的公有成员和公有方法,可以通过将成员和方法定义为私有,即私有成员和私有方法,从而限制对象对类的访问。
通过在类成员名称或类方法名称前面加上双下划线__限制成员的访问,即定义为私有成员和私有方法,如下:
class Way: __number_way = 3 def __world(self): print("hello world!")
(二)访问私有成员、方法
这里要注意,实例化的对象是无法直接访问类中的私有成员和私有方法的,它们都可通过公有方法中的参数self调用。
例如,下列python代码,定义了一个私有成员__number_way和一个私有方法__world()以及一个公有方法get_way():
class Way: __number_way = 3 def __world(self): # 私有方法 print("hello world!") def get_way(self): # 公有方法 print(f"number_way的值为:{self.__number_way}") # 私有成员通过公有方法中的指代类本身的默认参数self访问 self.__world() # 私有方法通过公有方法中的指代类本身的默认参数self访问 a = Way() a.get_way()
输出结果如下:
三、构造方法和析构方法
类中有两个名为 __init__() 和__del__()的特殊方法,它们分别是构造方法和析构方法,该两种方法在类创建和销毁时会自动调用。
(一)构造方法
每个定义的类中都有一个默认的__init__()构造方法,如果在定义类时未定义,则系统会调用默认的构造方法,而如果用户在定义时显式地定义了构造方法,则会调用该定义的构造方法。
可以通过无参构造方法和有参构造方法来分别对该方法创建的对象赋予相同的初始值和不同的初始值。
注:这里按照参数的有无分为两种构造方法,但除了self,因为类中必须包含参数 self, 且为第一个参数。
下列python代码,Triangle类中显式地定义了带参数的构造方法和一个get_s()方法:
class Triangle: def __init__(self, bottom, high): self.bottom = bottom self.high = high def get_s(self): s = (self.bottom * self.high) / 2.0 print(f"三角形的面积为:{s}") S = Triangle(1.5, 2) print(S.bottom, S.high) S.get_s()
运行结果如下:
(二)析构方法
对象被清理时,系统会自动调用析构方法,即对象在内存中被释放时自动触发执行__del__()析构方法。
下列python代码,Triangle类中显式地定义了带参数的构造方法和一个get_s()方法以及一个析构方法,析构方法打印输出__del__()方法被调用:
class Triangle: def __init__(self, bottom, high): self.bottom = bottom self.high = high print("__init__()方法被调用") def __del__(self): print("__del__()方法被调用") def get_s(self): s = (self.bottom * self.high) / 2.0 print(f"三角形的面积为:{s}") S = Triangle(1.5, 2) print(S.bottom, S.high)
运行结果如下,可知道对象在被销毁时自动调用了__del__()析构方法:
四、类方法和静态方法
(一)类方法
类方法通过装饰器@classmethod修饰,它的第一个参数并非类本身self,而是cls。
与实例方法不一样,它既可由类实例化的对象调用,也可由类调用,且类方法可以修改类属性,而实例方法不能。
如下代码,通过对象名称调用类方法,直接通过类调用类方法且通过类方法修改类属性word的值:
class GetW: word = "hello world!" @classmethod def print_word(cls): print(f"{cls.word}") cls.word = "HELLO WORLD!" # 类方法修改类属性的值为HELLO WORLD! A = GetW() # 创建一个GetW类的对象A print("通过类实例化的对象调用:") A.print_word() print("通过类调用:") GetW.print_word()
运行结果如下:
(二)静态方法
首先静态方法与类方法一样,既可由类实例化的对象调用,也可由类调用。静态方法没有self参数,是通过装饰器@classmethod修饰。
由于没有默认参数,所以它无法使用默认参数来访问类成员。
下列python代码:
class Get: number = 0 @staticmethod def print_number(): print(f"{Get.number}") A = Get() A.print_number() Get.print_number()
运行结果如下:
五、继承
类和类可以继承,继承(派生)的类的称为派生类或子类,被继承的类称为基类或父类。
由于是继承下来的,所以派生类具有基类的所有属性和方法,继承的格式如下:
class 派生类名称(基类名称):
例如,下列python代码,定义了基类Employee和子类teacher,通过class Teacher(Employee)来继承基类Employee中的属性和方法,另外派生类中还有自己定义的属性和方法:
class Employee: place = "office" def get_word(self): print(f"{self.place}") class Teacher(Employee): # 继承Employee类 student_num = 50 # 子类自己定义的属性 def get_word_num(self): # 子类自己定义的方法 print(f"教师办公地点为{self.place}") print(f"学生人数为{self.student_num}") A = Teacher() print(Teacher.place) # 子类继承了父类的属性,所以子类有父类的属性 A.get_word() # 子类继承了父类的方法,所以子类有父类的方法 print(Teacher.student_num) # 输出子类自己定义的属性 A.get_word_num() # 调用子类自己定义的方法
输出结果如下,可以看出继承基类后,派生类既可以调用自己的方法,也能调用所继承基类中的方法:
(一)多继承
多继承指一个派生类继承多个基类,多继承的格式为class 派生类(基类1,基类2……)。
(二)派生类方法重写
当基类中的方法无法满足派生类中的要求时,可以重写基类的方法,重写后的基类原方法并未改变。
例如下列python代码,派生类teacher中重写基类中的get_word()方法:
class Employee: place = "office" @classmethod def get_word(cls): print(f"{cls.place}") class Teacher(Employee): student_num = 50 def get_word(self): print(f"{self.student_num}") A = Teacher() Employee.get_word() A.get_word() Employee.get_word()
运行结果如下,重写基类中的get_word()方法后,并未改变该方法:
(三)super()函数
可以通过super()函数,在派生类重写基类的方法后,仍可调用基类中的方法。
下列python代码:
class Employee: place = "office" @classmethod def get_word(cls): print(f"{cls.place}") class Teacher(Employee): student_num = 50 def get_word(self): print(f"{self.student_num}") print("使用super()函数调用基类中的方法:") super().get_word() A = Teacher() A.get_word()
运行结果如下,可以看到通过super()函数调用已经被派生类teacher重写的基类方法get_word():
六、多态
多态指不考虑对象类型并使用该对象,让具有不同功能的函数使用相同的函数名称,从而通过函数名称调用不同功能的函数。
下列python代码,通过Person类中的get_word()方法中的name参数,传给name参数是目标类的实例对象即调用该类的get_word()方法:
class Person: def get_word(self, name): name.get_word() class Employee: def get_word(self): print("职工") class Teacher(Employee): def get_word(self): print("教师") class Professor(Employee): def get_word(self): print("教授") A = Person() A.get_word(Employee()) A.get_word(Teacher()) A.get_word(Professor())
运行结果如下: