5. Python的类
5.1 创建和使用类
使用类几乎可以模拟任何东西。在Python中,首字母大写的名称指的是类。下面来编写一个表示小狗的简单类Dog, 它表示的不是特定的小狗,而是任何小狗。
5.1.1 创建Dog 类
类中的函数称为方法。方法_init_()是一个特殊方法,每当Dog 类创建新的实例的时候,Python都会运行它。在这个方法名中,开头和结尾都有一个下划线,这是一种约定,为了避免Python默认方法和普通方法发生名称冲突。可以通过实例访问的变量称为属性。
示例:
class Dog:
'''根据类Dog 类创建的每个实例都将储存名称和年龄。'''
'''我们赋予了每条小狗蹲下和打滚的能力。'''
'''一次模拟小狗的简单尝试。'''
def __init__(self, name, age):
'''初始化属性name、age。'''
self.name = name
self.age = age
def sit(self):
'''模拟小狗收到命令时,蹲下。'''
print(f'{self.name} is now sitting.')
def roll_over(self):
'''模拟小狗收到命令时,打滚。'''
print(f'{self.age} rolled over.')
注意:每个方法中都有的形参self,这是因为在Python使用类创建实例时,与实例相关联的方法调用都会自动传递一个实参self,它是一个指向实例本身的引用,让实例能够访问类中的属性和方法。
self的中文译为:自己。
5.1.2 根据实例创建实例
创建一个简单的小狗实例:
class Dog:
my_dog = Dog('zhouluxun', 100000)
print(f"My dog's name is {my_dog.name}.")
print(f"My dog is {my_dog.age} years old.")
调用方法,示例:
class Dog:
my_dog = Dog('zhouluxun', 100000)
print(f"My dog's name is {my_dog.name}.")
print(f"My dog is {my_dog.age} years old.")
my_dog.sit()
my_dog.roll_over()
5.2 使用类和实例
5.2.1 Car 类
编写一个表示汽车的类。它存储了有关汽车的信息,还有一个汇总这些信息的方法,示例:
class Car:
'''一次模拟汽车的简单尝试。'''
def __init__(self, make, model, year):
self.make = make
self.model = model
self.year = year
def get_descriptive_name(self):
long_name = f"{self.make} {self.model} {self.year}"
return long_name.title()
my_new_car = Car('audi', 'a8', 2030)
print(my_new_car.get_descriptive_name())
5.2.2 给属性指定默认值
直接上示例:
class Car:
'''一次模拟汽车的简单尝试。'''
def __init__(self, make, model, year):
self.make = make
self.model = model
self.year = year
self.master = 'zhouluxun'#在上一个示例的基础上填上这句
def get_descriptive_name(self):
long_name = f"{self.make} {self.model} {self.year}"
return long_name.title()
def own(self):
print(f'The owner of the car is {self.master}')
#增添一个说明汽车主人的方法
my_new_car = Car('audi', 'a8', 2030)
print(my_new_car.get_descriptive_name())
my_new_car.own()
5.2.3 修改属性的值
直接修改属性的值(修改默认的属性的属性值),示例:
class Car:
'''一次模拟汽车的简单尝试。'''
def __init__(self, make, model, year):
self.make = make
self.model = model
self.year = year
self.master = 'zhouluxun'#在上一个示例的基础上填上这句
def get_descriptive_name(self):
long_name = f"{self.make} {self.model} {self.year}"
return long_name.title()
def own(self):
print(f'The owner of the car is {self.master}')
#增添一个说明汽车主人的方法
my_new_car = Car('audi', 'a8', 2030)
print(my_new_car.get_descriptive_name())
my_new_car.own()
my_new_car.master = 'joker'
my_new_car.own()
注意:不是默认值的属性也是可以修改的。
通过方法来修改属性的值,示例:
class Car:
'''一次模拟汽车的简单尝试。'''
def __init__(self, make, model, year):
self.make = make
self.model = model
self.year = year
self.master = 'zhouluxun'#在上一个示例的基础上填上这句
def get_descriptive_name(self):
long_name = f"{self.make} {self.model} {self.year}"
return long_name.title()
def own(self):
print(f'The owner of the car is {self.master}')
#增添一个说明汽车主人的方法
def masters(self, sb):
self.master = sb
my_new_car = Car('audi', 'a8', 2030)
print(my_new_car.get_descriptive_name())
my_new_car.own()
my_new_car.masters('joker')
my_new_car.own()
注意:我们可以使用这些方法来控制用户修改属性值,但能够访问程序的人都可以通过直接访问属性来修改他的值。
5.3 继承
编写类时,并非总是要从空白开始。如果要编写的类是另一个现成类的特殊版本,可使用继承。一个类继承另一个类时,将自动获得另一个类的所有属性和方法。原有的类称为父类,而新类称为子类。
5.3.1子类的方法__init__()
直接上示例:
class Car:
'''一次模拟汽车的简单尝试。'''
def __init__(self, make, model, year):
self.make = make
self.model = model
self.year = year
self.odometer_reading = 0
def get_descriptive_name(self):
long_name = f"{self.make} {self.model} {self.year}"
return long_name.title()
def read_odometer(self):
print(f"This car has {self.odometer_reading} miles on it.")
def update_odomter(self, mileage):
if mileage >= self.odometer_reading:
self.odometer_reading = mileage
else:
print("You can't roll back an odometer!")
def increment_odomter(self, miles):
self.odometer_reading += miles
class ElectricCar(Car):
'''电动汽车的独特之处'''
def __init__(self, make, model, year):
'''初始化父类的属性'''
super().__init__(make, model, year)
'''
super()是一个特殊函数,能够让我们调用父类的方法。
父类也被称为超类(superclass)
'''
my_tesla = ElectricCar('tesla', 'model s', '2019')
print(my_tesla.get_descriptive_name())
5.3.2 给子类定义属性和方法
直接上示例:
class Car:
'''一次模拟汽车的简单尝试。'''
def __init__(self, make, model, year):
self.make = make
self.model = model
self.year = year
self.odometer_reading = 0
def get_descriptive_name(self):
long_name = f"{self.make} {self.model} {self.year}"
return long_name.title()
def read_odometer(self):
print(f"This car has {self.odometer_reading} miles on it.")
def update_odomter(self, mileage):
if mileage >= self.odometer_reading:
self.odometer_reading = mileage
else:
print("You can't roll back an odometer!")
def increment_odomter(self, miles):
self.odometer_reading += miles
class ElectricCar(Car):
'''电动汽车的独特之处'''
def __init__(self, make, model, year):
'''初始化父类的属性'''
super().__init__(make, model, year)
self.battery_size = 75
'''
super()是一个特殊函数,能够让我们调用父类的方法。
父类也被称为超类(superclass)
'''
def describe_battery(self):
'''打印一条电瓶容量的消息'''
print(f"This car has a {self.battery_size}-kWh battery.")
my_tesla = ElectricCar('tesla', 'model s', '2019')
print(my_tesla.get_descriptive_name())
my_tesla.describe_battery()
5.3.3 重写父类的方法
对于父类的方法,只要他不符合子类模拟的实物的行为,都可以进行重写。这个非常简单,假如在父类中有一个方法对于子类来说没啥用,但是这个子类又从父类那里得到了这个方法,你可以直接在子类那里再重新定义一次这个方法,相对于修改了。
5.3.4 将实例用作属性
使用代码模拟实物时,可能会发现自己给类添加的细节越来越多:属性和方法清单以及文件都越来越长。在这种情况下,可能需要将类的一部分提取出来,作为一个独立的类。可将大型类拆分成多个能协同工作的小类。
示例:
class Car:
'''一次模拟汽车的简单尝试。'''
def __init__(self, make, model, year):
self.make = make
self.model = model
self.year = year
self.odometer_reading = 0
def get_descriptive_name(self):
long_name = f"{self.make} {self.model} {self.year}"
return long_name.title()
def read_odometer(self):
print(f"This car has {self.odometer_reading} miles on it.")
def update_odomter(self, mileage):
if mileage >= self.odometer_reading:
self.odometer_reading = mileage
else:
print("You can't roll back an odometer!")
def increment_odomter(self, miles):
self.odometer_reading += miles
class Battery:
'''一次模拟电动汽车电瓶的简单尝试'''
def __init__(self, battery_size):
self.battery_size = battery_size
def describe_battery(self):
'''打印一条电瓶容量的消息'''
print(f"This car has a {self.battery_size}-kWh battery.")
class ElectricCar(Car):
'''电动汽车的独特之处'''
def __init__(self, make, model, year):
'''初始化父类的属性'''
super().__init__(make, model, year)
self.battery = Battery(75)
'''
super()是一个特殊函数,能够让我们调用父类的方法。
父类也被称为超类(superclass)
'''
my_tesla = ElectricCar('tesla', 'model s', '2019')
print(my_tesla.get_descriptive_name())
my_tesla.battery.describe_battery()
'''这行代码让Python在实例my_tesla中查找属性battery,
并对存储在属性中的实例Battery调用方法describe_battery()'''
5.4 导入类
随着不断给类添加功能,文件肯能变得很长,即使妥善地使用了继承也是如此。为遵循Python的总体理念,尽量让文件整洁。Python提供了帮助在这方面,允许将类存储在模块中,然后再主程序中导入所需的模块。
5.4.1 导入单个类
无需多言跟函数那个一模一样。
car.py文件模块,示例:
'''一个可用于表示汽车的类'''
class Car:
'''一次模拟汽车的简单尝试。'''
def __init__(self, make, model, year):
self.make = make
self.model = model
self.year = year
self.odometer_reading = 0
def get_descriptive_name(self):
long_name = f"{self.make} {self.model} {self.year}"
return long_name.title()
def read_odometer(self):
print(f"This car has {self.odometer_reading} miles on it.")
def update_odomter(self, mileage):
if mileage >= self.odometer_reading:
self.odometer_reading = mileage
else:
print("You can't roll back an odometer!")
def increment_odomter(self, miles):
self.odometer_reading += miles
my_car.py文件,示例:
from car import Car
my_new_car = Car('audi', 'a8', 2030)
print(my_new_car.get_descriptive_name())
my_new_car.read_odometer()
5.4.2 在一个模块中存储多个类
就是在一个模块文件当中放多个类。
如果要用到哪个类就如下操作:
5.4.3 从一个模块中导入多个类
如果要同时导入多个类,需要注意的就是类中有父类的类名不用加括号,示例:
5.4.4 导入整个模块
可以直接使用代码 import car来导入car模块文件, 然后使用句点表示法拉访问需要的类。
例如这个:my_beetle = car.Car('***********')
5.4.5 导入模块中所有的类
可以直接使用代码:from car import *
5.4.6 在一个模块中导入另一个模块
示例:
5.4.7 使用别名
为类制造一个可以替代的别名。
示例:from car import ElectricCar as Ec