关于“Python”的核心知识点整理大全21

9.3.2 Python 2.7 中的继承

在Python 2.7中,继承语法稍有不同,ElectricCar类的定义类似于下面这样:

class Car(object):
 def __init__(self, make, model, year):
 --snip--
class ElectricCar(Car):
 def __init__(self, make, model, year):
 super(ElectricCar, self).__init__(make, model, year)
 --snip-- 

函数super()需要两个实参:子类名和对象self。为帮助Python将父类和子类关联起来,这些 实参必不可少。另外,在Python 2.7中使用继承时,务必在定义父类时在括号内指定object。

9.3.3 给子类定义属性和方法

让一个类继承另一个类后,可添加区分子类和父类所需的新属性和方法。

下面来添加一个电动汽车特有的属性(电瓶),以及一个描述该属性的方法。我们将存储电 瓶容量,并编写一个打印电瓶描述的方法:

class Car():
 --snip--
class ElectricCar(Car):
 """Represent aspects of a car, specific to electric vehicles."""
 def __init__(self, make, model, year):
 """
电动汽车的独特之处
初始化父类的属性,再初始化电动汽车特有的属性
 """
 super().__init__(make, model, year)
1 self.battery_size = 70
2 def describe_battery(self):
 """打印一条描述电瓶容量的消息"""
 print("This car has a " + str(self.battery_size) + "-kWh battery.")
my_tesla = ElectricCar('tesla', 'model s', 2016)
print(my_tesla.get_descriptive_name())
my_tesla.describe_battery()

在1处,我们添加了新属性self.battery_size,并设置其初始值(如70)。根据ElectricCar 类 创建的所有实例都将包含这个属性,但所有Car实例都不包含它。在2处,我们还添加了一个名 为describe_battery()的方法,它打印有关电瓶的信息。我们调用这个方法时,将看到一条电动 汽车特有的描述:

2016 Tesla Model S
This car has a 70-kWh battery.

对于ElectricCar类的特殊化程度没有任何限制

def ElectricCar(Car):
 --snip--
 def fill_gas_tank():
 """电动汽车没有油箱"""
 print("This car doesn't need a gas tank!")

。模拟电动汽车时,你可以根据所需的准确 程度添加任意数量的属性和方法。如果一个属性或方法是任何汽车都有的,而不是电动汽车特有 的,就应将其加入到Car类而不是ElectricCar类中。这样,使用Car类的人将获得相应的功能,而 ElectricCar类只包含处理电动汽车特有属性和行为的代码。

9.3.4 重写父类的方法

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

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

def ElectricCar(Car):
 --snip--
 def fill_gas_tank():
 """电动汽车没有油箱"""
 print("This car doesn't need a gas tank!")

现在,如果有人对电动汽车调用方法fill_gas_tank(),Python将忽略Car类中的方法 fill_gas_tank(),转而运行上述代码。使用继承时,可让子类保留从父类那里继承而来的精华, 并剔除不需要的糟粕。

9.3.5 将实例用作属性

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

例如,不断给ElectricCar类添加细节时,我们可能会发现其中包含很多专门针对汽车电瓶 的属性和方法。在这种情况下,我们可将这些属性和方法提取出来,放到另一个名为Battery的 类中,并将一个Battery实例用作ElectricCar类的一个属性:

class Car():
 --snip--
1 class Battery():
 """一次模拟电动汽车电瓶的简单尝试"""
2 def __init__(self, battery_size=70):
 """初始化电瓶的属性"""
 self.battery_size = battery_size
3 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)
4 self.battery = Battery()
my_tesla = ElectricCar('tesla', 'model s', 2016)
print(my_tesla.get_descriptive_name())
my_tesla.battery.describe_battery() 

在1处,我们定义了一个名为Battery的新类,它没有继承任何类。2处的方法__init__()除 self外,还有另一个形参battery_size。这个形参是可选的:如果没有给它提供值,电瓶容量将 被设置为70。方法describe_battery()也移到了这个类中(见3)。

在ElectricCar类中,我们添加了一个名为self.battery的属性(见4)。这行代码让Python 创建一个新的Battery实例(由于没有指定尺寸,因此为默认值70),并将该实例存储在属性 self.battery中。每当方法__init__()被调用时,都将执行该操作;因此现在每个ElectricCar实 例都包含一个自动创建的Battery实例。

我们创建一辆电动汽车,并将其存储在变量my_tesla中。要描述电瓶时,需要使用电动汽车 的属性battery:

my_tesla.battery.describe_battery() 

这行代码让Python在实例my_tesla中查找属性battery,并对存储在该属性中的Battery实例 调用方法describe_battery()。 输出与我们前面看到的相同:

2016 Tesla Model S
This car has a 70-kWh battery. 

这看似做了很多额外的工作,但现在我们想多详细地描述电瓶都可以,且不会导致ElectricCar 类混乱不堪。下面再给Battery类添加一个方法,它根据电瓶容量报告汽车的续航里程:

class Car():
 --snip--
class Battery():
 --snip--
1 def get_range(self):
 """打印一条消息,指出电瓶的续航里程"""
 if self.battery_size == 70:
 range = 240
 elif self.battery_size == 85:
 range = 270
 message = "This car can go approximately " + str(range)
 message += " miles on a full charge."
 print(message)
class ElectricCar(Car):
 --snip--
my_tesla = ElectricCar('tesla', 'model s', 2016)
print(my_tesla.get_descriptive_name())
my_tesla.battery.describe_battery()
2 my_tesla.battery.get_range()

1 处新增的方法get_range()做了一些简单的分析:如果电瓶的容量为70kWh,它就将续航里 程设置为240英里;如果容量为85kWh,就将续航里程设置为270英里,然后报告这个值。为使用 这个方法,我们也通过汽车的属性battery来调用它(见2)。 输出指出了汽车的续航里程(这取决于电瓶的容量):

2016 Tesla Model S
This car has a 70-kWh battery.
This car can go approximately 240 miles on a full charge. 

9.3.6 模拟实物

模拟较复杂的物件(如电动汽车)时,需要解决一些有趣的问题。续航里程是电瓶的属性还 是汽车的属性呢?如果我们只需描述一辆汽车,那么将方法get_range()放在Battery类中也许是合 适的;但如果要描述一家汽车制造商的整个产品线,也许应该将方法get_range()移到ElectricCar 类中。在这种情况下,get_range()依然根据电瓶容量来确定续航里程,但报告的是一款汽车的续 航里程。我们也可以这样做:将方法get_range()还留在Battery类中,但向它传递一个参数,如 car_model;在这种情况下,方法get_range()将根据电瓶容量和汽车型号报告续航里程。

这让你进入了程序员的另一个境界:解决上述问题时,你从较高的逻辑层面(而不是语法层 面)考虑;你考虑的不是Python,而是如何使用代码来表示实物。到达这种境界后,你经常会发 现,现实世界的建模方法并没有对错之分。有些方法的效率更高,但要找出效率最高的表示法,需要经过一定的实践。只要代码像你希望的那样运行,就说明你做得很好!即便你发现自己不得 不多次尝试使用不同的方法来重写类,也不必气馁;要编写出高效、准确的代码,都得经过这样 的过程。

9.4 导入类

随着你不断地给类添加功能,文件可能变得很长,即便你妥善地使用了继承亦如此。为遵循 Python的总体理念,应让文件尽可能整洁。为在这方面提供帮助,Python允许你将类存储在模块 中,然后在主程序中导入所需的模块。

9.4.1 导入单个类

下面来创建一个只包含Car类的模块。这让我们面临一个微妙的命名问题:在本章中,已经 有一个名为car.py的文件,但这个模块也应命名为car.py,因为它包含表示汽车的代码。我们将这 样解决这个命名问题:将Car类存储在一个名为car.py的模块中,该模块将覆盖前面使用的文件car.py。从现在开始,使用该模块的程序都必须使用更具体的文件名,如my_car.py。下面是模块 car.py,其中只包含Car类的代码:

car.py
1 """一个可用于表示汽车的类"""
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.")
 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,在其中导入Car类并创建其实例:

my_car.py
1 from car import Car
my_new_car = Car('audi', 'a4', 2016)
print(my_new_car.get_descriptive_name())
my_new_car.odometer_reading = 23
my_new_car.read_odometer() 

1处的import语句让Python打开模块car,并导入其中的Car类。这样我们就可以使用Car类了, 就像它是在这个文件中定义的一样。输出与我们在前面看到的一样:

2016 Audi A4
This car has 23 miles on it. 

导入类是一种有效的编程方式。如果在这个程序中包含了整个Car类,它该有多长呀!通过 将这个类移到一个模块中,并导入该模块,你依然可以使用其所有功能,但主程序文件变得整洁 而易于阅读了。这还能让你将大部分逻辑存储在独立的文件中;确定类像你希望的那样工作后, 你就可以不管这些文件,而专注于主程序的高级逻辑了。


关于“Python”的核心知识点整理大全12-CSDN博客

往期快速传送门👆(在文章最后):

感谢大家的支持!欢迎订阅收藏!专栏将持续更新!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

VHDL实验:基于有限状态机实现秒表

题目要求: 利用有限状态机实现实现一个具有启动、停止、清零功能的秒表,显示格式:分:秒:十分秒。启动、停止、清零由一个按键控制,按键按下时,功能按启动、停止、清零顺序循环。 思路分析&…

【NTN 卫星通信】Starlink,卫星互联网的技术革命(一)

1. 什么是Starlink Starlink是由Elon Musk创立的私人太空探索公司SpaceX提供的卫星互联网服务。它旨在为世界上传统互联网服务速度慢或不可用的偏远地区提供价格合理的高速互联网。 为什么Starlink很重要?   Starlink之所以重要,是因为它有可能为数百万…

万能微信在线考试系统:适用于任何行业的在线考试系统 附带完整的搭建教程

互联网技术的发展,线上教育、线上考试逐渐成为主流。特别是在疫情期间,许多传统的线下考试都被迫转为线上。然而,对于许多机构、企业来说,搭建一个稳定、安全的在线考试系统并非易事。这需要专业的技术团队、充足的时间和资源投入…

基于Java SSM框架实现二手交易平台网站系统项目【项目源码+论文说明】计算机毕业设计

基于java的SSM框架实现二手交易平台网站系统演示 摘要 21世纪的今天,随着社会的不断发展与进步,人们对于信息科学化的认识,已由低层次向高层次发展,由原来的感性认识向理性认识提高,管理工作的重要性已逐渐被人们所认…

逆向获取某音乐软件的加密(js逆向)

本文仅用于技术交流,不得以危害或者是侵犯他人利益为目的使用文中介绍的代码模块,若有侵权请联系作者更改。 老套路,打开开发者工具,直接开始找到需要的数据位置,然后观察参数,请求头,cookie是…

TypeScript入门实战笔记 -- 04 什么是字面量类型、类型推断、类型拓宽和类型缩小?

🍍开发环境 1:使用vscode 新建一个 04.Literal.ts 文件,运行下列示例。 2:执行 tsc 04.Literal.ts --strict --alwaysStrict false --watch 3:安装nodemon( 全局安装npm install -g nodemon ) 检测.js文件变化重启项…

网络层--TCP/UDP协议

目录 一、TCP/UDP协议介绍 1、UDP(User Datagram Protocol)--用户数据报协议 1.1 UDP报文格式 1.2 UDP协议的特性 2、TCP(Transmission Control Protocol )--传输控制协议 2.1 TCP报文格式 2.2 TCP协议的特性 2.3 TCP三次握手 2.4 四次挥手 三、TCP和UDP的区别 四、t…

HTML字体阴影

目录 1.阴影颜色 color2.水平轴和垂直轴3.模糊半径 blur 效果如下: h-shadow必需,水平阴影的位置,允许负值v-shadow必须,垂直阴影的位置,允许负值blur可选,模糊的距离color可选,阴影的颜色 1…

WebSocket开发

目录 前言 1.介绍 2.原理解析 3.简单的聊天室搭建 4.点到点消息传输 总结 前言 WebSocket 是互联网项目中画龙点睛的应用,可以用于消息推送、站内信、在线聊天等业务。 1.介绍 WebSocket 是一种基于 TCP 的新网络协议,它是一种持久化的协议&…

vim + ctags 跳转, 查看函数定义

yum install ctags Package ctags-5.8-13.el7.x86_64 already installed and latest version 创建 /home/mzh/pptp-master/tags.sh #!/usr/bin/shWORKDIR/home/mzh/pptp-masterfind ${WORKDIR} -name "*.[c|h]" | xargs ctags -f ${WORKDIR}/tags find /usr/inclu…

花裤衩vue-element-admin-master

这个模板是集成度比较高的 在实习的时候老是依赖装不上 今天在公司 把版本切换到16.17.1 一次就成功了 里面的工具还是比较多的, vue3里开源模板里工具比较多的是vben,它同样安装依赖比较难搞

React Native android环境搭建,使用夜神模拟器进行开发(适用于0.73+版本)

前言 本文基于:“react-native” : “^0.73.0” 1.安装 Node Node.js,下载时选择 > 18 版本 2.下载并安装 JDK Java SE Development Kit (JDK),下载时选择 17 版本 安装 验证是否安装成功 打开命令提示符输入 javac -version 回车 3.…

Springboot集成支付宝支付---完整详细步骤

网页操作步骤 1.进入支付宝开发平台—沙箱环境 使用开发者账号登录开放平台控制平台 2.点击沙箱进入沙箱环境 说明:沙箱环境支持的产品,可以在沙箱控制台 沙箱应用 > 产品列表 中查看。 3.进入沙箱,配置接口加签方式 在沙箱进行调试前…

网页设计--第7次课后作业

已在qq课程群发送了课程的相关资料。 1、安装nodejJS。 2、安装vue-cli。 3、新建一个自己的vue工程化项目。 4、修改默认的vue项目,体会main.js,app.vue以及其他vue文件之间的调用关系,明白vue工程化项目的运行原理。 可以参考视频讲解(…

SQL排列组合

SQL排列组合 1、排列组合概述2、SQL排列组合2.1、排列2.2、组合3、SQL排列组合的应用1、排列组合概述 排列组合是针对离散数据常用的数据组织方法,本节将分别介绍排列、组合的SQL实现方法,并结合实例着重介绍通过组合对数据的处理 如何使用SQL实现排列与组合?本节将通过介绍…

LeetCode 2132. 用邮票贴满网格图:二维前缀和 + 二维差分

【LetMeFly】2132.用邮票贴满网格图:二维前缀和 二维差分 力扣题目链接:https://leetcode.cn/problems/stamping-the-grid/ 给你一个 m x n 的二进制矩阵 grid ,每个格子要么为 0 (空)要么为 1 (被占据&…

欧盟eDelivery的AS4解决方案

为实现绿色和数字欧洲的愿景,欧盟启动了“数字欧洲计划(DEP)”,总预算为75.9亿欧元,重点是将数字技术带给企业、公民和公共行政部门。它将建立数字能力和基础设施,并以创建数字市场为目标,主要通…

escapeshellarg参数绕过和注入的问题

escapeshellcmd escapeshellcmd(string $command): string command--要转义的命令。 escapeshellcmd() 对字符串中可能会欺骗 shell 命令执行任意命令的字符进行转义。 此函数保证用户输入的数据在传送到 exec() 或 system() 函数,或者 执行操作符 之前进行转义。 …

apk反编译修改教程系列---简单给app添加启动弹窗 添加对话框 跳转指定网页等【七】

往期教程: apk反编译修改教程系列-----修改apk应用名称 任意修改名称 签名【一】 apk反编译修改教程系列-----任意修改apk版本号 版本名 防止自动更新【二】 apk反编译修改教程系列-----修改apk中的图片 任意更换apk桌面图片【三】 apk反编译修改教程系列---简单…

FolkMQ 国产消息中间件,v1.0.21 发布

简介 采用 “多路复用” “内存运行” “快照持久化” “Broker 集群模式”(可选)基于 Socket.D 网络应用协议 开发。全新设计,自主架构! 角色功能生产端发布消息(Qos0、Qos1)、发布定时消息&#xff…