面向对象编程是最有效的软件编写方法之一。在面向对象编程中,你编写表示现实世界中的事物和情景的类,并基于这些类来创建对象。编写类时,你定义一大类对象都有的通用行为。基于类创建对象时,每个对象都自动具备这种通用行为,然后可根据需要赋予每个对象独特的个性。使用面向对象编程可模拟现实情景,其逼真程度达到了令你惊讶的地步。
​ 根据类来创建对象被称为实例化,这让你能够使用类的实例。在本章中,你将编写一些类并创建其实例。你将指定可在实例中存储什么信息,定义可对这些实例执行哪些操作。你还将编写一些类来扩展既有类的功能,让相似的类能够高效地共享代码。你将把自己编写的类存储在模块中,并在自己的程序文件中导入其他程序员编写的类。

创建类和使用类

​ 使用类几乎可以模拟任何东西。

创建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

将实例作用属性

​ 有些情况下,可能需要将类的一部分作为一个独立的类提取出来,