python的自学之路—第九节:类

本文介绍了Python中的类概念,包括如何创建和使用类,如何通过类创建实例,设置和修改属性,以及如何使用方法。文章详细讲解了__init__方法,展示了属性和方法的使用,并探讨了类的继承机制,包括子类化、添加子类属性和方法,以及重写父类方法。此外,还讨论了导入类的不同方式。
摘要由CSDN通过智能技术生成

前言:这个博客是为了记录我的学习过程也是为了能够有一种动力学习python,欢迎大家监督更新此博客。
                          (更新:2023年3月3日)

第九节:类

一、创建和使用类

1.什么是类

类是一种自定义的数据类型,它可以用来描述某一类对象的属性和行为。在类中,属性通常表示对象的状态或者特征,而方法则表示对象能够进行的操作或者行为。类的定义包括类名、属性和方法的定义,它们可以被多个实例对象共享。

2.简单的创建一个类

我们来简单的创建一个类,这个类是一个Dog类,里面包含了Dog的名字跟年龄,并且赋予每条狗有蹲下(crouch)和打滚(roll_about)的能力(属性):

class Dog:   # 创建一个类,注意class 类的名称开头字母大写
    """简单的模拟小狗"""

    def __init__(self, name, age):   # 方法init  有两边有两个下划线,为dog类的默认方法,每次调用Dog类都会调用这个方法
        """初始化属性name和age。"""
        self.name = name
        self.age = age

    def crouch(self):
        """模拟小狗收到命令时蹲下。"""
        print(f"{self.name} is now sitting.")

    def roll_about(self):
        """模拟小狗收到命令时打滚。"""
        print(f"{self.name} rolled over!")
  • _ init _ 这边由于显示问题,这两边都是两条下划线的,方法__init__(),在类中,函数被称为方法,我们前面所学的函数的一切用法都适用于这里类的方法,唯一区别是调用的方法。

  • 方法__init__() 是一个特殊方法,每当你根据Dog 类创建新实例时,Python都会自动运行它。在这个方法的名称中,开头和末尾各有两个下划线,这是一种约定,旨在避免Python默认方法与普通 方法发生名称冲突。务必确保__init__() 的两边都有两个下划线,否则当你使用类来创建实例时,将不会自动调用这个方法,进而错误。

我们将方法__init__() 定义成包含三个形参:self 、name 和age 。在这个方法的定义中,形参self 必不可少,而且必须位于其他形参的前面。

为何必须在方法定义中包含形参self呢?因为Python调用这个方法来创建Dog实例时,将自动传入实参self 。每个与实例相关联的方法调用都自动传递实参self ,它是一个指向实例本身的引用,让实例能够访问类中的属性和方法。

创建Dog 实例时,Python将调用Dog 类的方法__init__() 。我们将通过实参向Dog() 传递名字和年龄,self 会自动传递,因此不需要传递它。每当根据Dog 类创建实例时,都只需给最后两个形参(name 和age )提供值。


_init_定义的两个变量都有前缀self 。以self 为前缀的变量可供类中的所有方法使用,可以通过类的任何实例来访问。

self.name = name 获取与形参name 相关联的值,并将其赋给变量name ,然后该变量被关联到当前创建的实例。self.age = age 的作用与此类似。像这样可通过实例访问的变量称为属性


Dog 类还定义了另外两个方法:sit() 和roll_over()。这些方法执行时不需要额外的信息,因此它们只有一个形参self 。我们随后将创建的实例能够访问这些方法,换句话说,它们都会蹲下和打滚。当前,sit() 和roll_over() 所做的有限,只是打印一条消息,指出小狗正在蹲下或打滚。

3.根据类来创建一个实例

my_dog = Dog(name="大黄", age=19)
print(f'我家的小狗叫{my_dog.name}')
print(f'今年它已经{my_dog.age}')

来简单的解释一下这个代码的运行过程

  • 第一行:(my_dog = Dog(name=“大黄”, age=19)),学习过函数的小伙伴都知道,这是一个函数,里面有两个形参,但是这里面是 所以这个函数在引用了Dog类的时候就变成的一个 实例,上面说了,任何一个实例调用这个类的时候都会默认执行_init_函数,所以这个实例的两个实参就被传递啊给了方法init。
  • 当将这两个实参传递给方法init的时候,他就会运行,变成所有实例都能调用的属性,就是self.name和self.age这就是属性
  • 第二三行:这两个分别是调用属性的用法,首先这个函数调用了类变成了一个实例,实例将实参传递给了默认方法init,实参的值变成了这个类的默认属性,然后我们调用这个属性的时候是实例名称+点+属性名称,注意self.name只是表示为默认属性,名称忽略前缀self。

官方解释:这这里使用的是前一个示例中编写的Dog 类。让Python创建一条名字 为’大黄’ 、年龄为19的小狗。遇到这行代码时,Python使用实参’大黄’ 和19调用Dog 类的方法__init__() 。方法__init__() 创建一个表示特定小狗的 实例,并使用提供的值来设置属性name 和age 。接下来,Python返回一个表示这条小狗的实例,而我们将这个实例赋给了变量my_dog 。在这里,命名约定很有 用:通常可认为首字母大写的名称(如Dog )指的是类,而小写的名称(如 my_dog )指的是根据类创建的实例。

4.调用属性

要访问实例的属性,可使用句点表示法。my_dog.name来访问my_dog 的属性name 的值。

句点表示法在Python中很常用,这种语法演示了Python如何获悉属性的值。在这里, Python先找到实例my_dog ,再查找与该实例相关联的属性name 。在Dog 类中引用这个属性时,使用的是self.name 。

5.调用方法

根据Dog 类创建实例后,就能使用句点表示法来调用Dog 类中定义的任何方法了。下面来让小狗蹲下和打滚:

my_dog = Dog(name="大黄", age=19)
my_dog.crouch()
my_dog.roll_about()
  • 这就像是调用函数一样很像,但是这个是类的方法,方法中唯一的形参是self,所以调用的时候不用传递任何参数
我家的小狗叫大黄
今年它已经19
大黄 is now sitting.
大黄 rolled over!

二、使用类和实例

1.初步只用类和实例

下面来编写一个表示汽车的类。它存储了有关汽车的信息,还有一个汇总这些信息的方法:

class Car:
    """ 汽车模拟类 """
    def __init__(self, name, km, much):
        """汽车的默认属性"""
        self.name = name
        self.km = km
        self.much = much

    def get_car_message(self):
        """返回汽车的完整信息"""
        message = f"这辆车的品牌是{self.name},车辆行驶里程|Km{self.km}公里,您一共需要支付{self.much}"
        return message.title()


my_car = Car(name="理想", km=28, much="288888元")
print(my_car.get_car_message())
  • 虽然写注释是个好习惯,但是好多字不想打哇,不懂就留言哈。
# 运行结果
这辆车的品牌是理想,车辆行驶里程|Km28公里,您一共需要支付288888

2.给属性指定默认值

创建实例时,有些属性无须通过形参来定义,可在方法__init__() 中为其指定默认值。
下面我们来创建一个磨损值(attrite),默认值为0,还添加一个show_attrite来显示车辆当前磨损值

class Car:
    """ 汽车模拟类 """
    def __init__(self, name, km, much):
        """汽车的默认属性"""
        self.name = name
        self.km = km
        self.much = much
        self.attrite = 0

    def get_car_message(self):
        """返回汽车的完整信息"""
        message = f"这辆车的品牌是{self.name},车辆行驶里程|Km{self.km}公里,您一共需要支付{self.much}"
        return message.title()

    def show_attrite(self):
        """显示车辆磨损值"""
        print(f'当前车辆的磨损值为:{self.attrite}%')


my_car = Car(name="理想", km=28, much="288888元")
print(my_car.get_car_message())
my_car.show_attrite()

  • 这里没有向里面传递attrite的值,所以程序默认值为0
# 运行结果
这辆车的品牌是理想,车辆行驶里程|Km28公里,您一共需要支付288888元
当前车辆的磨损值为:0%

3.修改默认值属性

a.直接修改属性的值

要修改属性的值,最简单的方式是通过实例直接访问它。下面的代码直接将磨损值读数设置为23:

my_car = Car(name="理想", km=28, much="288888元")
print(my_car.get_car_message())
my_car.attrite = 23
my_car.show_attrite()
  • 简单粗暴直接修改值即可
这辆车的品牌是理想,车辆行驶里程|Km28公里,您一共需要支付288888元
当前车辆的磨损值为:23%
b.通过方法来修改属性的值

使用方法来修改,这样就无须直接访问属性,而可将值传递给方法,由它在内部进行更新。

    def alter_attrite(self, alter):
        """修改车辆磨损值"""
        self.attrite = alter


my_car = Car(name="理想", km=28, much="288888元")
print(my_car.get_car_message())
my_car.alter_attrite(40)
my_car.show_attrite()
  • 前面的代码一致,只是增加了一个方法,这个方法是作用就是修改车辆的磨损值,我们在输出车辆的磨损值之前,先给这个方法传递一个值,这个方法会在内部更新这个磨损值,然后我们再输出车辆信息。
这辆车的品牌是理想,车辆行驶里程|Km28公里,您一共需要支付288888元
当前车辆的磨损值为:40%

在方法里面设置限制,磨损值不能减小修改

    def alter_attrite(self, alter):
        """修改车辆磨损值"""
        if self.attrite < alter:
            self.attrite = alter
        elif self.attrite > alter:
            print("非法操作禁止修改")


my_car = Car(name="理想", km=28, much="288888元")
print(my_car.get_car_message())
my_car.alter_attrite(40)
my_car.show_attrite()
my_car.alter_attrite(30))
  • 这是防止出现不符合逻辑的修改,在上面传递40%之后再传递30%为非法操作
# 运行结果
这辆车的品牌是理想,车辆行驶里程|Km28公里,您一共需要支付288888元
当前车辆的磨损值为:40%
非法操作禁止修改
c.通过方法对属性的值进行递增

我们的值不止有初始值,还有可能在转运中会增加一下磨损或者公里这都很正常,我们可以在原有的基础上增加而不是直接修改


    def add_attrite(self, add):
        self.attrite += add


my_car = Car(name="理想", km=28, much="288888元")
print(my_car.get_car_message())
my_car.alter_attrite(40)
my_car.show_attrite()
my_car.add_attrite(15)
my_car.show_attrite()
my_car.alter_attrite(30)
  • 简单的加法运算
这辆车的品牌是理想,车辆行驶里程|Km28公里,您一共需要支付288888元
当前车辆的磨损值为:40%
当前车辆的磨损值为:55%
非法操作禁止修改

三、继承

1.概念

编写类时,并非总是要从空白开始。如果要编写的类是另一个现成类的特殊版本, 可使用继承 。一个类继承另一个类时,将自动获得另一个类的所有属性和方法。 原有的类称为父类 ,而新类称为子类 。子类继承了父类的所有属性和方法,同时 还可以定义自己的属性和方法

在既有类的基础上编写新类时,通常要调用父类的方法__init__() 。这将初始化在父类__init__() 方法中定义的所有属性,从而让子类包含这些属性。


class Elecar(Car):
    """继承汽车的电动汽车"""
    def __init__(self, name, km, much):
        super().__init__(name, km, much)


my_eleacr = Elecar('特斯拉', 200, "190000元")
print(my_eleacr.get_car_message())

  • 上面的Car类的代码不动,最后面添加上述代码,即创建子类Elecar。创建子类时,父类必须包含在当前文件中,且位于子类前面
  • super() 是一个特殊函数,让你能够调用父类的方法。这行代码让Python调用Car 类的方法__init__() ,让Elecarr 实例包含这个方法中定义的所有属性。父类也称为超类 (superclass),名称super 由此而来。
这辆车的品牌是特斯拉,车辆行驶里程|Km200公里,您一共需要支付190000

2.在继承父类下增加子类自身属性

我们在继承了父类之后,可以在自身子类下面添加自己的属性,这个属性只能在自己子类中使用,父类无法使用

class Elecar(Car):
    """继承汽车的电动汽车"""
    def __init__(self, name, km, much):
        super().__init__(name, km, much)
        self.capacity = "80度电"

    def car_capacity(self):
        print(f"当前的电池容量为:{self.capacity}")


my_eleacr = Elecar('特斯拉', 200, "190000元")
print(my_eleacr.get_car_message())
print(my_eleacr.car_capacity())
  • 调用方式跟父类一致
# 运行结果
这辆车的品牌是特斯拉,车辆行驶里程|Km200公里,您一共需要支付190000元
当前的电池容量为:80度电

3.修改父类的方法在子类中的内容

对于父类的方法,只要它不符合子类模拟的实物的行为,都可以进行重写。为此, 可在子类中定义一个与要重写的父类方法同名的方法。这样,Python将不会考虑这个父类方法,而只关注你在子类中定义的相应方法。

比如说,电动车没有磨损值这一说

    def car_capacity(self):
        print(f"当前的电池容量为:{self.capacity}")

    def alter_attrite(self, alter_s):
        print("电动汽车没有磨损值")


my_eleacr = Elecar('特斯拉', 200, "190000元")
print(my_eleacr.get_car_message())
print(my_eleacr.car_capacity())
my_eleacr.alter_attrite(40)
my_car = Car(name="理想", km=28, much="288888元")
my_car.alter_attrite(40)
  • 只要方法名相同即可,形参的名字随意
# 运行结果
这辆车的品牌是特斯拉,车辆行驶里程|Km200公里,您一共需要支付190000元
当前的电池容量为:80度电
电动汽车没有磨损值

4.将实例用作属性

使用代码模拟实物时,你可能会发现自己给类添加的细节越来越多:属性和方法清单以及文件都越来越长。在这种情况下,可能需要将类的一部分提取出来,作为一个独立的类。可以将大型类拆分成多个协同工作的小类。

class Car:
    """ 汽车模拟类 """
    def __init__(self, name, km, much):
        """汽车的默认属性"""
        self.name = name
        self.km = km
        self.much = much
        self.attrite = 0

    def get_car_message(self):
        """返回汽车的完整信息"""
        message = f"这辆车的品牌是{self.name},车辆行驶里程|Km{self.km}公里,您一共需要支付{self.much}"
        return message.title()

    def show_attrite(self):
        """显示车辆磨损值"""
        print(f'当前车辆的磨损值为:{self.attrite}%')

    def alter_attrite(self, alter):
        """修改车辆磨损值"""
        if self.attrite < alter:
            self.attrite = alter
        elif self.attrite > alter:
            print("非法操作禁止修改")

    def add_attrite(self, add):
        self.attrite += add


class End_car:
    def __init__(self, end=170, end_s=500):
        self.end = end
        self.end_s = end_s

    def car_end(self):
        print(f"这辆车的续航为{self.end}")
        print(f"长续航版本为{self.end_s}")


class Elecar(Car):
    """继承汽车的电动汽车"""
    def __init__(self, name, km, much):
        super().__init__(name, km, much)
        self.capacity = "80度电"
        self.end_elecar = End_car(end_s=500)

    def car_capacity(self):
        print(f"当前的电池容量为:{self.capacity}")

    # def end_carr(self):


    def alter_attrite(self, alter_s):
        print("电动汽车没有磨损值")


my_eleacr = Elecar('特斯拉', 200, "190000元")
print(my_eleacr.get_car_message())
print(my_eleacr.car_capacity())
my_eleacr.alter_attrite(40)
my_end = End_car(700, 1000)
my_eleacr.end_elecar.car_end()   # 这里注意调用方法有两个点
  • 注意最后面的代码调用是两个点,这个类和方法的名称最好能一眼看懂是什么作用最好
# 运行结果
这辆车的品牌是特斯拉,车辆行驶里程|Km200公里,您一共需要支付190000元
当前的电池容量为:80度电
电动汽车没有磨损值
这辆车的续航为170
长续航版本为500

三、导入类

导入单个类

导入步骤

  • 首先我们把class Car 类剪切出来,我们再创建一个car.py的python文件,把Car类放进去
  • 然后我们再在文件的开头写上引入,引入方式跟模块类似from car import Car
  • 这样即可使用Car类里面的功能,即相当于在同一个文件内

导入一个文件的多个类

简单粗暴点吧

from car import Car, End_car
  • 想要啥类就在import后面写啥类,每个类用逗号隔开

导入文件所有的类

import car
  • 简单粗暴完事,直接导入整个文件名即可使用整个文件中的类

使用别名

第8节说过,使用模块来组织项目代码时,别名大有裨益。导入类时,也可为其指定别名。

from car import Car as a 
  • 现在使用a级相当于使用Car,当然这个是我随便写的,现实中别名也要好好规划避免报错或者自己都不认识自己写的代码那就尴尬了。

这一节顺利结束,类真的好难学哇,我都快迷糊了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AI_老猫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值