python编程 从入门到实践 第九章
创建和使用类
创建Dog类
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.')
方法__init__()
- 类中的函数成为方法。
-__init__()
方法是一个特殊的方法,每当根据Dog
类创建新实例的时候,python都会自动运行它。 - 在这个方法名称中,开头和末尾各有两个下划线,这是一种约定,避免python默认方法与普通方法发生名称冲突。
- 将方法
__init__()
定义成了包含三个形参:self
、name
、age
。在这个方法的定义中,形参self
必不可少,还必须位于其他形参的前面。 self
形参:python在调用这个__init__()
方法来创建Dog
实例时,将自动传入实参self
。- 每个与类相关量的方法调用都自动传递实参
self
,它是一个指向实例本身的引用,让实例可以访问类中的属性和方法。 - 每次根据
Dog
实例创建对象的时候,都只需给最后两个形参提供值。 __init__()
函数体内的两个变量都有前缀self.
。以self.
为前缀的变量都可以共类中的所有方法使用,我们还可以通过类的任何实例来访问这些变量。self.name = name
:获取存储在形参name
中的值,并将其存储到变量name
中,然后该变量被关联到当前创建的实例。- 可以通过实例来访问的变量称之为“属性”。
其他方法
- Dog类中还定义了其他两个方法。这些方法不需要额外的信息,因此它们只有一个形参
self
。
根据类创建实例
my_dog = Dog('Willie', 6)
print("My dog's name is " + my_dog.name.title() + '.')
print("My dog is ", my_dog.age + 'years old')
my_dog.sit()
my_dog.roll_over()
- 这里使用的是前一个例子中编写的Dog类。
- 在第一行,我们让python创建一条名字为
Willie
,年龄为6的小狗狗。遇到这一行代码时,python使用实参Willie
和6
调用Dog类中的方法__init__()
。方法__init__()
创建一个表示特定小狗的实例,并使用我们提供的值来设置属性name
和age
。方法__init__()
并未显式地包含return
语句,但是python会自动返回一个表示这条小狗的实例。我们将这个实例存储在变量my_dog
中。 - 通常约定,首字母大写的名称指的是类名,而小写的名称通常是指根据类创建的实例。
- 要访问实例的属性,可以用句点表示法,如:
my_dog.name
。python会先找到实例my_dog
,再查找跟这个实例相关联的属性name
。在Dog类中引用这个属性时,使用的是self.name
- 要调用实例的方法,可以使用句点表示法。先指定实例的名称以及要调用的方法,并用句点分隔他们。代码运行到该行时,python会在
Dog
类助攻查找对应的方法并且运行其代码。 - 可以按照需求根据类创建任意数量的实例。
Part One 练习
# 9.1 餐馆
print('---------- 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('restaurant_name: ' + self.restaurant_name)
print('cuisine_type: ' + self.cuisine_type)
def open_restaurant(self):
print('This restaurant ' + self.restaurant_name + ' is open now.')
KFC = Restaurant('KFC', 'Western-style food')
print(KFC.restaurant_name+' '+ KFC.cuisine_type)
KFC.describe_restaurant()
KFC.open_restaurant()
# 9.2 三家餐馆
print('---------- 9.2 ----------')
KFC = Restaurant('KFC', 'Western-style food')
KFC.describe_restaurant()
KFC.open_restaurant()
QuanJuDe = Restaurant('QuanJuDe', 'Chinese food')
QuanJuDe.describe_restaurant()
QuanJuDe.open_restaurant()
Dong = Restaurant('Dong Laishun', 'Chinese food')
Dong.describe_restaurant()
Dong.open_restaurant()
# 9.3 用户
print('---------- 9.3 ----------')
class User():
def __init__(self, first, last, **user_info):
self.first_name = first
self.last_name = last
self.user_info = {}
for k,v in user_info.items():
self.user_info[k] = v
def describe_user(self):
print('first name: ' + self.first_name +
'; last name: ' + self.last_name)
for k,v in self.user_info.items():
print(k, ':', v)
def greet_user(self):
print('Hello! ', self.first_name, self.last_name)
user1 = User('Vera', 'Zhang')
user1.describe_user()
user1.greet_user()
user2 = User('Sunny', 'Sun', city='HeKou', age=23)
user2.describe_user()
user2.greet_user()
使用类和实例
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())
给属性指定默认值
- 类中的每一个属性都必须有初始值,哪怕这个值是0或者空字符串。
- 在有些情况下,如设置默认值时,在方法
__init__()
内指定这种初始值是可行的。 - 如果已经对某个属性在方法
__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 = 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()
修改属性的值
- 直接修改属性的值
my_new_car.odometer_reading = 23
my_new_car.read_odometer()
- 通过方法进行设置
# 在类中添加一个方法
def update_odometer(self, mileage):
if mileage >= self.odometer_reading:
self.odometer_reading = mileage
else:
print('You cannot roll back an aodometer!')
# 类外进行的操作
my_new_car.update_odometer(23)
my_new_car.read_odometer()
- 通过方法进行递增
# 在类中添加一个方法
def increment_odometer(self, miles):
if miles >= 0:
self.odometer_reading += mileage
else:
print('You cannot roll back an aodometer!')
# 类外进行的操作
my_new_car.increment_odometer(10)
my_new_car.read_odometer()
Part Two 练习
# 9.4 就餐人数
print('---------- 9.4 ----------')
class Restaurant():
def __init__(self, restaurant_name, cuisine_type):
self.restaurant_name = restaurant_name
self.cuisine_type = cuisine_type
self.number_served = 0
def describe_restaurant(self):
print('restaurant_name: ' + self.restaurant_name)
print('cuisine_type: ' + self.cuisine_type)
def open_restaurant(self):
print('This restaurant ' + self.restaurant_name + ' is open now.')
def set_number_served(self, num):
if num >= self.number_served:
self.number_served = num
else:
print('Number of people served must increase at every time.')
def increment_number_served(self, num):
if num >= 0:
self.number_served += num
else:
print('Number of people served must increase at every time.')
my_restaurant = Restaurant('My Res', 'Chinese food')
print('Number of people served:', my_restaurant.number_served)
my_restaurant.set_number_served(10)
print('Number of people served:', my_restaurant.number_served)
my_restaurant.increment_number_served(5)
print('Number of people served:', my_restaurant.number_served)
# 9.5 尝试登录次数
print('---------- 9.5 ----------')
class User():
def __init__(self, first, last, **user_info):
self.first_name = first
self.last_name = last
self.user_info = {}
for k,v in user_info.items():
self.user_info[k] = v
self.loggin_attempts = 0
def describe_user(self):
print('first name: ' + self.first_name +
'; last name: ' + self.last_name)
for k,v in self.user_info.items():
print(k, ':', v)
def greet_user(self):
print('Hello! ', self.first_name, self.last_name)
def increment_loggin_attempts(self):
self.loggin_attempts += 1
def reset_loggin_attempts(self):
self.loggin_attempts = 0
user = User('Sunny', 'Sun', city='HeKou', age=23)
print('loggin attempts:', user.loggin_attempts)
user.increment_loggin_attempts()
print('loggin attempts:', user.loggin_attempts)
user.increment_loggin_attempts()
print('loggin attempts:', user.loggin_attempts)
user.increment_loggin_attempts()
print('loggin attempts:', user.loggin_attempts)
user.reset_loggin_attempts()
print('loggin attempts:', user.loggin_attempts)
继承
一个类继承另一个类时,它将自动获得另一个类的所有属性和方法。原来的类称为父类,新类称为子类。子类会继承父类的所有属性和方法,同时还可以定义自己的属性和方法。
子类的方法__init__()
# 这里写入前面的Car类
class Car():
# 类的主体
class ElectricCar(Car):
def __init__(self, make, model, year):
super().__init__(make, model, year)
my_tesla = ElectricCar('tesla', ',odel s', 2016)
print(my_tesla.get_descriptive_name())
- 在创建子类时,父类必须包含在当前文件中,并且位于子类的前面。
- 定义子类时,必须在括号内指定父类的名称。
super()
是一个特殊的函数,帮助python把子类和父类关联起来。这一行代码让python调用ElectricCar
的父类Car
的方法__init__()
,让ElectricCar
实例包含父类的所有属性。
给子类定义属性和方法
让一个类继承另外一个类后,可以添加区分子类和父类所需的新属性和方法。
# 这里写入前面的Car类
class Car():
# 类的主体
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', ',odel s', 2016)
print(my_tesla.get_descriptive_name())
my_tesla.describe_battery()
在上面的代码中,为子类添加了新的属性battery_size
并设置其初始值为0,同时也为子类加入了方法describe_battery()
.则所有根据类ElectricCar
创建的所有实例都包含这个属性,都可以调用这个方法,但是Car
的实例都不包含它们。
重写父类的方法
可以在子类中定义一个与父类的方法重名的方法,即对父类中的方法进行重写。这样python就只会关注于子类中定义的相应的方法。
将实例用作属性
可以在类的属性中添加另一个类的实例。
# 这里写入前面的Car类
class 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.")
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
的新类,它没有继承任何类。在它的初始化函数中,定义了一个默认形参battery_size
。
在ElectricCar
类中,定义了一个名为battery
的属性,它是Battery
类的一个实例。
Part Three 练习
# 9.6 冰淇淋小店
print('---------- 9.6 ----------')
class Restaurant():
def __init__(self, restaurant_name, cuisine_type):
self.restaurant_name = restaurant_name
self.cuisine_type = cuisine_type
self.number_served = 0
def describe_restaurant(self):
print('restaurant_name: ' + self.restaurant_name)
print('cuisine_type: ' + self.cuisine_type)
def open_restaurant(self):
print('This restaurant ' + self.restaurant_name + ' is open now.')
def set_number_served(self, num):
if num >= self.number_served:
self.number_served = num
else:
print('Number of people served must increase at every time.')
def increment_number_served(self, num):
if num >= 0:
self.number_served += num
else:
print('Number of people served must increase at every time.')
class IceCreamStand(Restaurant):
def __init__(self, restaurant_name, cuisine_type, *flavors):
super().__init__(restaurant_name, cuisine_type)
self.flavors = flavors
def display_flavors(self):
print("Here are some icecreams:")
for flavor in self.flavors:
print('\t' + str(flavor))
ice_cream_stand = IceCreamStand('ice cream', 'cold food',
'ice cream 1', 'ice cream 2','ice cream 3',)
ice_cream_stand.display_flavors()
# 9.7 管理员
print('---------- 9.6 ----------')
class User():
def __init__(self, first, last, **user_info):
self.first_name = first
self.last_name = last
self.user_info = {}
for k,v in user_info.items():
self.user_info[k] = v
self.loggin_attempts = 0
def describe_user(self):
print('first name: ' + self.first_name +
'; last name: ' + self.last_name)
for k,v in self.user_info.items():
print(k, ':', v)
def greet_user(self):
print('Hello! ', self.first_name, self.last_name)
def increment_loggin_attempts(self):
self.loggin_attempts += 1
def reset_loggin_attempts(self):
self.loggin_attempts = 0
class Admin(User):
def __init__(self, privileges, first, last, **user_info):
super().__init__(first, last, **user_info)
self.privileges = privileges
# privileges : 'can add post', 'can delete post', 'can be user'
def show_privileges(self):
print(str(self.privileges))
admin = Admin('can add post', 'Sunny', 'Sun', city='HeKou', age=23)
admin.show_privileges()
# 9.8 权限
print('---------- 9.6 ----------')
class Privileges():
def __init__(self, privileges):
self.privileges = privileges
def show_privileges(self):
print(str(self.privileges))
class Admin(User):
def __init__(self, privileges, first, last, **user_info):
super().__init__(first, last, **user_info)
self.privileges = Privileges(privileges)
admin = Admin('can add post', 'Sunny', 'Sun', city='HeKou', age=23)
admin.privileges.show_privileges()
# 9.9 电瓶升级
print('---------- 9.6 ----------')
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.')
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):
range = 0
if self.battery_size == 70:
range = 240
elif self.battery_size == 85:
range = 270
message = "This car can go approximately " + str(range) + " miles on a full charge"
print(message)
def update_battery(self):
if self.battery_size != 85:
self.battery_size = 85
class ElectricCar(Car):
def __init__(self, make, model, year):
super().__init__(make, model, year)
self.battery = Battery()
electric_car = ElectricCar('tesla', 'model s', 2016)
electric_car.battery.describe_battery()
electric_car.battery.get_range()
electric_car.battery.update_battery()
electric_car.battery.get_range()
导入类
导入单个类
将Car
类的定义放在car.py
文件里面。
在my_car.py
文件中导入Car
类并创建实例:from car import Car
在一个模块中存储多个类
将Battery
和ElectricCar
类都放在模块car.py
中,因为这些类中都是存在某种相关性的。
在my_electric_car.py
的文件中导入ElectricCar
类,并创建一辆电动汽车:from car import ElectricCar
从一个模块中导入多个类
my_car.py
文件中导入Car
和ElectricCar
两个类:from car import Car, ElectricCar
导入整个模块
my_cars.py
中import car
导入模块中的所有类
from module_name import *
在一个模块中导入另外一个模块
有时候需要将类分散到多个模块中,避免模块太大,或者在同一个模块中存储不相关的类。将类存储在多个模块时,发现一个模块中的类依赖于另一个模块中的类。在这种情况下,可以在前一个模块中导入必要的类。
from car import Car