Python面向对象编程-OOP
20141216 Chenxin整理
OOP的3大特性: 封装,继承,多态
一.封装
OOP目的,OOP为了代码重用 :分解代码 ,最小化代码的冗余以及对现在的代码进行定制来编写程序 ,而不是实地修改代码或从头开始.
一.类定义
在进行python面向对象编程之前,先来了解几个术语:类,类对象,实例对象,属性,函数和方法。
类是对现实世界中一些事物的封装,定义一个类可以采用下面的方式来定义:
class className:
block
注意类名后面有个冒号,在block块里面就可以定义属性和方法了。当一个类定义完之后,就产生了一个类对象。
类对象支持两种操作:引用和实例化。引用操作是通过类对象去调用类中的属性或者方法,而实例化是产生出一个类对象的实例,称作实例对象。比如定义了一个people类:
class people: #people就是个全局的类对象
name = 'jack' #定义了一个属性
def printName(self): #定义了一个方法
print self.name
people类定义完成之后就产生了一个全局的类对象,可以通过类对象来访问类中的属性和方法了。当通过people.name来访问时,people.name中的people称为类对象。
当然还可以进行实例化操作,p=people( ),这样就产生了一个people的实例对象,此时也可以通过实例对象p来访问属性或者方法了(p.name).
在上面代码中注释的很清楚了,name是一个属性,printName()是一个方法,与某个对象进行绑定的函数称作为方法。一般在类里面定义的函数与类对象或者实例对象绑定了,所以称为方法;而在类外定义的函数一般没有同对象进行绑定,就称为函数。
class 语句说明
一般形式
class (superclass,...):
data=value
def mothod(self,...):
self.member=value
1.就像函数一样 .class语句是作用域 ,由内嵌的赋值语句建立变量名 ,就存在这个本地作用域内 .
2.就像模块内的变量名 ,在 class语句内赋值的变量名会变成类对象中的属性 (对象的成员变量 ).
扩展阅读 命名空间
命名空间
点号和无点号的变量 ,会用不同的方式处理 .
无点号运算的变量名(例如 ,X)与作用域相对应.
点号的属性名(如 object.X)使用的是对象的命名空间 .
有些作用域会对对象的命名空间进行初始化(模块和类)
以下实例总结了命名空间的概念
X=11 #模块属性,全局
def f():
print X # 函数(本地)作用域内没有 X,嵌套函数没有 X变量 ,当前全局作用域(模块的命名空间内)有 ,显示全局
def g():
X=22 # 定义本地作用域变量 X
print X # 搜索函数(本地)作用域内变量 X,有打印
class C:
X=33 # 定义的类属性,类的命名空间
def m(self ):
X=44 # 貌似在这里没有什么意义
self.X=55 # 定义类实例的属性 ,实例的命名空间
if name=='main':
print X # 打印模块属性 结果 11
f() # 调用f(),f() 返回模块全局变量的 X 11
g() # 调用g(),g() 返回函数内局部变量 X 22
print X # 打印 模块全局变量的里变量 ,模块的属性 11
obj=C() # 调用类的方法产生实例
print obj.X # 打印实例的属性X X继承类的属性 ,所以为 33
obj.m() # 实例调用类的m方法
print obj.X # 显示这个X 属性 因为上一步m方法设置了实例的属性 X,为 55
命名空间字典
模块的命名空间实际上是以字典的形式实现的 ,并且可以由内置属性 __dict__显示这一点 .类和实例对象也是如此:属性点号运算
其内部就是字典的索引运算 ,而属性继承其实就是搜索链接的字典而已 .
实际上 ,实例和类对象就是 Python中带有链接的字典而已 ,
class Super():
... def hello(self):
... self.data1='diege'
...
class Sub(Super):
... def hola(self):
... self.data2='eggs'
...
制作子类的实例时 ,该实例一开始会是空的命名空间字典 ,但是有链接会指向它的类 ,让继承搜索能顺着寻找 .
实际上,继承树可在特殊的属性中看到 ,你可以进行查看 .实例中有个 __class__属性链接到了它的类 ,而类有个 __base__属性(就是元组,其中包含了通往更高的超类的连接) .
X=Sub()
X.dict
{}
X.class
Y=Super()
Y.dict
{}
Y.class
Sub.bases
(,)
Super.bases
()
当类为self属性赋值时 ,会填入实例对象 .
实例对象的命名空间保存了数据 ,会随实例的不同而不同 ,而 self正是进入其命名空间的钩子 .
Y=Sub()
X.hello()
X.dict
{'data1': 'diege'}
X.hola()
X.dict
{'data1': 'diege', 'data2': 'eggs'}
Sub.dict
{'module': 'main', 'doc': None, 'hola': }
Super.dict
{'module': 'main', 'hello': , 'doc': None}
Sub.dict.keys(),Super.dict.keys()
(['module', 'doc', 'hola'], ['module', 'hello', 'doc'])
Y.dict
{}
Y是这个类的第 2个实例 .即时 X的字典已由方法内的赋值语句做了填充 ,Y还是空的命名空间字典 .每个实例都有独立的命名空间字典 ,一开始是空的 ,可以记录和相同类的其他实例命名空间字典中属性 ,完全不同的属性 .
因为属性实际上是 python的字典键 ,其实有两种方式可以读取并对其进行赋值:通过点号运算 ,或通过键索引运算 .
X.data1,X.dict['data1']
(