Python 基础:类

news2024/11/22 16:28:54

目录

  • 一、类的概念
  • 二、定义类
  • 三、创建对象并进行访问
  • 四、修改属性的值
    • 方法一:句点表示法直接访问并修改
    • 方法二:通过方法进行修改
  • 五、继承
    • 继承父类属性和方法
    • 重写父类方法
  • 六、将实例用作属性
  • 七、导入类
    • 导入单个类
    • 从一个模块中导入多个类
    • 导入整个模块
    • 导入模块中的所有类
  • 八、一些代码编写规范

遇到看不明白的地方,欢迎在评论中留言呐,一起讨论,一起进步!
在这里插入图片描述
本文参考:《Python编程:从入门到实践(第2版)》

一、类的概念

是是一种定义对象结构的方式,它包含了属性(变量)和行为(方法),这些行为的代码可以操作这些变量。类可以看作是一个模板,用来创建具有相同属性和方法的对象实例。通过类,我们可以实例化出各种各样具体的对象

在这里插入图片描述

二、定义类

定义一个类非常简单,只需要使用 class 关键字,后面跟着类名(首字母大写),然后是冒号。类体中的代码块定义了类的属性和方法。

class Car:
    def __init__(self, make, model, year):
        self.make = make
        self.model = model
        self.year = year

    def description(self):
        return f"{self.year} {self.make} {self.model}"

在上面的例子中,Car 是一个类,它有三个属性:makemodelyear

__init__(开头结尾都有两个下划线)方法是一个特殊的方法,被称为类的构造器,它在创建类的新实例时自动调用。在这个方法中,形参 self 必不可少。

__init__ 方法中,我们可以指定属性的默认值,下面来添加一个名为 odometer_reading 的属性,其初始值总是为 0:

class Car:
    def __init__(self, make, model, year):
        self.make = make
        self.model = model
        self.year = year
        self.odometer_reading = 0  # 指定属性的默认值
    ...

注:方法的第一个参数总是 self,它代表当前对象的实例。

三、创建对象并进行访问

一旦定义了一个类,就可以使用它来创建对象。在Python中,我们使用 ClassName() 的方式来创建一个类的新实例,这时会自动调用方法 __init__,并使用提供的值来设置对象的属性。这种方式最后会返回一个对象的实例,我们再将这个实例赋值给一个变量(小写字母表示)进行存储。

my_car = Car("Toyota", "Corolla", 2020)

要访问实例的属性,使用句点表示法:对象变量.属性名

print(my_car.year)

要调用实例的方法,也使用句点表示法:对象变量.方法名()

print(my_car.description())

我们可以根据一个类创建任意数量的实例,这些实例都存储在不同的变量中,互不影响。

四、修改属性的值

方法一:句点表示法直接访问并修改

class Car:
    def __init__(self, make, model, year):
        self.make = make
        self.model = model
        self.year = year
        self.odometer_reading = 0  # 指定属性的默认值
    ... 

my_car = Car("Toyota", "Corolla", 2020)
print(my_car.description())
my_car.odometer_reading = 23  # 直接修改属性的值
print(my_car.description())

执行结果:
在这里插入图片描述

方法二:通过方法进行修改

class Car:
    def __init__(self, make, model, year):
        self.make = make
        self.model = model
        self.year = year
        self.odometer_reading = 0

    def update_odometer(self, mileage):
        """将里程表读数设置为指定的值。"""
        self.odometer_reading = mileage

    def description(self):
        return f"{self.year} {self.make} {self.model} {self.odometer_reading}"


my_car = Car("Toyota", "Corolla", 2020)
print(my_car.description())
my_car.update_odometer(99)  # 通过方法修改
print(my_car.description())

执行结果:
在这里插入图片描述

五、继承

继承父类属性和方法

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

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

super() 是一个特殊函数,让子类能够调用父类的方法。父类也称为超类 (superclass),名称 super 由此而来。

在下面的例子中,ElectricCar 类继承了 Car 类,并添加了一个新的属性 battery_size 和相应的方法。

class Car:
    def __init__(self, make, model, year):
        self.make = make
        self.model = model
        self.year = year
        self.odometer_reading = 0
    ...

class ElectricCar(Car):  # 注意格式
    def __init__(self, make, model, year, battery_size):
        super().__init__(make, model, year)  # 要调用父类的__init__()方法
        self.battery_size = battery_size

    def display_battery(self):
        return f"Battery size: {self.battery_size} kWh"

👉 这里有几点需要注意:

  1. 创建子类时,父类必须包含在当前文件中,且位于子类前面
  2. 定义子类时,必须在圆括号内指定父类的名称

重写父类方法

重写父类的方法时,可在子类中定义一个与要重写的父类方法同名的方法。这样,Python 将不会考虑这个父类方法,而只关注你在子类中定义的相应方法。

假设 Car 类有一个名为 fill_gas_tank() 的方法,它对全电动汽车来说毫无意义,因此你可能想重写它。下面演示了一种重写方式:

class ElectricCar(Car):
    -...

    def fill_gas_tank(self):
        """电动汽车没有油箱。"""
        print("This car doesn't need a gas tank!")
    ...

现在,如果有人对电动汽车调用方法 fill_gas_tank(),Python 将忽略 Car 类中的方法 fill_gas_tank(),转而运行上述代码。

使用继承时,可让子类保留从父类那里继承而来的精华,并剔除不需要的糟粕。

六、将实例用作属性

有时可能需要将类的一部分提取出来,作为一个独立的类,这样可以将大型类拆分成多个协同工作的小类。

class Car:
    def __init__(self, make, model, year):
        self.make = make
        self.model = model
        self.year = year
        self.odometer_reading = 0

    def update_odometer(self, mileage):
        """将里程表读数设置为指定的值。"""
        self.odometer_reading = mileage

    def description(self):
        return f"{self.year} {self.make} {self.model} {self.odometer_reading}"

class Battery:
    """一次模拟电动汽车电瓶的简单尝试。"""
    def __init__(self,battery_size=75):
        """初始化电瓶的属性。"""
        self.battery_size = battery_size

    def describe_battery(self):
        """打印一条描述电瓶容量的消息。"""
        print(f"This car has a {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',2019)
my_tesla.battery.describe_battery()

执行结果:
在这里插入图片描述

七、导入类

Python 允许将类存储在模块中,然后在主程序中导入所需的模块。

导入单个类

car.py:(模块,文件名 car 就是模块名)

"""一个可用于表示汽车的类。"""
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 = f"{self.year} {self.make} {self.model}"
        return long_name.title()

    def read_odometer(self):
        """打印一条消息,指出汽车的里程。"""
        print(f"This car has {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

my_car.py:(主程序)

from car import Car

my_new_car = Car('audi','a4',2019)
print(my_new_car.get_descriptive_name())

my_new_car.odometer_reading = 23
my_new_car.read_odometer()

执行结果:
在这里插入图片描述

从一个模块中导入多个类

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 = f"{self.year} {self.make} {self.model}"
        return long_name.title()

    def read_odometer(self):
        """打印一条消息,指出汽车的里程。"""
        print(f"This car has {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=75):
        """初始化电瓶的属性。"""
        self.battery_size = battery_size

    def describe_battery(self):
        """打印一条描述电瓶容量的消息。"""
        print(f"This car has a {self.battery_size}-kWh battery.")

    def get_range(self):
        """打印一条描述电瓶续航里程的消息。"""
        if self.battery_size == 75:
            range = 260
        elif self.battery_size == 100:
            range = 315

        print(f"This car can go about {range} miles on a full charge.")

class ElectricCar(Car):
    """模拟电动汽车的独特之处。"""

    def __init__(self,make,model,year):
        """
        初始化父类的属性。
        再初始化电动汽车特有的属性。
        """
        super().__init__(make,model,year)
        self.battery = Battery()

my_cars.py:(主程序)

from car import Car,ElectricCar  # 多个类用逗号分隔

my_beetle = Car('volkswagen','beetle',2019)
print(my_beetle.get_descriptive_name())

my_tesla = ElectricCar('tesla','roadster',2019)
print(my_tesla.get_descriptive_name())

执行结果:
在这里插入图片描述

导入整个模块

还可以导入整个模块,再使用句点表示法访问需要的类
my_cars.py:(主程序)

import car

my_beetle = car.Car('volkswagen','beetle',2019)  # 句点表示法
print(my_beetle.get_descriptive_name())

my_tesla = car.ElectricCar('tesla','roadster',2019)  # 句点表示法
print(my_tesla.get_descriptive_name())

导入模块中的所有类

from module_name import *

不推荐使用这种导入方式。这种方式可能引发名称方面的同名问题,难以诊断。

需要从一个模块中导入很多类时,最好导入整个模块,并使用 模块名.类名 语法来访问类

八、一些代码编写规范

类名应采用驼峰命名法,即将类名中的每个单词的首字母都大写,而不使用下划线。
实例名模块名都采用小写格式,并在单词之间加上下划线

对于每个类,都应紧跟在类定义后面包含一个文档字符串,简要地描述类的功能。
每个模块也都应包含一个文档字符串,对其中的类可用于做什么进行描述。

在类中,可使用一个空行来分隔方法。
而在模块中,可使用两个空行来分隔类。

先编写导入标准库模块的 import 语句,再添加一个空行,然后编写导入自己编写的模块的 import 语句

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1829325.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

简单谈谈云服务器私网IP的存在意义及优势

云服务器是基于虚拟化技术的计算资源,可以在云平台上灵活创建和管理。为了满足不同用户的需求,云服务提供商在云服务器上分配了两种类型的IP地址:公网IP和私网IP。其中,私网IP是指在局域网内使用的内部IP地址,无法通过…

TF-IDF(Term Frequency-Inverse Document Frequency)

TF-IDF(Term Frequency-Inverse Document Frequency)是一种常用于信息检索和文本挖掘的统计方法,用以评估一个词语对于一个文件集或一个语料库中的其中一份文件的重要程度。它的重要性随着词语在文本中出现的次数成正比增加,但同时…

《Cloud Native Data Center Networking》(云原生数据中心网络设计)读书笔记 -- 01 为什么需要一个新的网络架构

关于专栏 本专栏是工作之后阅读 Cloud Native Data Center Networking ( O’Reilly, 2019)的读书笔记。这本书是我在数据中心从事云网络工作的启蒙、扫盲读物。可惜,其中文版翻译并非尽善尽美,必须结合英文原版才能理解原作者要表…

xss+csrf项目实例

项目背景: 如下:我们是在一个类似文章管理系统的网站上面发现的该漏洞。我们将其运行在本地的phpstudy集成环境上面。 源码地址下载链接:https://pan.baidu.com/s/1MpnSAq7a_oOcGh4XgPE-2w 提取码:4444 考察内容: …

盗版游戏缺少steamdll文件怎么办?游戏报错steam_api64.dll缺失解决方法

steam_api64.dll 是一个针对64位Windows操作系统设计的动态链接库文件,其核心作用是实现运行在Windows上的应用程序与Steam客户端之间的通信。该文件通常大小在1.5-3.5 MB之间,对于Steam平台的正常运行至关重要。 功能概述: 游戏验证&#…

Linux:线程池

Linux:线程池 线程池概念封装线程基本结构构造函数相关接口线程类总代码 封装线程池基本结构构造与析构初始化启动与回收主线程放任务其他线程读取任务终止线程池测试线程池总代码 线程池概念 线程池是一种线程使用模式。线程过多会带来调度开销,进而影…

第一篇——怎样堵住我们人生错误的源头

目录 一、背景介绍二、思路&方案三、过程1.思维导图2.文章中经典的句子理解3.学习之后对于投资市场的理解4.通过这篇文章结合我知道的东西我能想到什么? 四、总结五、升华 一、背景介绍 再次开始了孙子兵法的学习,之前听完就让我醍醐灌顶&#xff0…

Linux:基础IO(二.缓冲区、模拟一下缓冲区、详细讲解文件系统)

上次介绍了:Linux:基础IO(一.C语言文件接口与系统调用、默认打开的文件流、详解文件描述符与dup2系统调用) 文章目录 1.缓冲区1.1概念1.2作用与意义 2.语言级别的缓冲区2.1刷新策略2.2具体在哪里2.3支持格式化 3.自己来模拟一下缓…

【数据库编程-SQLite3(一)】sqlite3数据库在Windows下的配置及测试

学习分析 1、资源准备2、环境配置2.1、将资源包下载解压缩保存。2.2、在QT中创建工程,配置环境 3、测试配置3.1、 sqlite3_open函数3.2、sqlite3_close函数3.3、代码测试 1、资源准备 资源包 2、环境配置 2.1、将资源包下载解压缩保存。 解压缩得到以下文件 2.2、在QT中创建…

JavaFX VBox

VBox布局将子节点堆叠在垂直列中。新添加的子节点被放置在上一个子节点的下面。默认情况下,VBox尊重子节点的首选宽度和高度。 当父节点不可调整大小时,例如Group节点,最大垂直列的宽度基于具有最大优选宽度的节点。 默认情况下,…

逢3必过报数游戏-第13届蓝桥杯省赛Python真题精选

[导读]:超平老师的Scratch蓝桥杯真题解读系列在推出之后,受到了广大老师和家长的好评,非常感谢各位的认可和厚爱。作为回馈,超平老师计划推出《Python蓝桥杯真题解析100讲》,这是解读系列的第84讲。 逢3必过报数游戏&…

guli商城业务逻辑-基础篇笔记

这里写目录标题 0.1 viscode设置用户代码片段1.实现多级菜单接口1.1 对接前端菜单1.2 对接网关接口解决跨域问题,如果不解决跨域,浏览器还是访问不了api1.3 把商品服务添加网关1.4 修改前端显示分类菜单1.5 给菜单添加删除修改功能1.5.1 删除功能的后端业…

安卓在Fragment控制状态栏显示隐藏

废话不多上效果 隐藏 显示 核心代码 首先是Framgrent package com.zx.tab;import android.content.Context; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Button;impor…

分布式系统中的经典思想实验——两将军问题和拜占庭将军问题

文章目录 一、两将军问题1.1 问题描述1.2 深入理解两将军问题1.3 实验结论 二、拜占庭将军问题2.1 问题描述2.2 深入理解拜占庭将军问题2.3 解决方案 三、两将军和拜占庭问题的关系3.1 区别和联系3.2 应用与现实意义 参考资料 一、两将军问题 1.1 问题描述 两将军问题描述的是…

使用了代理IP怎么还会被封?代理IP到底有没有效果

代理IP作为一种网络工具,被广泛应用于各种场景,例如网络爬虫、海外购物、规避地区限制等。然而,很多用户在使用代理IP的过程中却发现自己的账号被封禁,这让他们不禁产生疑问:使用了代理IP怎么还会被封?代理…

基于粒子群优化算法的的微电网多目标优化调度----算法改进

前言: 当阅读过前一篇我的博客之后,并且认真去读懂了那篇文章末尾的代码,那么,后续的算法改进对于你来说应当是很容易的了。前文中提及过,粒子群在进行迭代时,每迭代一次,都会根据自己个体最优值…

4 最简单的 C 程序设计—顺序程序设计-4.6 顺序结构程序设计举例

【例 4.14】输入三角形的三边长&#xff0c;求三角形面积。 #include <stdio.h> #include <math.h> // 包含数学函数头文件main() {/* 【例 4.14】输入三角形的三边长&#xff0c;求三角形面积。已知三角形的三边长 a,b,c&#xff0c;则该三角形的面积公式为&…

【Java04】引用变量数组初始化的内存机制

引用类型数组指向的元素也是引用。其本质是&#xff1a; 由一个在栈上的引用数组变量指向一块堆内存&#xff1b;这块堆内存里存储的元素是引用&#xff0c;又分别指向其他堆内存。 class Person // Person是一个自定义的类 {public int age;puiblic double height;public vo…

mybatis-plus使用拦截器实现sql完整打印

shigen坚持更新文章的博客写手&#xff0c;擅长Java、python、vue、shell等编程语言和各种应用程序、脚本的开发。记录成长&#xff0c;分享认知&#xff0c;留住感动。 个人IP&#xff1a;shigen 在使用mybatis-plus&#xff08;mybatis&#xff09;的时候&#xff0c;往往需要…

DDPM公式推导(四)

3 Diffusion models and denoising autoencoders 扩散模型可能看起来是一类受限制的潜在变量模型&#xff0c;但它们在实现中允许很大的自由度。必须选择正向过程的方差 β t \beta_t βt​以及逆向过程的模型架构和高斯分布参数化。为了指导我们的选择&#xff0c;我们在扩散…