类的基本概念
Python是一门面向对象的编程语言,在程序设计中,可通过编写类来模拟现实世界中的事物和情景,并基于这些类来创建对象。基于类创建对象时,每个对象都自动具备类中定义的行为,这个过程被称为实例化。
类的创建和使用
1、创建类
class Dog(): '''创建Dog类''' def __init__(self, name, age): #self是指向实例的__init__函数的特殊参量 '''初始化属性name和age''' self.name = name self.age = age def sit(self): #函数中包含__init__函数中的self.name,故需要指向实例的__init__函数的形参self作为这个sit函数的参量,下面的roll_over函数同 '''模拟小狗被命令时蹲下''' print(self.name.title() + " is now sitting.") def roll_over(self): '''模拟小狗被命令时打滚''' print(self.name.title() + " rolled over!")
按照约定,在Python中首字母大写的名称指的是类。
类中的函数被称为方法(故引用时使用点号连接)。__init__()是一个Python中的默认方法,每当你根据Dog类创建新实例时,Python都会自动运行它。__init__()开头和末尾各有两个下划线,用于与普通的方法区分。
__init__()包含3个形参:self、name和age。其中self必不可少且需位于其他形参之前,它是一个指向实例本身的引用(类似于指针),让实例能够作为类中函数的参数访问类中的属性与方法。当调用__init__()方法创建实例时,Python将自动传入实参self,也就是说我们在创建实例时不需要给self这个形参赋值,而只需给后面的其他形参赋值即可。
在Dog类定义的另外两个方法中,由于这些方法不需要额外的信息,如名字或年龄,因此它们只有一个必带的形参self。在未来的开发中,可以扩展这些方法以模拟实际情况,如插入小狗蹲下和打滚动画的代码。
2、根据类创建实例
类可以视为有关如何创建实例的说明。Dog类是一系列说明,让Python知道如何创建表示特定小狗的实例。
class Dog(): --snip-- my_dog = Dog('willie', 6) #注意:可用首字母是否大写来区分类和实例 print("My dog's name is " + my_dog.name.title() + ".") print("My dog is " + str(my_dog.age) + " years old.")
'''调用类中定义的方法'''
my_dog.sit()
my_dog.roll_over()
输出为:
My dog's name is Willie. My dog is 6 years old. Willie is now sitting. Willie rolled over!
3、给属性指定默认值
类中的每个属性都必须有初始值。当给某个属性指定默认值后,就无需包含为它提供初始值的形参。
class Car(): '''创建Car类''' def __init__(self, make, model, year): '''初始化描述汽车的属性''' self.make = make self.model = model self.year = year #添加名为odometer_reading的属性,将初始值设置为0 self.odometer_reading = 0 def get_descriptive_name(self): '''返回描述性信息''' long_name = str(self.year) + ' ' + self.make + ' ' + self.model return long_name.title() #添加名为read_odometer的调用odometer_reading的函数 def read_odometer(self): '''打印一条指出汽车里程的消息''' print("This car has " + str(self.odometer_reading) + " miles on it.") my_new_car = Car('audi', 'a4', 2016) print(my_new_car.get_descriptive_name()) #调用read_odometer函数,打印汽车行驶里程 my_new_car.read_odometer()
输出为:
2016 Audi A4
This car has 0 miles on it.
以下写法与上述代码等价
class Car(): '''创建Car类''' def __init__(self, make, model, year, odometer_reading = 0): #将带默认值的参量写入括号 '''初始化描述汽车的属性''' self.make = make self.model = model self.year = year #添加名为odometer_reading的属性,将初始值设置为0 self.odometer_reading = odometer_reading #带默认值变量的赋值 '''或写成:self.odometer_reading = 0'''
def get_descriptive_name(self): '''返回描述性信息''' long_name = str(self.year) + ' ' + self.make + ' ' + self.model return long_name.title() #添加名为read_odometer的调用odometer_reading的函数 def read_odometer(self): '''打印一条指出汽车里程的消息''' print("This car has " + str(self.odometer_reading) + " miles on it.") my_new_car = Car('audi', 'a4', 2016, 0) print(my_new_car.get_descriptive_name()) #调用read_odometer函数,打印汽车行驶里程 my_new_car.read_odometer()
4、修改属性的值
(1)直接修改
my_new_car.odometer_reading = 23
(2)在类中定义可以修改属性的值的方法
class Car(): --snip-- def update_odometer(self, mileage): '''将里程数设置为指定的值''' self.odometer_reading = mileage my_new_car.update_odometer(23)
(3)在类中定义可以使属性的值递增/递减变化的方法
class Car(): --snip-- def update_odometer(self, mileage): '''将里程数设置为指定的值''' self.odometer_reading = mileage def increment_odometer(self, miles): '''使读数递增指定的值''' self.odometer_reading += miles my_old_car.update_odometer(23) my_old_car.increment_odometer(100)
类的继承
编写类时,并非总要从空白开始。如果你想要在一个已有的类的基础上编写新的类,则可以使用继承。当一个类继承另一个类时,它将自动获得另一个类的所有属性和方法;原有的类称为父类,新类称为子类。子类继承了其父类所有属性和方法,同时还可以定义自己的属性和方法。
1、创建子类
class Car(): --snip-- class ElectricCar(Car): '''由父类Car创建子类ElectricCar''' def __init__(self, make, model, year): '''初始化父类的属性,从而得到子类对应属性''' super().__init__(make, model, year) my_tesla = ElectricCar('tesla', 'model s', 2016) print(my_tesla.get_descriptive_name())
创建子类时,父类必须包含在当前文件中,且位于子类前面。
定义子类时,必须在括号内指明父类的名称。方法__init__()接收创建Car实例所需的信息。
注意不同结构的命名方式:类的每个单词的首字母大写,不用下划线连接;而方法的单词全部小写,并用下划线连接。
super()是一个特殊函数,帮助Python将父类和子类关联起来,这行代码让Python调用父类的__init__()方法,从而让ElectricCar下的实例包含父类的所有属性。父类也被称为超类(superclass),super就得名于此。
2、给子类定义新的属性和方法
让一个类继承另一个类后,可在新类中添加独属于它的新属性和新方法。
class Car(): --snip-- class ElectricCar(Car): def __init__(self, make, model, year): '''继承父类的属性''' super().__init__(make, model, year) '''添加独属于子类的新属性''' self.battery_size = 70 '''定义独属于子类的新方法''' def describe_battery(self): print("This car has a " + str(self.battery_size) + "-kWh battery.") my_tesla.describe_battery()
本例在Car类的基础上创建了ElectricCar类,ElectricCar类继承了Car类的属性和方法,同时也根据自己的特点添加了特有的新的属性和方法。
如果一个属性或方法是任何汽车都有的,而不是电动汽车所特有的,就应该将其加入Car类而不是ElectricCar类。
3、在子类中重写父类
通过在子类中定义一个与要重写的父类方法同名的方法的方式,可将原父类中的方法“覆盖”掉,Python只会关注这个新的方法,而会忽略原来的方法。
class ElectricCar(Car): --snip-- def fill_gas_tank(self): '''重写父类中包含的同名方法''' print("This car doesn't need a gas tank!")
4、创建多个类
当类的属性和方法数量逐渐增多、变得越来越复杂时,可将大类的一个部分作为一个独立的类提取出来,也就是把一个大类拆分成若干个小类。
class Car(): --snip-- class Battery(): '''拆分出新的类Battery''' def __init__(self, battery_size = 70): self.battery_size = battery_size def describe_battery(self): print("This car has a " + str(self.battery_size) + "-kWh battery.") class ElectricCar(Car): '''被拆分后的大类''' super().__init__(make, model, year) '''指向新类的属性定义''' self.battery = Battery() '''实例.属性->新类Battery,新类.方法->调用相关函数''' my_tesla.battery.describe_battery()
类的导入
假设我们已经编写了一个包含类的文件,文件名为car.py,在这个类中我们定义了Car和ElectricCar两个类(在同一个文件中存储的类最好具有一定的相关性),则有以下几种不同的导入方式。
从一个文件导入单个类: from car import Car 从一个文件导入多个类: from car import Car, ElectricCar 假设还有另一个模块,从不同模块中导入多个类: from electric_car import Battery from car import Car, ElectricCar 导入整个模块: import car 导入模块中所有类: from car import *
Python自带了Python标准库,里面有很多已经编写好的函数和类。通过函数和类的导入,你可以在你的程序中使用这些函数和类。
参考书籍:《Python编程:从入门到实践》
2020-07-22