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

简介: 关于“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类,它该有多长呀!通过 将这个类移到一个模块中,并导入该模块,你依然可以使用其所有功能,但主程序文件变得整洁 而易于阅读了。这还能让你将大部分逻辑存储在独立的文件中;确定类像你希望的那样工作后, 你就可以不管这些文件,而专注于主程序的高级逻辑了。

目录
相关文章
|
16天前
|
Python
python知识点
【8月更文挑战第27天】python知识点
29 1
WK
|
24天前
|
存储 机器学习/深度学习 JSON
Python入门知识点
Python入门覆盖历史、设计理念、变量、数据类型、控制结构等。了解Python的发展,掌握动态类型的灵活性,熟悉整数、浮点数、字符串等数据类型。学会if/else、for/while循环构建逻辑流程,使用def定义函数,lambda快速创建匿名函数。通过类实现面向对象编程,利用模块和包组织代码。掌握try-except处理异常,open()进行文件操作。利用标准库和第三方库增强功能,理解集合、字典、列表推导式的应用,深入魔法方法、递归、装饰器等高级特性,以及上下文管理器和字符串、列表、元组的操作技巧。
WK
24 0
|
3月前
|
存储 Python 容器
Python新手入门,这些基础知识点你掌握了吗?
【6月更文挑战第12天】Python是新手友好的编程语言,具备解释型、面向对象、动态类型和跨平台特性。基础知识包括:变量(如整数、浮点数、字符串、列表、元组、字典和集合),运算符与控制流(如条件语句和循环),以及函数的定义与调用。要精通Python,还需学习更多如面向对象编程、模块、文件操作等内容。开始你的Python学习之旅吧!
28 0
|
30天前
|
存储 Python
Python时间模块四大必备知识点
Python时间模块四大必备知识点
40 4
Python时间模块四大必备知识点
|
19天前
|
Unix 开发者 iOS开发
开发知识点-Python-virtualenv
`virtualenv`通过其简易性、灵活性与高度的可配置性,成为Python开发中推荐的环境隔离工具之一。随着Python生态的发展,类似的工具如 `venv`(Python 3.3+自带的轻量级环境构建工具)和 `pipenv`(提供更复杂的依赖管理功能)也越来越受欢迎,但 `virtualenv`仍保持着重要的地位,尤其是在需要维护旧项目或者系统没有提供最新工具的情况下。
30 1
|
2月前
|
缓存 网络协议 Linux
Linux、Python、计算机网络中的常见知识点
Linux、Python、计算机网络中的常见知识点
|
2月前
|
算法 Java Linux
python中的面试常考知识点
python中的面试常考知识点
|
3月前
|
数据采集 机器学习/深度学习 数据挖掘
python运用知识点说明
Python涵盖广泛,从基础语法(变量、数据类型、字符串操作)到高级特性(装饰器、迭代器、闭包)。常用库包括NumPy, Pandas(数据处理),Scikit-learn, TensorFlow(机器学习),Django, Flask(Web开发),Scrapy(网络爬虫)。应用于Web开发、数据分析、系统运维、游戏开发和网络爬虫。Python历经1.x、2.x到3.x版本,3.x引入重大更新,强调Unicode和函数打印等,与2.x不兼容。掌握这些能提升开发效率。【6月更文挑战第4天】
42 2
|
4月前
|
Python
最新用Python做一个变态版的《超级玛丽》游戏,面试必备知识点
最新用Python做一个变态版的《超级玛丽》游戏,面试必备知识点
最新用Python做一个变态版的《超级玛丽》游戏,面试必备知识点
|
4月前
|
数据可视化 Python
Python模型评估与选择:面试必备知识点
【4月更文挑战第17天】本文深入探讨了Python模型评估与选择在面试中的关键点,包括性能度量、过拟合与欠拟合识别、模型比较与选择、模型融合和偏差-方差权衡。强调了避免混淆评估指标、忽视模型验证和盲目追求高复杂度模型的常见错误,并提供相关代码示例,如交叉验证、网格搜索和超参数调优。通过理解这些概念和技巧,可在面试中展示出色的数据科学能力。
90 12