以下为《第6章 面向对象编程教案》的无排版文字预览,完整内容请下载
第6章 面向对象编程
Python从设计之初就已经是一门面向对象的语言,正因为如此,在Python中创建一个类和对象是很容易的。和其他编程语言相比,Python 在尽可能不增加新的语法和语义的情况下加入了类机制。
Python中的类提供了面向对象编程的所有基本功能:类的继承机制允许多个基类;派生类可以覆盖基类中的任何方法;方法中可以调用基类中的同名方法;对象可以包含任意数量和类型的数据。
本章学习重点:
类的方法和属性
单某某
多继承
方法重载
6.1 创建类
6.1.1 类的定义
类(Class)是用来描述具有相同属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法,对象是类的实例。类变量在整个实例化的对象中是公用的,它定义在类中且在函数体之外。类变量通常不作为实例变量使用。类定义的语法格式如下:
class ClassName:
.
.
.
6.1.2 类的实例化
类对象支持两种操作:属性引用和实例化。属性引用是在创建一个类之后,通过类名访问其属性;实例化是创建一个类的实例,即类的具体对象。类实例化后,可以使用其属性。可以使用带有对象的点(.)运算符来访问对象的属性。
【例6-1】创建一个类将其赋值给实例对象。实例代码如下:
#!/usr/bin/python3
class MyClass:
"""一个简单的类实例"""
i = 'python'
def f(self):
return 'hello world'
# 实例化类
x = MyClass()
# 访问类的属性和方法
print("MyClass 类的属性 i 为:", x.i)
print("MyClass 类的方法 f 输出为:", x.f())
以上程序运行结果为:
MyClass 类的属性 i 为: python
MyClass 类的方法 f 输出为: hello world
6.1.3 类的方法
方法是类中定义的函数。类的方法与普通的函数有一个特别的区别是:它们必须有一个额外的第一个参数名称, 按照惯例它的名称是 self。
【例6-2】创建类的方法。实例代码如下:
#!/usr/bin/python3
class Test:
def prt(self):
print(self)
print(self.__class__)
t = Test()
t.prt(
以上程序运行结果为:
从执行结果可以看出,self 代表的是类的实例,代表当前对象的地址,而 self.class 则指向类。但是self 不是Python关键字,把self换成其他字母也是可以正常执行的。
【例6-3】创建类的方法,使用其他字母替代self。实例代码如下:
#!/usr/bin/python3
class Test:
def prt(runman):
print(runman)
print(runman.__class__)
t = Test()
t.prt()
以上程序运行结果为:
6.1.4 构造方法
__init__()方法是一种特殊的方法,被称为类的构造方法或初始化方法,由于很多类都倾向于将对象创建为有初始状态的类,当创建类的实例时就会调用该方法。类的构造方法定义如下:
def __init__(self):
self.data = [ ]
如果类定义了__init__()方法,类的实例化操作会自动调用__init__()方法,并且通过该方法将参数传递到类的实例化操作上。
【例6-4】用__init__()方法传递参数。实例代码如下:
#!/usr/bin/python3
class Complex:
def __init__(self, real, imag):
self.r = real
self.i = imag
x = Complex(3.0, -4.5)
print(x.r, x.i)
以上程序运行结果为:
3.0 -4.5
6.1.5 私有属性和方法
可以在类定义的属性和方法前面加上双下划线,来定义类的私有属性和方法,私有属性和方法在类的外部无法被直接访问。
【例6-5】类中定义私有属性。实例代码如下:
#!/usr/bin/python3
#类定义
class people:
#定义基本属性
name = ''
age = 0
#定义私有属性,私有属性在类外部无法直接进行访问
__weight = 0
#定义构造方法
def __init__(self,n,a,w):
self.name = n
self.age = a
self.__weight = w
def speak(self):
print("%s 说:我 %d 岁。" %(self.name,self.age))
print(self.__weight)
# 实例化类
p = people('runman',10,30)
p.speak()
以上程序运行结果为:
runman 说:我 10 岁。
30
【例6-6】类的私有属性在类的外部被使用时会报错。实例代码如下:
#!/usr/bin/python3
class JustCounter:
__secretCount = 0 # 私有变量
publicCount = 0 # 公开变量
def count(self):
self.__secretCount += 1
self.publicCount += 1
print (self.__secretCount)
counter = JustCounter()
counter.count()
counter.count()
print (counter.publicCount)
print (counter.__secretCount) # 报错,实例不能访问私有变量
以上程序运行结果为:
1
2
2
Traceback (most recent call last):
File "D:/anli", line 18, in
print (counter.__secretCount) # 报错,实例不能访问私有变量
AttributeError: 'JustCounter' object has no attribute '__secretCount'
【例6-7】类的私有方法在类的外部被使用时会报错。实例代码如下:
#!/usr/bin/python3
class Site:
def __init__(self, name, url):
self.name = name
self.__url = url # 私有属性
def who(self):
print('name : ', self.name)
print('url : ', self.__url)
def __foo(self): # 私有方法
print('这是私有方法')
def foo(self):
print('这是公共方法')
self.__foo()
x = Site('python','runman')
x.who() # 正常输出
x.foo() # 正常输出
x.__foo() # 报错
以上程序运行结果为:
name : python
url : runman
这是公共方法
这是私有方法
Traceback (most recent call last):
File "D:/fuzhiyunsuanfu.py", line 22, in
x.__foo() # 报错
AttributeError: 'Site' object has no attribute '__foo'
6.2 继承
6.2.1 继承的定义和特征
1.继承的定义
继承是面向对象最显著的一个特性。继承是使用已存在的类的定义作为基础建立新类的技术,新类的定义可以增加新的数据或新的功能,也可以用父类的功能,但不能选择性地继承父类。这种技术使得复用以前的代码非常容易,能够大大缩短开发周期,降低开发费用。
例如可以先定义一个叫作车的类,车有以下属性:车体大小,颜色,方向盘,轮胎,又由车这个类派生出轿车和卡车两个类,为轿车添加一个小后备箱,而为卡车添加一个大货箱。Python 同样支持类的继承,派生类的定义如下所示:
class DerivedClassName(BaseClassName1):
.
.
.
参数说明:
BaseClassName1:基类的名称。
2.继承的特征
继承关系是传递的。若类C继承类B,类B继承类A,则类C(多继承)既有从类B那里继承下来的属性与方法,也有从类A那里继承下来的属性与方法,还可以有自己新定义的属性和方法。继承来的属性和方法尽管是隐式的,但仍是类C的属性和方法。
因而继承具有以下特征:
继承是在一些比较一般的类的基础上构造、建立和扩充新类的最有效的手段。
继承简化了人们对事物的认识和描述,能清晰体现相关类间的层次结构关系。
继承提供了软件复用功能。若类B继承类A,那么建立类B时只需要再描述与父类(类A)不同的少量特征(数据成员和成员方法)即可。这种做法能减小代码和数据的冗余度,大大增加程序的复用性。
继承通过增强一致性来减少模块间的接口和界面,大大增加了程序的易维护性。
提供多继承机制。从理论上说,一个类可以是多个一般类的特殊类,它可以从多个一般类中继承属性与方法,这便是多继承。
6.2.2 单某某
单某某是指继承类是由一个基类派生而来的。子类继承其父类的属性,可以像子类中一样定义和使用它们。子类也可以从父类继承数据成员和方法。
【例6-8】单某某类实例。实例代码如下:
#!/usr/bin/python3
#类定义
class people:
#定义基本属性
name = ''
age = 0
#定义私有属性,私有属性在类外部无法直接进行访问
__weight = 0
#定义构造方法
def __init__(self,n,a,w):
self.name = n
self.age = a
self.__weight = w
def speak(self):
print("%s 说:我 %d 岁。" %(self.name,self.age))
#单某某示例
class student(people):
grade = ''
def __init__(self,n,a,w,g):
#调用父类的构造函数
people.__init__(self,n,a,w)
self.grade = g
#覆写父类的方法
def speak(self):
print("%s 说:我 %d 岁了,我在读 %d 年级"%(self.name,self.age,self.grade))
s = student('ken',10,60,3)
s.speak()
以上程序运行结果为:
ken 说:我 10 岁了,我在读 3 年级
6.2.3 多继承
Python同样有限地支持多继承形式。多继承中一个子类可以同时继承多个父类。多继承类的定义形如下:
class DerivedClassName(Base1, Base2, Base3):
.
.
.
参数说明:
Base:父类名称,若是父类中有相同的方法名,而在子类使用时未指定,Python从左至右搜索。即方法在子类中未找到时,从左到右查找父类中是否包含此方法。
【例6-9】多继承类实例。实例代码如下:
#!/usr/bin/python3
#类定义
class people:
#定义基本属性
name = ''
age = 0
#定义私有属性,私有属性在类外部无法直接进行访问
__weight = 0
#定义构造方法
def __init__(self,n,a,w):
self.name = n
self.age = a
self.__weight = w
def speak(self):
print("%s 说:我%d岁。" %(self.name,self.age))
#单某某示例
class student(people):
grade = ''
def __init__(self,n,a,w,g):
#调用父类的构函
people.__init__(self,n,a,w)
self.grade = g
#覆写父类的方法
def speak(self):
print("%s 说:我%d岁了,我在读%d年级"%(self.name,self.age,self.grade))
#另一个类,多继承之前的准备
class speaker():
topic = ''
name = ''
def __init__(self,n,t):
self.name = n
self.topic = t
def speak(self):
print("我叫%s,我是一个演说家,我演讲的主题是 %s"%(self.name,self.topic))
#多继承
class sample(speaker,student):
a =''
def __init__(self,n,a,w,g,t):
student.__init__(self,n,a,w,g)
speaker.__init__(self,n,t)
test = sample("Tim",25,80,4,"Python")
test.speak() #方法名同,默认调用的是在括号中排前的父类的方法
以上程序运行结果为:
我叫Tim,我是一个演说家,我演讲的主题是 Python
6.2.4 方法重写
如果父类方法的功能不能满足子类的需求,可以在子类重写父类的方法,这称之为方法重写。
【例6-10】方法重写。实例代码如下:
#!/usr/bin/python3
class Parent: # 定义父类
def myMethod(self):
print ('调用父类方法')
class Child(Parent): # 定义子类
def myMethod(self):
print ('调用子类方法')
c = Child() # 子类实例
c.myMethod() # 子类调用重写方法
以上程序运行结果为:
调用子类方法
6.2.5 运算符重载
Python同样支持运算符重载,可以对类的专有方法进行重载。假设已经创建了一个Vector类来表示二维向量。在进行二维向量的加法时,若还是使用专有的加号“+”运算符执行运算,就无法达到目的。因此可以在类中定义一个__add__方法来执行向量加法,按照期望行为那样执行加法运算。
【例6-11】二维向量的加法重载。实例代码如下:
#!/usr/bin/python3
class Vector:
def __init__(self, a, b):
self.a = a
self.b = b
def __str__(self):
return 'Vector (%d, %d)' % (self.a, self.b)
#重载“+”运算符
def __add__(self,other):
return Vector(self.a+other.a, self.b+other.b)
v1 = Vector(2,10)
v2 = Vector(5,-2)
print (v1 + v2)
以上程序运行结果为:
Vector (7, 8)
【例6-12】三维向量的加法、减法和三维向量与标量的乘法、除法重载。实例代码如下:
#!/usr/bin/python3
class Vecter3:
def __init__(self,x=0,y=0,z=0):
self.X = x
self.Y = y
self.Z = z
#加法重载
def __add__(self, n):
r = Vecter3()
r.X = self.X + n.X
r.Y = self.Y + n.Y
r.Z = self.Z + n.Z
return r
#减法重载
def __sub__(self, n):
r = Vecter3()
r.X = self.X - n.X
r.Y = self.Y - n.Y
r.Z = self.Z - n.Z
return r
#乘法重载
def __mul__(self,n):
r = Vecter3()
r.X = self.X * n
r.Y = self.Y * n
r.Z = self.Z * n
return r
内容过长,仅展示头部和尾部部分文字预览,全文请查看图片预览。 性和方法尽管是隐式的,但仍是__________的属性和方法。
二、填空题
1.Python中构造函数的名称是( )。
A.与类同名 B.self C._init_ D.init
2.Python中定义私有变量的方法是( )。
A.使用this关键字
B.使用private关键字
C.__变量名
D.变量名__
三、判断题
1.定义类时所有实例方法的第一个参数用来表示对象本身,在类的外部通过对象名来调用实例方法时不需要为该参数传值。 ( )
2.在面向对象程序设计中,函数和方法是完全一样的,都必须为所有参数进行传值。
3.Python中没有严格意义上的私有成员。 ( )
4.在Python中定义类时,运算符重载是通过重写特殊方法实现的。例如,在类中实现了__mul__()方法即可支持该类对象的**运算符。 ( )
5.在派生类中可以通过“基类名.方法名()”的方式来调用基类中的方法。 ( )
6.Python支持多继承,如果父类中有相同的方法名,而在子类中调用时没有指定父类名,则Python解释器将从左向右按顺序进行搜索。 ( )
[文章尾部最后500字内容到此结束,中间部分内容请查看底下的图片预览]请点击下方选择您需要的文档下载。
以上为《第6章 面向对象编程教案》的无排版文字预览,完整内容请下载
第6章 面向对象编程教案由用户“sumos”分享发布,转载请注明出处