第9章:类
9.1 创建和使用类
9.1.1 创建dog类
根据Dog 类创建的每个实例都将存储名字和年龄。我们赋予了每条小狗蹲下(sit()) 和打滚(roll_over()) 的能力:
class Dog():
"""一次模拟小狗的简单尝试"""
def __init__(self, name, age):
"""初始化属性name和age"""
self.name = name
self.age = age
def sit(self):
"""模拟小狗被命令时蹲下"""
print(self.name.title() + " is now sitting.")
def roll_over(self):
"""模拟小狗被命令时打滚"""
print(self.name.title() + " rolled over!")
9.1.2 根据类创建实例
可将类视为有关如何创建实例的说明
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 的属性name 的值:
my_dog.name
调用方法
根据Dog 类创建实例后,就可以使用句点表示法来调用Dog 类中定义的任何方法。下面来让小狗蹲下和打滚:
class Dog():
--snip--
my_dog = Dog('willie', 6)
my_dog.sit()
my_dog.roll_over()
创建多个实例
class Dog():
--snip--
my_dog = Dog('willie', 6)
your_dog = Dog('lucy', 3)
print("My dog's name is " + my_dog.name.title() + ".")
print("My dog is " + str(my_dog.age) + " years old.")
my_dog.sit()
print("\nYour dog's name is " + your_dog.name.title() + ".")
print("Your dog is " + str(your_dog.age) + " years old.")
your_dog.sit()
9.2 使用类和实例
你可以使用类来模拟现实世界中的很多情景。类编写好后,你的大部分时间都将花在使用根据类创建的实例上。你需要执行的一个重要任务是修改实例的属性。你可以直接修改实例的属性,也可以编写方法以特定的方式进行修改。
9.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 = str(self.year) + " " + self.make + " " + self.model
return long_name.title()
my_new_car = Car('audi', 'a4', 2016)
print(my_new_car.get_descriptive_name())
输出:
2016 Audi A4
9.2.2 给属性指定默认值
类中的每个属性都必须有初始值,哪怕这个值是0或空字符串。在有些情况下,如设置默认值时,在方法__init__() 内指定这种初始值是可行的;如果你对某个属性这样做了,就无需包含为它提供初始值的形参。
下面来添加一个名为odometer_reading 的属性,其初始值总是为0。我们还添加了一个名为read_odometer() 的方法,用于读取汽车的里程表:
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 = str(self.year) + " " + self.make + " " + self.model
return long_name.title()
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)
my_new_car.read_odometer()
9.2.3 修改属性的值
可以以三种不同的方式修改属性的值:直接通过实例进行修改;通过方法进行设置;通过方法进行递增(增加特定的值)。下面依次介绍这些方法:
直接修改属性的值
要修改属性的值,最简单的方式是通过实例直接访问它。下面的代码直接将里程表读数设置为23:
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 = str(self.year) + " " + self.make + " " + self.model
return long_name.title()
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)
my_new_car.odometer_reading = 23
my_new_car.read_odometer()
通过方法修改属性的值
如果有替你更新属性的方法,将大有裨益。这样,你就无需直接访问属性,而可将值传递给一个方法,由它在内部进行更新。
class Car():
def __init__(self, make, model, year):
--snip--
def update_odometer(self, mileage):
"""将里程表设置为指定值"""
self.odometer_reading = mileage
my_new_car = Car('audi', 'a4', 2016)
print(my_new_car.get_descriptive_name)
my_new_car.update_odometer(23)
my_new_car.read_odometer()
方法update_odometer() 接受一个里程值,并将其存储到self.odometer_reading 中。
可对方法update_odometer() 进行扩展,使其在修改里程表读数时做些额外的工作。下面来添加一些逻辑,禁止任何人将里程表读数往回调:
class Car():
def __init__(self, make, model, year):
--snip--
def update_odometer(self, mileage):
"""
将里程表读数设置为指定的值
禁止将里程表读数往回调
"""
if mileage >= self.odometer_reading:
self.odometer_reading = mileage
else:
print("You can't roll back an odometer!")
my_new_car = Car('audi', 'a4', 2016)
print(my_new_car.get_descriptive_name)
my_new_car.update_odometer(23)
my_new_car.read_odometer()
现在,update_odometer() 在修改属性前检查指定的读数是否合理。如果新指定的里程(mileage )大于或等于原来的里程(self.odometer_reading ),就将里程表读数改为新指定的里程;否则就发出警告,指出不能将里程表往回拨
通过方法对属性的值进行递增
有时候需要将属性值递增特定的量,而不是将其设置为全新的值。假设我们购买了一辆二手车,且从购买到登记期间增加了100英里的里程,下面的方法让我们能够传递这个增量,并相应地增加里程表读数:
class Car():
--snip--
def update_odometer(self, mileage):
--snip--
def increment_odometer(self, miles):
self.odometer_reading += miles
my_used_car = Car('subaru', 'outback', 2013)
print(my_used_car.get_descriptive_name())
my_used_car.update_odometer(23500)
my_used_car.read_odometer()
my_used_car.increment_odometer(100)
my_used_car.read_odometer()
9.3 继承
编写类时,并非总是要从空白开始。如果你要编写的类是另一个现成类的特殊版本,可使用继承 。一个类继承 另一个类时,它将自动获得另一个类的所有属性和方法;原有的类称为父类 ,而新类称为子类 。子类继承了其父类的所有属性和方法,同时还可以定义自己的属性和方法。
9.3.1 子类的方法__init__()
创建子类的实例时,Python首先需要完成的任务是给父类的所有属性赋值。为此,子类的方法__init__() 需要父类施以援手。
例如,下面来模拟电动汽车。电动汽车是一种特殊的汽车,因此我们可以在前面创建的Car 类的基础上创建新类ElectricCar ,这样我们就只需为电动汽车特有的属性和行为编写代码。
electric_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 = str(self.year) + ' ' + self.make + ' ' + self.model
return long_name
def update_odometer(self, mileage):
if mileage > self.odometer_reading:
self.odometer_reading = mileage
else:
print("You can't roll back an odometer!")
def increment_odometer(self, miles):
self.odometer_reading += miles
class ElectricCar(Car):
"""电动汽车的独特之处"""
def __init__(self, make, model, year):
"""初始化父类的属性"""
super().__init__(make, model, year)
my_tesla = ElectricCar('tesla', 'model s', 2016)
print(my_tesla.get_descriptive_name())
创建子类时,父类必须包含在当前文件中,且位于子类前面。定义子类时,必须在括号内指定父类的名称。
super() 是一个特殊函数,帮助Python将父类和子类关联起来。这行代码让Python调用ElectricCar 的父类的方法__init__() ,让ElectricCar 实例包含父类的所有属性。父类也称为超类 (superclass),名称super因此而得名。
9.3.3 给子类定义属性和方法
让一个类继承另一个类后,可添加区分子类和父类所需的新属性和方法。
下面来添加一个电动汽车特有的属性(电瓶),以及一个描述该属性的方法。我们将存储电瓶容量,并编写一个打印电瓶描述的方法:
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 = ElectricCar('tesla', 'model s', 2016)
print(my_tesla.get_descriptive_name())
my_tesla.describe_battery()
9.3.4 重写父类的方法
对于父类的方法,只要它不符合子类模拟的实物的行为,都可对其进行重写。为此,可在子类中定义一个这样的方法,即它与要重写的父类方法同名。这样,Python将不会考虑这个父类方法,而只关注你在子类中定义的相应方法。
假设Car 类有一个名为fill_gas_tank() 的方法,它对全电动汽车来说毫无意义,因此你可能想重写它。下面演示了一种重写方式:
def ElectricCar(Car):
--snip--
def fill_gas_tank():
"""电动汽车没有油箱"""
print("This car doesn't need a gas tank.")
现在,如果有人对电动汽车调用方法fill_gas_tank() ,Python将忽略Car 类中的方法fill_gas_tank() ,转而运行上述代码。使用继承时,可让子类保留从父类那里继承而来的精华,并剔除不需要的糟粕。
9.3.5 将实例用作属性
使用代码模拟实物时,你可能会发现自己给类添加的细节越来越多:属性和方法清单以及文件都越来越长。在这种情况下,可能需要将类的一部分作为一个独立的类提取出来。你可以将大型类拆分成多个协同工作的小类。
例如,不断给ElectricCar 类添加细节时,我们可能会发现其中包含很多专门针对汽车电瓶的属性和方法。在这种情况下,我们可将这些属性和方法提取出来,放到另一个名为Battery 的类中,并将一个Battery 实例用作ElectricCar 类的一个属性:
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 = str(self.year) + " " + self.make + " " + self.model
return long_name
def read_odometer(self):
print("This car has " + str(self.odometer_reading) + " miles on it.")
def update_odometer(mileage):
if mileage >= self.odometer_reading:
self.odometer_reading = mileage
else:
print("You can't roll back an odometer!")
def increment_odometer(miles):
self.odometer_reading += miles
class 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):
"""电动汽车的独特之处"""
def __init__(self, make, model, year):
"""
初始化父类的属性
再初始化电动汽车特有的属性
"""
super().__init__(make, model, year)
self.battery = Battery()
my_tesla = ElectricCar('tesla', 'model s', 2016)
print(my_tesla.get_descriptive_name())
my_tesla.battery.describe_battery()
我们定义了一个名为Battery 的新类,它没有继承任何类。每个ElectricCar 实例都包含一个自动创建的Battery 实例。
我们创建一辆电动汽车,并将其存储在变量my_tesla 中。要描述电瓶时,需要使用电动汽车的属性battery,这时属性时Battery类的一个实例,于是可以使用Battery类的一个方法:describe.battery()
my_tesla.battery.describe_battery()
这看似做了很多额外的工作,但现在我们想多详细地描述电瓶都可以,且不会导致ElectricCar 类混乱不堪。下面再给Battery 类添加一个方法,它根据电瓶容量报告汽车的续航里程:
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 = str(self.year) + " " + self.make + " " + self.model
return long_name
def read_odometer(self):
print("This car has " + str(self.odometer_reading) + " miles on it.")
def update_odometer(mileage):
if mileage >= self.odometer_reading:
self.odometer_reading = mileage
else:
print("You can't roll back an odometer!")
def increment_odometer(miles):
self.odometer_reading += miles
class 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.")
def get_range(self):
"""根据电瓶容量确定最大行驶里程"""
if self.battery_size == 70:
range = 240
elif self.battery_size == 85:
range = 270
message = "This car can go approximately " + str(range)
message += " miles on a full charge."
print(message)
class ElectricCar(Car):
"""电动汽车的独特之处"""
def __init__(self, make, model, year):
"""
初始化父类的属性
再初始化电动汽车特有的属性
"""
super().__init__(make, model, year)
self.battery = Battery()
my_tesla = ElectricCar('tesla', 'model s', 2016)
print(my_tesla.get_descriptive_name())
my_tesla.battery.describe_battery()
my_tesla.battery.get_range()
输出:
2016 tesla model s
This car has a 70 -KWh battery.
This car can go approximately 240 miles on a full charge.
9.4 导入类
随着你不断地给类添加功能,文件可能变得很长,即便你妥善地使用了继承亦如此。为遵循Python的总体理念,应让文件尽可能整洁。为在这方面提供帮助,Python允许你将类存储在模块中,然后在主程序中导入所需的模块。
9.4.1 导入单个类
下面来创建一个只包含Car 类的模块。
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 = str(self.year) + " " + self.make + " " + self.model
return long_name
def read_odometer(self):
"""打印一条消息,指出汽车的里程"""
print("This car has " + str(self.odometer_reading) + " miles on it.")
def update_odometer(mileage):
"""
将里程表读数设置为指定的值
拒绝将里程表往回拨
"""
if mileage >= self.odometer_reading:
self.odometer_reading = mileage
else:
print("You can't roll back an odometer!")
def increment_odometer(miles):
"""将里程表读数增加指定的量"""
self.odometer_reading += miles
下面来创建另一个文件:my_car.py,在其中导入Car 类并创建其实例:
my_car.py
from car import Car
my_new_car = Car('audi', 'a4', 2016)
print(my_new_car.get_descriptive_name())
my_new_car.odometer_reading = 23
my_new_car.read_odometer()
9.4.2 在一个模块中存储多个类
虽然同一个模块中的类之间应存在某种相关性,但可根据需要在一个模块中存储任意数量的类。类Battery 和ElectricCar 都可帮助模拟汽车,因此下面将它们都加入模块car.py中:
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 = str(self.year) + " " + self.make + " " + self.model
return long_name
def read_odometer(self):
"""打印一条消息,指出汽车的里程"""
print("This car has " + str(self.odometer_reading) + " miles on it.")
def update_odometer(mileage):
"""
将里程表读数设置为指定的值
拒绝将里程表往回拨
"""
if mileage >= self.odometer_reading:
self.odometer_reading = mileage
else:
print("You can't roll back an odometer!")
def increment_odometer(miles):
"""将里程表读数增加指定的量"""
self.odometer_reading += miles
class 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.")
def get_range(self):
"""打印一条描述电瓶续航里程的消息"""
if self.battery_size == 70:
range = 240
elif self.battery_size == 85:
range = 270
message = "This car can go approximately " + str(range)
message += " miles on a full charge."
print(message)
class ElectricCar(Car):
"""模拟电动汽车的独特之处"""
def __init__(self, make, model, year):
"""初始化父类的属性,再初始化电动汽车特有的属性"""
super().__init__(make, model, year)
self.battery = Battery()
现在,可以新建一个名为my_electric_car.py的文件,导入ElectricCar 类,并创建一辆电动汽车了:
my_electric_car.py
from car import ElectricCar
my_tesla = ElectricCar('tesla', 'model s', 2016)
print(my_tesla.get_descriptive_name())
my_tesla.battery.describe_battery()
my_tesla.battery.get_range()
输出:
2016 tesla model s
This car has a 70-kWh battery.
This car can go approximately 240 miles on a full charge.
9.4.3 从一个模块中导入多个类
可根据需要在程序文件中导入任意数量的类。如果我们要在同一个程序中创建普通汽车和电动汽车,就需要将Car 和ElectricCar 类都导入:
my_cars.py
from car import ElectricCar, Car
my_beetle = Car('volkswagen', 'beetle', 2016)
print(my_beetle.get_descriptive_name())
my_tesla = ElectricCar('tesla', 'roadster', 2016)
print(my_tesla.get_descriptive_name())
9.4.4
你还可以导入整个模块,再使用句点表示法访问需要的类。这种导入方法很简单,代码也易于阅读。由于创建类实例的代码都包含模块名,因此不会与当前文件使用的任何名称发生冲突。
my_cars.py
import car
my_beetle = car.Car('volkswagen', 'beetle', 2016)
print(my_beetle.get_descriptive_name())
my_tesla = car.ElectricCar('tesla', 'roadster', 2016)
print(my_tesla.get_descriptive_name())
我们导入了整个car 模块,使用语法 module_name.class_name 访问需要的类。
9.4.5 导入模块中的所有类
要导入模块中的每个类,可使用下面的语法:
from module_name import *
不推荐使用这种导入方式,其原因有二。首先,如果只要看一下文件开头的import 语句,就能清楚地知道程序使用了哪些类,将大有裨益;但这种导入方式没有明确地指出你使用了模块中的哪些类。这种导入方式还可能引发名称方面的困惑。如果你不小心导入了一个与程序文件中其他东西同名的类,将引发难以诊断的错误。这里之所以介绍这种导入方式,是因为虽然不推荐使用这种方式,但你可能会在别人编写的代码中见到它。
需要从一个模块中导入很多类时,最好导入整个模块,并使用 module_name.class_name 语法来访问类。这样做时,虽然文件开头并没有列出用到的所有类,但你清楚地知道在程序的哪些地方使用了导入的模块;你还避免了导入模块中的每个类可能引发的名称冲突。
9.4.6 在一个模块中导入另一个模块
有时候,需要将类分散到多个模块中,以免模块太大,或在同一个模块中存储不相关的类。将类存储在多个模块中时,你可能会发现一个模块中的类依赖于另一个模块中的类。在这种情况下,可在前一个模块中导入必要的类。
例如,下面将Car 类存储在一个模块中,并将ElectricCar 和Battery 类存储在另一个模块中。我们将第二个模块命名为electric_car.py ,并将Battery 和ElectricCar 类复制到这个模块中:
electric_car.py
"""一组可用于表示电动汽车的类"""
from car import Car
class 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.")
def get_range(self):
"""打印一条描述电瓶续航里程的消息"""
if self.battery_size == 70:
range = 240
elif self.battery_size == 85:
range = 270
message = "This car can go approximately " + str(range)
message += " miles on a full charge."
print(message)
class ElectricCar(Car):
"""模拟电动汽车的独特之处"""
def __init__(self, make, model, year):
"""初始化父类的属性,再初始化电动汽车特有的属性"""
super().__init__(make, model, year)
self.battery = Battery()
更新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 = str(self.year) + " " + self.make + " " + self.model
return long_name
def read_odometer(self):
"""打印一条消息,指出汽车的里程"""
print("This car has " + str(self.odometer_reading) + " miles on it.")
def update_odometer(mileage):
"""
将里程表读数设置为指定的值
拒绝将里程表往回拨
"""
if mileage >= self.odometer_reading:
self.odometer_reading = mileage
else:
print("You can't roll back an odometer!")
def increment_odometer(miles):
"""将里程表读数增加指定的量"""
self.odometer_reading += miles
my_cars.py
from car import Car
from electric_car import ElectricCar
my_beetle = Car('volkswagen', 'beetle', 2016)
print(my_beetle.get_descriptive_name())
my_tesla = ElectricCar('tesla', 'roadster', 2016)
print(my_tesla.get_descriptive_name())
9.4.7 自定义工作流程
一开始应让代码结构尽可能简单。先尽可能在一个文件中完成所有的工作,确定一切都能正确运行后,再将类移到独立的模块中。如果你喜欢模块和文件的交互方式,可在项目开始时就尝试将类存储到模块中。先找出让你能够编写出可行代码的方式,再尝试让代码更为组织有序。
9.5 Python标准库
Python标准库 是一组模块,安装的Python都包含它。。下面来看模块collections 中的一个类——OrderedDict 。
字典让你能够将信息关联起来,但它们不记录你添加键—值对的顺序。要创建字典并记录其中的键—值对的添加顺序,可使用模块collections 中的OrderedDict 类。OrderedDict 实例的行为几乎与字典相同,区别只在于记录了键—值对的添加顺序。
favorite_language.py
from collections import OrderedDict
favorite_languages = OrderedDict()
favorite_languages['jen'] = 'python'
favorite_languages['sarah'] = 'c'
favorite_languages['edward'] = 'ruby'
favorite_languages['phil'] = 'python'
for name, language in favorite_languages.items():
print(name.title() + "'s favorite language is " + language.title() + ".")
输出:
Jen's favorite language is Python.
Sarah's favorite language is C.
Edward's favorite language is Ruby.
Phil's favorite language is Python.
9.6 类编码风格
类名应采用驼峰命名法 ,即将类名中的每个单词的首字母都大写,而不使用下划线。实例名和模块名都采用小写格式,并在单词之间加上下划线。
对于每个类,都应紧跟在类定义后面包含一个文档字符串。这种文档字符串简要地描述类的功能,并遵循编写函数的文档字符串时采用的格式约定。每个模块也都应包含一个文档字符串,对其中的类可用于做什么进行描述。
可使用空行来组织代码,但不要滥用。在类中,可使用一个空行来分隔方法;而在模块中,可使用两个空行来分隔类。
需要同时导入标准库中的模块和你编写的模块时,先编写导入标准库模块的import 语句,再添加一个空行,然后编写导入你自己编写的模块的import 语句。在包含多条import 语句的程序中,这种做法让人更容易明白程序使用的各个模块都来自何方。
习题
9-1
class Restaurant():
def __init__(self, restaurant_name, cuisine_type):
self.restaurant_name = restaurant_name
self.cuisine_type = cuisine_type
def describe_restaurant(self):
print("The name of this restaurant is " + self.restaurant_name +".The cuisine_type is "+ self.cuisine_type + ".")
def open_restaurant(self):
print("The restaurant is available now!")
restaurant = Restaurant('Chaoyixing', 'Lucai')
restaurant.describe_restaurant()
restaurant.open_restaurant()
9-3
class User():
def __init__(self, first_name, last_name, age, country):
self.first_name = first_name
self.last_name = last_name
self.age = age
self.country = country
def describe_user(self):
long_name = self.first_name.title() + " " + self.last_name.title() + " "
long_name += str(self.age) + " " + self.country
print(long_name)
def greet_user(self):
print("Hello, " + self.first_name.title() + " " + self.last_name.title() + ".")
admin = User('bruce', 'zhang', 20, 'China')
admin.describe_user()
admin.greet_user()
user1 = User('jack', 'ma', 50, 'Amercia')
user1.describe_user()
user1.greet_user()
9-4
class Restaurant():
def __init__(self, restaurant_name, cuisine_type):
"""初始化描述餐馆的属性"""
self.restaurant_name = restaurant_name
self.cuisine_type = cuisine_type
self.number_saved = 0
def describe_restaurant(self):
"""对餐馆名和菜系进行描述"""
print("The name of this restaurant is " + self.restaurant_name +".The cuisine_type is "+ self.cuisine_type + ".")
def open_restaurant(self):
"""当前餐馆正在营业"""
print("The restaurant is available now!")
def read_number_saved(self):
"""读取当前就餐人数"""
if self.number_saved == 0:
print("There is no people eating now.")
elif self.number_saved == 1:
print("There is 1 person eating now.")
elif self.number_saved >= 2:
print("There are " + str(self.number_saved) + " persons eating now.")
def increment_number_saved(self, increment_numbers):
"""就餐人数增加指定的量"""
self.number_saved += increment_numbers
def set_number_saved(self, persons):
"""设置就餐人数"""
self.number_saved = persons
restaurant = Restaurant('Chaoyixing', 'Lucai')
restaurant.describe_restaurant()
restaurant.read_number_saved()
restaurant.set_number_saved(10)
restaurant.read_number_saved()
restaurant.increment_number_saved(2)
restaurant.read_number_saved()
9-5
class User():
def __init__(self, first_name, last_name, age, country, login_attemps):
self.first_name = first_name
self.last_name = last_name
self.age = age
self.country = country
self.login_attemps = login_attemps
def describe_user(self):
"""对用户的信息进行描述"""
long_name = self.first_name.title() + " " + self.last_name.title() + " "
long_name += str(self.age) + " " + self.country
print(long_name)
def greet_user(self):
"""欢迎用户"""
print("Hello, " + self.first_name.title() + " " + self.last_name.title() + ".")
def read_login_attempts(self):
print(str(self.login_attemps))
def increment_login_attemps(self):
self.login_attemps += 1
def reset_login_attemps(self):
self.login_attemps = 0
admin = User('bruce', 'zhang', 20, 'China', 3)
for i in range(4):
admin.increment_login_attemps()
admin.read_login_attempts()
admin.reset_login_attemps()
admin.read_login_attempts()
9-6
class Restaurant():
def __init__(self, restaurant_name, cuisine_type):
"""初始化描述餐馆的属性"""
self.restaurant_name = restaurant_name
self.cuisine_type = cuisine_type
self.number_saved = 0
def describe_restaurant(self):
"""对餐馆名和菜系进行描述"""
print("The name of this restaurant is " + self.restaurant_name +".The cuisine_type is "+ self.cuisine_type + ".")
def open_restaurant(self):
"""当前餐馆正在营业"""
print("The restaurant is available now!")
def read_number_saved(self):
"""读取当前就餐人数"""
if self.number_saved == 0:
print("There is no people eating now.")
elif self.number_saved == 1:
print("There is 1 person eating now.")
elif self.number_saved >= 2:
print("There are " + str(self.number_saved) + " persons eating now.")
def increment_number_saved(self, increment_numbers):
"""就餐人数增加指定的量"""
self.number_saved += increment_numbers
def set_number_saved(self, persons):
"""设置就餐人数"""
self.number_saved = persons
class IceCreamStand(Restaurant):
def __init__(self, restaurant_name, cuisine_type):
super().__init__(restaurant_name, cuisine_type)
# 这里我容易犯一个错误,super().__init__(self, restaurant_name, cuisine_type)
self.flavors = ['apple', 'strawberry', 'pear']
def show_flavors(self):
print("There are several flavors:")
for flavor in self.flavors:
print("-" + flavor)
new_ice_cream = IceCreamStand('mixuebingcheng', 'fruit')
new_ice_cream.show_flavors()
9-7
class User():
def __init__(self, first_name, last_name, age, country, login_attemps):
self.first_name = first_name
self.last_name = last_name
self.age = age
self.country = country
self.login_attemps = login_attemps
def describe_user(self):
"""对用户的信息进行描述"""
long_name = self.first_name.title() + " " + self.last_name.title() + " "
long_name += str(self.age) + " " + self.country
print(long_name)
def greet_user(self):
"""欢迎用户"""
print("Hello, " + self.first_name.title() + " " + self.last_name.title() + ".")
def read_login_attempts(self):
print(str(self.login_attemps))
def increment_login_attemps(self):
self.login_attemps += 1
def reset_login_attemps(self):
self.login_attemps = 0
class Admin(User):
def __init__(self, first_name, last_name, age, country, login_attemps):
super().__init__(first_name, last_name, age, country, login_attemps)
self.privileges = ['can add post', 'can delete post', 'can ban user']
def show_privileges(self):
print("You have these privileges:")
for privilege in self.privileges:
print("-" + privilege)
master = Admin('bruce', 'zhang', 20, 'China', 1)
master.show_privileges()
9-8
class User():
def __init__(self, first_name, last_name, age, country, login_attemps):
self.first_name = first_name
self.last_name = last_name
self.age = age
self.country = country
self.login_attemps = login_attemps
def describe_user(self):
"""对用户的信息进行描述"""
long_name = self.first_name.title() + " " + self.last_name.title() + " "
long_name += str(self.age) + " " + self.country
print(long_name)
def greet_user(self):
"""欢迎用户"""
print("Hello, " + self.first_name.title() + " " + self.last_name.title() + ".")
def read_login_attempts(self):
print(str(self.login_attemps))
def increment_login_attemps(self):
self.login_attemps += 1
def reset_login_attemps(self):
self.login_attemps = 0
class Privilege():
def __init__(self):
self.privileges = ['can add post', 'can delete post', 'can ban user']
def show_privileges(self):
print("You have these privileges:")
for privilege in self.privileges:
print("-" + privilege)
class Admin(User):
def __init__(self, first_name, last_name, age, country, login_attemps):
super().__init__(first_name, last_name, age, country, login_attemps)
self.privileges = Privilege()
master = Admin('bruce', 'zhang', 20, 'China', 1)
master.privileges.show_privileges()
9-9
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 = str(self.year) + ' ' + self.make + ' ' + self.model
return long_name.title()
def read_odometer(self):
print("This car has " + str(self.odometer_reading) + " miles on it.")
def update_odometer(self, mileage):
if mileage >= self.odometer_reading:
self.odometer_reading = mileage
else:
print("You can't roll back an odometer!")
def increment_odometer(self, miles):
self.odometer_reading += miles
class 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.")
def upgrade_battery(self):
if self.battery_size != 85:
self.battery_size = 85
def get_range(self):
"""打印一条消息,指出电瓶的续航里程"""
if self.battery_size == 70:
range = 240
elif self.battery_size == 85:
range = 270
message = "This car can go approximately " + str(range)
message += " miles on a full charge."
print(message)
class ElectricCar(Car):
"""电动汽车的独特之处"""
def __init__(self, make, model, year):
"""
初始化父类的属性,再初始化电动汽车特有的属性
"""
super().__init__(make, model, year)
self.battery = Battery()
my_tesla = ElectricCar('tesla', 'model s', 2016)
print(my_tesla.get_descriptive_name())
my_tesla.battery.get_range()
my_tesla.battery.upgrade_battery()
my_tesla.battery.get_range()
9-10
restaurant.py
class Restaurant():
def __init__(self, restaurant_name, cuisine_type):
"""初始化描述餐馆的属性"""
self.restaurant_name = restaurant_name
self.cuisine_type = cuisine_type
self.number_saved = 0
def describe_restaurant(self):
"""对餐馆名和菜系进行描述"""
print("The name of this restaurant is " + self.restaurant_name +".The cuisine_type is "+ self.cuisine_type + ".")
def open_restaurant(self):
"""当前餐馆正在营业"""
print("The restaurant is available now!")
def read_number_saved(self):
"""读取当前就餐人数"""
if self.number_saved == 0:
print("There is no people eating now.")
elif self.number_saved == 1:
print("There is 1 person eating now.")
elif self.number_saved >= 2:
print("There are " + str(self.number_saved) + " persons eating now.")
def increment_number_saved(self, increment_numbers):
"""就餐人数增加指定的量"""
self.number_saved += increment_numbers
def set_number_saved(self, persons):
"""设置就餐人数"""
self.number_saved = persons
new_restaurant.py
from restaurant import Restaurant
real_me = Restaurant('chaoyixing', 'lucai')
real_me.describe_restaurant()
9-11
website.py
class User():
def __init__(self, first_name, last_name, age, country, login_attemps):
self.first_name = first_name
self.last_name = last_name
self.age = age
self.country = country
self.login_attemps = login_attemps
def describe_user(self):
"""对用户的信息进行描述"""
long_name = self.first_name.title() + " " + self.last_name.title() + " "
long_name += str(self.age) + " " + self.country
print(long_name)
def greet_user(self):
"""欢迎用户"""
print("Hello, " + self.first_name.title() + " " + self.last_name.title() + ".")
def read_login_attempts(self):
print(str(self.login_attemps))
def increment_login_attemps(self):
self.login_attemps += 1
def reset_login_attemps(self):
self.login_attemps = 0
class Privilege():
def __init__(self):
self.privileges = ['can add post', 'can delete post', 'can ban user']
def show_privileges(self):
print("You have these privileges:")
for privilege in self.privileges:
print("-" + privilege)
class Admin(User):
def __init__(self, first_name, last_name, age, country, login_attemps):
super().__init__(first_name, last_name, age, country, login_attemps)
self.privileges = Privilege()
manage.py
from website import Admin
master = Admin('bruce', 'zhang', 20, 'China', 1)
master.privileges.show_privileges()
9-12
user.py
class User():
def __init__(self, first_name, last_name, age, country, login_attemps):
self.first_name = first_name
self.last_name = last_name
self.age = age
self.country = country
self.login_attemps = login_attemps
def describe_user(self):
"""对用户的信息进行描述"""
long_name = self.first_name.title() + " " + self.last_name.title() + " "
long_name += str(self.age) + " " + self.country
print(long_name)
def greet_user(self):
"""欢迎用户"""
print("Hello, " + self.first_name.title() + " " + self.last_name.title() + ".")
def read_login_attempts(self):
print(str(self.login_attemps))
def increment_login_attemps(self):
self.login_attemps += 1
def reset_login_attemps(self):
self.login_attemps = 0
manage.py
from user import User
class Privilege():
def __init__(self):
self.privileges = ['can add post', 'can delete post', 'can ban user']
def show_privileges(self):
print("You have these privileges:")
for privilege in self.privileges:
print("-" + privilege)
class Admin(User):
def __init__(self, first_name, last_name, age, country, login_attemps):
super().__init__(first_name, last_name, age, country, login_attemps)
self.privileges = Privilege()
real_work.py
from user import User
from manage import Admin
master = Admin('bruce', 'zhang', 20, 'China', 1)
master.privileges.show_privileges()
9-13
from collections import OrderedDict
program_vocabulary = OrderedDict()
program_vocabulary['print'] = '打印'
program_vocabulary['variable'] = '变量'
program_vocabulary['set'] = '集合'
program_vocabulary['list'] = '列表'
program_vocabulary['dict'] = '字典'
for vocabulary, meaning in program_vocabulary.items():
print("\n" + vocabulary + ":\n\t" + meaning)
9-14
from random import randint
class Die():
def __init__(self, sides=6):
self.sides = sides
def roll_die(self, time=10):
print("with the "+ str(self.sides) + " sides dice,play in " + str(time) + " times:" )
for i in range(time):
self.result = randint(1, self.sides)
print("THe " + str(i+1) + " time:" + "You get a result:" + str(self.result))
s1 = Die(6)
s1.roll_die()
s2 = Die(10)
s2.roll_die()
s3 = Die(20)
s3.roll_die()