03python面向对象编程2
3.继承
如果你要编写的类是另一个现成类的特殊版本,可使用继承。一个类继承另一个类时,它将自动获得另一个类的所有属性和方法;原有的类称为父类,而新类称为子类。子类继承了其父类的所有属性和方法,同时还可以定义自己的属性和方法。
3.1子类的方法 init()
创建子类的实例时,Python首先需要完成的任务是给父类的所有属性赋值。为此,子类的方法 init()
需要父类施以援手。
例如,下面来模拟电动汽车。电动汽车是一种特殊的汽车,因此我们可以在前面创建的 Car类的基础上创建新类 ElectricCar ,这样我们就只需为电动汽车特有的属性和行为编写代码。下面来创建一个简单的 ElectricCar 类版本,它具备 Car 类的所有功能:
"""A class that can be used to represent a car.""" class Car():
"""A simple attempt to represent a car.""" def __init__(self, manufacturer, model, year):
"""Initialize attributes to describe a car."""
self.manufacturer = manufacturer
self.model = model
self.year = year
self.odometer_reading = 0 def get_descriptive_name(self):
"""Return a neatly formatted descriptive name."""
long_name = str(self.year) + ' ' + self.manufacturer + ' ' + self.model
return long_name.title() def read_odometer(self):
"""Print a statement showing the car's mileage."""
print("This car has " + str(self.odometer_reading) + " miles on it.") def update_odometer(self, mileage):
"""
Set the odometer reading to the given value.
Reject the change if it attempts to roll the odometer back.
"""
if mileage >= self.odometer_reading:
self.odometer_reading = mileage
else:
print("You can't roll back an odometer!") def increment_odometer(self, miles):
"""Add the given amount to the odometer reading."""
self.odometer_reading += miles
class ElectricCar(Car):
"""Models aspects of a car, specific to electric vehicles.""" def __init__(self, manufacturer, model, year):
"""
Initialize attributes of the parent class.
Then initialize attributes specific to an electric car.
"""
super().__init__(manufacturer, model, year)
首先是 Car 类的代码。创建子类时,父类必须包含在当前文件中,且位于子类前面。我们定义了子类 ElectricCar 。定义子类时,必须在括号内指定父类的名称。方法 init()接受创建 Car 实例所需的信息。
super() 是一个特殊函数,帮助Python将父类和子类关联起来。这行代码让Python调用 ElectricCar 的父类的方法 init() ,让 ElectricCar 实例包含父类的所有属性。父类也称为超 类(superclass),名称super因此而得名。
为测试继承是否能够正确地发挥作用,我们尝试创建一辆电动汽车,但提供的信息与创建普通汽车时相同。在处,我们创建 ElectricCar 类的一个实例,并将其存储在变量 my_tesla 中。这行代码调用 ElectricCar 类中定义的方法 init() ,后者让Python调用父类 Car 中定义的方法 init() 。我们提供了实参 'tesla' 、 'model s' 和 2016 。 除方法 init() 外,电动汽车没有其他特有的属性和方法。当前,我们只想确认电动汽车具备普通汽车的行为:
my_tesla = ElectricCar('tesla', 'model s', 2016)
print(my_tesla.get_descriptive_name())
2016 Tesla Model S
3.2 Python2.7中的继承。
在Python 2.7中,继承语法稍有不同, ElectricCar 类的定义类似于下面这样:
函数 super() 需要两个实参:子类名和对象 self 。为帮助Python将父类和子类关联起来,这些实参必不可少。另外,在Python 2.7中使用继承时,务必在定义父类时在括号内指定 object 。
# 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 --
3.3 给子类定义属性和方法
让一个类继承另一个类后,可添加区分子类和父类所需的新属性和方法。 下面来添加一个电动汽车特有的属性(电瓶),以及一个描述该属性的方法。我们将存储电 瓶容量,并编写一个打印电瓶描述的方法:
class ElectricCar(Car):
"""Models aspects of a car, specific to electric vehicles.""" def __init__(self, manufacturer, model, year):
"""
Initialize attributes of the parent class.
Then initialize attributes specific to an electric car.
"""
super().__init__(manufacturer, model, year)
self.battery_size = 70 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()
2016 Tesla Model S
This car has a 70-kWh battery.
3.4 重写父类的方法
对于父类的方法,只要它不符合子类模拟的实物的行为,都可对其进行重写。为此,可在子
类中定义一个这样的方法,即它与要重写的父类方法同名。这样,Python将不会考虑这个父类方
法,而只关注你在子类中定义的相应方法。
假设 Car 类有一个名为 fill_gas_tank() 的方法,它对全电动汽车来说毫无意义,因此你可能
想重写它。下面演示了一种重写方式:
# class ElectricCar(Car):
# -- snip --
# def fill_gas_tank(self):
# """电动汽车没有油箱"""
# print("This car doesn't need a gas tank!")
现在,如果有人对电动汽车调用方法 fill_gas_tank() ,Python将忽略 Car 类中的方法 fill_gas_tank() ,转而运行上述代码。使用继承时,可让子类保留从父类那里继承而来的精华, 并剔除不需要的糟粕。
3.5 将实例用作属性
使用代码模拟实物时,你可能会发现自己给类添加的细节越来越多:属性和方法清单以及文
件都越来越长。在这种情况下,可能需要将类的一部分作为一个独立的类提取出来。你可以将大
型类拆分成多个协同工作的小类。
例如,不断给 ElectricCar 类添加细节时,我们可能会发现其中包含很多专门针对汽车电瓶
的属性和方法。在这种情况下,我们可将这些属性和方法提取出来,放到另一个名为 Battery 的
类中,并将一个 Battery 实例用作 ElectricCar 类的一个属性:
# class Car():
# -- snip --
class Battery():
"""A simple attempt to model a battery for an electric car.""" def __init__(self, battery_size=60):
"""Initialize the batteery's attributes."""
self.battery_size = battery_size def describe_battery(self):
"""Print a statement describing the battery size."""
print("This car has a " + str(self.battery_size) + "-kWh battery.")
class ElectricCar(Car):
"""Models aspects of a car, specific to electric vehicles.""" def __init__(self, manufacturer, model, year):
"""
Initialize attributes of the parent class.
Then initialize attributes specific to an electric car.
"""
super().__init__(manufacturer, model, year)
self.battery = Battery()
我们定义了一个名为 Battery 的新类,它没有继承任何类。方法 init() 除 self 外,还有另一个形参 battery_size 。这个形参是可选的:如果没有给它提供值,电瓶容量将 被设置为60。方法 describe_battery() 也移到了这个类中。
在 ElectricCar 类中,我们添加了一个名为 self.battery 的属性。这行代码让Python 创建一个新的 Battery 实例(由于没有指定尺寸,因此为默认值 60 ),并将该实例存储在属性 self.battery 中。每当方法 init() 被调用时,都将执行该操作;因此现在每个 ElectricCar 实 例都包含一个自动创建的 Battery 实例。
my_tesla = ElectricCar('tesla', 'model s', 2016)
print(my_tesla.get_descriptive_name())
my_tesla.battery.describe_battery()
2016 Tesla Model S
This car has a 60-kWh battery.
class Battery():
"""A simple attempt to model a battery for an electric car.""" def __init__(self, battery_size=60):
"""Initialize the batteery's attributes."""
self.battery_size = battery_size def describe_battery(self):
"""Print a statement describing the battery size."""
print("This car has a " + str(self.battery_size) + "-kWh battery.") def get_range(self):
"""Print a statement about the range this battery provides."""
if self.battery_size == 60:
range = 140
elif self.battery_size == 85:
range = 185
else:
range = 200
message = "This car can go approximately " + str(range)
message += " miles on a full charge."
print(message)
my_tesla = ElectricCar('tesla', 'model s', 2016)
print(my_tesla.get_descriptive_name())
my_tesla.battery.describe_battery()
my_tesla.battery.get_range()
2016 Tesla Model S
This car has a 60-kWh battery.
This car can go approximately 140 miles on a full charge.
新增的方法 get_range()。
3.6 模拟实物
模拟较复杂的物件(如电动汽车)时,需要解决一些有趣的问题。续航里程是电瓶的属性还
是汽车的属性呢?如果我们只需描述一辆汽车,那么将方法 get_range() 放在 Battery 类中也许是合
适的;但如果要描述一家汽车制造商的整个产品线,也许应该将方法 get_range() 移到 ElectricCar
类中。在这种情况下, get_range() 依然根据电瓶容量来确定续航里程,但报告的是一款汽车的续
航里程。我们也可以这样做:将方法 get_range() 还留在 Battery 类中,但向它传递一个参数,如
car_model ;在这种情况下,方法 get_range() 将根据电瓶容量和汽车型号报告续航里程。
这让你进入了程序员的另一个境界:解决上述问题时,你从较高的逻辑层面(而不是语法层
面)考虑;你考虑的不是Python,而是如何使用代码来表示实物。到达这种境界后,你经常会发
现,现实世界的建模方法并没有对错之分。有些方法的效率更高,但要找出效率最高的表示法,需要经过一定的实践。只要代码像你希望的那样运行,就说明你做得很好!即便你发现自己不得
不多次尝试使用不同的方法来重写类,也不必气馁;要编写出高效、准确的代码,都得经过这样的过程。
03python面向对象编程2的更多相关文章
- 03python面向对象编程5
5.1 继承机制及其使用 继承是面向对象的三大特征之一,也是实现软件复用的重要手段.Python 的继承是多继承机制,即一个子类可以同时有多个直接父类. Python 子类继承父类的语法是在定义子类时 ...
- 03python面向对象编程4
http://c.biancheng.net/view/2287.html 1.1定义类和对象 在面向对象的程序设计过程中有两个重要概念:类(class)和对象(object,也被称为实例,insta ...
- 03python面向对象编程1
1.创建和使用类 1.1 创建 Dog 类.根据 Dog 类创建的每个实例都将存储名字和年龄.我们赋予了每条小狗蹲下( sit() )和打滚( roll_over() )的能力: In [2]: cl ...
- 03python面向对象编程3
案例学习 # notebook.pyimport datetime # Store the next available id for all new notes last_id = 0 class ...
- angular2系列教程(六)两种pipe:函数式编程与面向对象编程
今天,我们要讲的是angualr2的pipe这个知识点. 例子
- 带你一分钟理解闭包--js面向对象编程
上一篇<简单粗暴地理解js原型链--js面向对象编程>没想到能攒到这么多赞,实属意外.分享是个好事情,尤其是分享自己的学习感悟.所以网上关于原型链.闭包.作用域等文章多如牛毛,很多文章写得 ...
- PHP 面向对象编程和设计模式 (1/5) - 抽象类、对象接口、instanceof 和契约式编程
PHP高级程序设计 学习笔记 2014.06.09 什么是面向对象编程 面向对象编程(Object Oriented Programming,OOP)是一种计算机编程架构.OOP 的一条基本原则是计算 ...
- Delphi_09_Delphi_Object_Pascal_面向对象编程
今天这里讨论一下Delphi中的面向对象编程,这里不做过多过细的讨论,主要做提纲挈领的描述,帮助自己抓做重点. 本随笔分为两部分: 一.面向对象编程 二.面向对象编程详细描述 ------------ ...
- python基础-面向对象编程
一.三大编程范式 编程范式即编程的方法论,标识一种编程风格 三大编程范式: 1.面向过程编程 2.函数式编程 3.面向对象编程 二.编程进化论 1.编程最开始就是无组织无结构,从简单控制流中按步写指令 ...
随机推荐
- [LeetCode]-010-Regular_Expression_Matching
Implement regular expression matching with support for '.' and '*'. '.' Matches any single character ...
- 为Sublime Text 3设置优雅的字体
本文使用的Sublime Text 3版本是3.2.1(build 3207),这个版本默认对中文的支持很糟糕,中国程序员很费眼睛,需要做一番设置. 首选需要在本机安装漂亮的字体,我们选用的是YaHe ...
- Codeforces Aim Tech Round4 (Div2) D
题目链接: 题意: 给你一个严格升序的单链表,但是是用数组来存放的.对于每一个位置来说,你可以知道这个位置的值和下一个的位置.你每一个可以询问一个位置,机器会告诉你这个位置的值,和下一个位置的指针.要 ...
- JWT原理和使用
jwt JSON Web Tokens,是一种开发的行业标准RFC 7519,用于安全的表示双方之间的声明.目前,jwt广泛的用在系统的用户认证方面,特别是前后端分离项目. 1.jwt认证流程 在项目 ...
- Html/CSS 初步介绍html和css部分重要标签
&初步介绍html和css部分重要标签& 注:开头书写:<!DOCTYPE html>表明对应标准html代码 先行总结重点 下方给出具体 CSS: 1. position ...
- 设计模式(5): vue 不监听绑定的变量
概述 最近最近做项目的时候总会思考一些大的应用设计模式相关的问题,我把自己的思考记录下来,供以后开发时参考,相信对其他人也有用. 绑定变量 一般情况下,如果我们需要在组件中使用某个变量,会这么使用: ...
- com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Table 'jeewx.weixin_account_user_relation' doesn't exist
[INFO] Scanning for projects...[INFO] [INFO] ------------------------------------------------------- ...
- excel 导入导出测试点
目前,为方便操作,很多系统都会增加批量导入导出的功能.文件导入导出一般格式都是excel.由于用户直接在excel在填写内容,无法控制填写的格 式,加上excel解析比较困难,所以一般涉及到excel ...
- poker
一副扑克牌有n张牌.一般你买的一副新扑克牌里除了这n张牌外还会有一些张特殊的牌,如果你不小心弄丢了n张牌中的某一张,就可以用特殊牌来代替,但是如果你弄丢两张的话就没有办法了,因为特殊牌上的图案是一样的 ...
- spark 怎么去连接 ElasticSearch
https://stackoverflow.com/questions/52659109/cannot-read-from-elasticsearch-using-pyspark https://st ...