类
面向对象编程是最有效的软件编写方法之一。在面向对象编程中,你编写表示现实世界中的事物和情景的类,并基于这些类来创建对象。编写类时,你定义一大类对象都有的通用行为。基于类创建对象时,每个对象都自动具备这种通用行为,然后可根据需要赋予每个对象独特的个性。使用面向对象编程可模拟现实情景,其逼真程度达到了令你惊讶的地步。
根据类来创建对象被称为实例化,这让你能够使用类的实例。在本章中,你将编写一些类并创建其实例。你将指定可在实例中存储什么信息,定义可对这些实例执行哪些操作。你还将编写一些类来扩展既有类的功能,让相似的类能够高效地共享代码。你将把自己编写的类存储在模块中,并在自己的程序文件中导入其他程序员编写的类。
创建类和使用类
使用类几乎可以模拟任何东西。
创建dog类
根据dog类创建的每个实例都将存储名字和年龄。赋予每条小狗蹲下和打滚的能力
##首字母大写为类
class Dog:
"""
模拟小狗
"""
###__init__()是一个特色方法,当你根据类来创建实列的时候,python都会自动运行它,开头和末尾的__都是一种约定,避免和其他名字发生冲入,形参self必不可少
###当你创建实列时,self指向的就是这个实列本身
###我们将通过实参向Dog()传递名字和年龄;self会自动传递,因此我们不需要传递它。每当我们根据Dog类创建实例时,都只需给最后两个形参( name和age)提供值。
def __init__(self, name, age):
"""初始化name,age"""
###处定义的两个变量都有前缀self。以self为前缀的变量都可供类中的所有方法使用,我们还可以通过类的任何实例来访问这些变量。self.name = name获取存储在形参name中的值,并将其存储到变量name中,然后该变量被关联到当前创建的实例。self.age = age的作用与此类似。
##这里定义了self.name和slie.age这种为变量被称为属性,以self为前缀开始的变量可供类中的所有方法使用
self.name = name
self.age = age
##现在由于这些方法不需要额外的信息,因此他们只有有个形参self
def sit(self):
print(self.name.title() + '现在蹲下!!')
def roll_over(self):
print(self.name.title() + '现在打滚!!')
根据类创建实例
上面的Dog类是一系列说明,让python知道如何创建表示特定小狗的实列
class Dog:
##这里是接着上面的
.......
##创建实列Dog类括号内传递参数就是__init__的作用
my_dog = Dog('smith', '4')
##这里是访问类的属性name,就是实列名.类属性
print('我的dog的名字叫'+my_dog.name)
print('它'+my_dog.age+'岁了')
##调用定义的方法
my_dog.sit()
my_dog.roll_over()
print("\n")
###还可以创建多个实列、
her_dog = Dog('william', '3')
print('她的dog的名字叫'+her_dog.name)
print('它'+her_dog.age+'岁了')
her_dog.sit()
her_dog.roll_over()
####执行
我的dog的名字叫smith
它4岁了
Smith现在蹲下!!
Smith现在打滚!!
她的dog的名字叫william
它3岁了
William现在蹲下!!
William现在打滚!!
创建一个名为 Restaurant的类,其方法_init_()设置两个属性:restaurant_name和 cuisine_type。创建一个名为describe_restaurant()的方法和一个名open_restaurant()的方法,其中前者打印前述两项信息,而后者打印一条消息,指出餐馆正在营业。
根据这个类创建一个名为restaurant 的实例,分别打印其两个属性,再调用前述两个方法。
class Restaurant:
def __init__(self,restaurant_name,cuisine_type):
self.restaurant_name = restaurant_name
self.cuisine_type = cuisine_type
def describe_restaurant(self):
print("餐馆名:"+self.restaurant_name+", 主要菜系为:"+self.cuisine_type)
def open_restaurant(self):
print(self.restaurant_name+'正在营业中...')
restaurant = Restaurant('川菜馆', '川菜')
print(restaurant.restaurant_name)
print(restaurant.cuisine_type)
print('----------------------------------------')
restaurant.describe_restaurant()
restaurant.open_restaurant()
###执行
川菜馆
川菜
----------------------------------------
餐馆名:川菜馆, 主要菜系为:川菜
川菜馆正在营业中...
使用类和实列
你需要执行的一个重要任务是修改实列的属性。你可以直接修改实列的属性。你可以直接修改实列的属性,也可以编写方法特定的方式进行修改
Car类
下面来编写一个表示汽车的类,它存储了有关汽车的信息,还有一个汇总这些信息
class Car:
def __init__(self, makes, models, years):
"""初始化描述信息"""
self.make = makes
self.model = models
self.year = years
def get_desc(self):
"""返回car的描述信息"""
car_name = str(self.year) + '-' + str(self.make) + '-' + str(self.model)
return car_name.title()
print('请按提示输入汽车的信息(输入q退出)')
print('----------------------------------------------------------')
###循环输入
while True:
make = input('请输入汽车的生成地:')
if make == 'q':
break
model = input('输入汽车的大小:')
if model == 'q':
break
year = input("请输入汽车的生产年份:")
if year == 'q':
break
##传递参数
##循环创建实列
name = Car(make, model, year)
print(name.get_desc())
###执行
请按提示输入汽车的信息(输入q退出)
----------------------------------------------------------
请输入汽车的生成地:china
输入汽车的大小:moddle
请输入汽车的生产年份:2021
2021-China-Moddle
请输入汽车的生成地:q
Process finished with exit code 0
给定属性指定默认值
类中的每个属性都必须要有初始值,哪怕这个值是0或者空字符
如果你对某个属性赋予了初始值,那就没必要为它做一个形参了
##接下来为这个固定添加公司名字
class Car:
def __init__(self, makes, models, years):
"""初始化描述信息"""
self.make = makes
self.model = models
self.year = years
self.comp = 'niuB' ##添加的默认值
def get_desc(self):
"""放回car的描述信息"""
car_name = str(self.year) + '-' + str(self.make) + '-' + str(self.model)+'--'+self.comp ###添加默认值self.comp
return car_name.title()
print('请按提示输入汽车的信息(输入q退出)')
print('----------------------------------------------------------')
###循环输入
while True:
make = input('请输入汽车的生成地:')
if make == 'q':
break
model = input('输入汽车的大小:')
if model == 'q':
break
year = input("请输入汽车的生产年份:")
if year == 'q':
break
name = Car(make, model, year)
print(name.get_desc())
##执行
请按提示输入汽车的信息(输入q退出)
----------------------------------------------------------
请输入汽车的生成地:china
输入汽车的大小:moddle
请输入汽车的生产年份:2021
2021-China-Moddle--Niub
请输入汽车的生成地:q
修改属性的值
有三种方法可以修改属性的值:
直接通过实列来进行修改
通过方法进行设置
通过方法进行递增
直接修改属性的值
直接再实列里面修改
##依照上面的代码在实列内改
class Car:
def __init__(self, makes, models, years):
"""初始化描述信息"""
self.make = makes
self.model = models
self.year = years
self.comp = 'niuB' ##添加的默认值
def get_desc(self):
"""放回car的描述信息"""
car_name = str(self.year) + '-' + str(self.make) + '-' + str(self.model)+'--'+self.comp ###添加默认值self.comp
return car_name.title()
name = Car('China', 'moddle', '2021')
##直接修改
name.comp = 'HNGY'
print(name.get_desc())
###执行
2021-China-Moddle--Hngy
通过方法来修改属性的值
你可以无需直接访问属性,而可将值传递给一个方法,由它在内部进行更新
###把之前的公司改为车子的保修年份
class Car:
def __init__(self, makes, models, years):
"""初始化描述信息"""
self.make = makes
self.model = models
self.year = years
self.warranty = 3 ##添加的默认值
def get_desc(self):
"""放回car的描述信息"""
car_name = str(self.year) + '-' + str(self.make) + '-' + str(self.model) ###添加默认值self.comp
return car_name.title()
##定义一个更新保修的方法
def update_warranty(self, warranty):
"""如果默认的保修小于或者小于输入的保修则会询问一下是否修改,如果用户输入n不修改,输入y修改"""
###当然可以直接使用一下代码修改,不用加那么多的询问语句
###self.warranty = warranty
if warranty >= warranty:
data = input("确定要将保修回调吗?输入(y/n):")
if data == 'y':
self.warranty = warranty
elif warranty <= warranty:
data = input("确定要将保修更新吗?输入(y/n):")
if data == 'y':
self.warranty = warranty
###打印保修日期
print('现在的保修是;'+ str (warranty) + '年')
Car_data = Car('china', 'big', '2021')
print(Car_data.get_desc())
##执行update函数时会循环是否修改,如果用户不想修改就会跳过修改
data_warranty_choose = input('需要调节保修吗?(y/n)')
if data_warranty_choose == 'y':
###如果用户想要修改的话,这里我使用了input函数传递给update函数
Car_data.update_warranty(input('输入保修日期:'))
##执行
2021-China-Big
需要调节保修吗?(y/n)y
输入保修日期:10
确定要将保修回调吗?输入(y/n):y
现在的保修是;10年
通过方法对属性的值进行递增
如果你需要递增特定的或者递减,而不是将其设置为全选的值
假如我保修有3年,我可以每年递减一年的保修,但是如果每年的话还要进行时间循环,现在就没这个必要了
class Car:
def __init__(self, makes, models, years):
"""初始化描述信息"""
self.make = makes
self.model = models
self.year = years
self.warranty = 3 ##添加的默认值
def get_desc(self):
"""放回car的描述信息"""
car_name = str(self.year) + '-' + str(self.make) + '-' + str(self.model) ###添加默认值self.comp
return car_name.title()
##定义一个方法让保修递减
def descrease_warranty(self,year):
self.warranty -= year
print('现在保修还有'+ str(self.warranty) + '年' )
Car_data = Car('china', 'big', '2021')
print(Car_data.get_desc())
##其实这里可以用个时间循环
##递减保修多少年
Car_data.descrease_warranty(1)
###执行
2021-China-Big
现在保修还有2年
尝试登录次数:在为完成练习9-3而编写的 User类中,添加一个名为login_attempts 的属性。编写一个名为increment_login_attempts()的方法,它将属性login_attempts的值加1。再编写一个名为reset_login_attempts()的方法,它将属性login_attempts的值重置为0。
根据User类创建一个实例,再调用方法increment_login_attempts()多次。打印属性login_attempts的值,确认它被正确地递增;然后,调用方法reset_login_attempts(),并再次打印属性login_attempts 的值,确认它被重置为0。
class login:
def __init__(self):
self.login_apptempt = 0
def increment_login_appempts(self):
"""登录依次就加一"""
self.login_apptempt += 1
return self.login_apptempt
def reset_login_apptempts(self):
"""把登录次数归0"""
self.login_apptempt = 0
return self.login_apptempt
login_apptempts = login()
for i in range(5):
print(login_apptempts.increment_login_appempts())
print(login_apptempts.reset_login_apptempts())
###执行
1
0
1
0
1
0
1
0
1
0
继承
一个类继承另一个类时,它将自动获得另一个类的所有属性和方法;原有的类被称为父类,而新类被称为子类,子类继承了其父类的所有属性和方法,同时还可以定义自己的属性和方法
子类的方法__ init __()
创建子类实列是,Python首先需要完成的任务是给父类的所有属性赋值。为此
我们依照car类来衍生一个新能源汽车,super()函数使用来将父类和子类关联起来的,
class Car:
def __init__(self, makes, models, years):
"""初始化描述信息"""
self.make = makes
self.model = models
self.year = years
self.warranty = 3 ##添加的默认值
def get_desc(self):
"""放回car的描述信息"""
car_name = str(self.year) + '-' + str(self.make) + '-' + str(self.model) ###添加默认值self.comp
return car_name.title()
def update_warranty(self, warranty):
"""如果默认的保修小于或者小于输入的保修则会询问一下是否修改,如果用户输入n不修改,输入y修改"""
if warranty >= warranty:
data = input("确定要将保修回调吗?输入(y/n):")
if data == 'y':
self.warranty = warranty
elif warranty <= warranty:
data = input("确定要将保修更新吗?输入(y/n):")
if data == 'y':
self.warranty = warranty
###打印保修日期
print('现在的保修是;' + str(self.warranty) + '年')
##方法递减
def descrease_warranty(self,year):
self.warranty -= year
print('现在的保修是;' + str(self.warranty) + '年')
##定义一个新能源子类
class new_energy(Car):
"""新能源汽车类"""
def __init__(self, makes, models, years):
super().__init__(makes, models, years)
##创建子类的实例
my_car = new_energy('china', 'BYD-宋', '2021')
print(my_car.get_desc())
###执行
2021-China-Byd-宋
当然子类也可以定义它的属性和方法
class Car:
def __init__(self, makes, models, years):
"""初始化描述信息"""
self.make = makes
self.model = models
self.year = years
self.warranty = 3 ##添加的默认值
def get_desc(self):
"""放回car的描述信息"""
car_name = str(self.year) + '-' + str(self.make) + '-' + str(self.model) ###添加默认值self.comp
return car_name.title()
def update_warranty(self, warranty):
"""如果默认的保修小于或者小于输入的保修则会询问一下是否修改,如果用户输入n不修改,输入y修改"""
if warranty >= warranty:
data = input("确定要将保修回调吗?输入(y/n):")
if data == 'y':
self.warranty = warranty
elif warranty <= warranty:
data = input("确定要将保修更新吗?输入(y/n):")
if data == 'y':
self.warranty = warranty
###打印保修日期
print('现在的保修是;' + str(self.warranty) + '年')
##方法递减
def descrease_warranty(self, year):
self.warranty -= year
print('现在的保修是;' + str(self.warranty) + '年')
##定义一个新能源子类
class new_energy(Car):
"""新能源汽车类"""
def __init__(self, makes, models, years):
super().__init__(makes, models, years)
self.battery_size = 70
def get_desc_energy(self):
"""打印电池信息"""
print('这款车的电池容量为'+str(self.battery_size))
##创建子类的实例
my_car = new_energy('china', 'BYD-宋', '2021')
print(my_car.get_desc())
my_car.get_desc_energy()
###执行
2021-China-Byd-宋
这款车的电池容量为70
将实例作用属性
有些情况下,可能需要将类的一部分作为一个独立的类提取出来,