您的位置:首页 > 编程语言 > Python开发

python学习笔记之面向对象编程特性(二)

2016-06-28 18:38 696 查看
面向对象程序设计中的术语对象(Object)基本上可以看做数据(特性)以及由一系列可以存取、操作这些数据的方法所组成的集合。传统意义上的“程序=数据结构+算法”被封装”掩盖“并简化为“程序=对象+消息”。对象是类的实例,类的抽象则需要经过封装。封装可以让调用者不用关心对象是如何构建的而直接进行使用。

首先说明一下python编程规范:
#!/usr/bin/env python
#coding=utf-8
#编程规范,示例如下:

class ClassName(object):
'''testdoc         #这里面是一些说明文档,该类的说明信息是可以被help看到的
example:
'''
#注释的写法,可以在后面,也可以在上一行,单行注释以#号开头
a= 100          #this is a number for a
#thisis a number for b
b= 200
c= ['a','b']   #or 分行写
d= {                                   #列表、字典等可以分行写,这样更加直观
'key1':'v1',
'key2':'v2',
'key3':'v3'
}

def__init__(self,num,m):                   #初始化方法。如果不写,则是从基类继承
self.age= num
self.__money= m

deftest(self):
return100

def__eq__(self,other):                 #魔术方法
returnself.age == other.age

def__del__(self):   #析构函数,在整个类调用执行完后会执行
print'world'

d = Hello(2,200)
d2 = Hello(3,100)

print d == d2         #会自动调用__eq__方法,返回比较结果

print d
print d2


书写规范一般从 说明文、初始化方法、单行或多行注释等

一、构造方法:

下面示例说明了构造方法和初始化方法的执行顺序:
#!/usr/bin/env python

class Of(object):

def __new__(cls,*args,**kwargs):               #构造方法
print 'new'
return super(Of,cls).__new__(cls,*args,**kwargs)
#returnobject.__new__(cls,*args,**kwargs)

def __init__(self):                #初始化方法
print "init"

def test(self):
print 'hello'

f = Of()
执行结果如下:
new
init
说明了类在实例化时会先执行构造方法,再去执行初始化方法

下面的示例说明了构造方法和初始化方法的区别:
#!/usr/bin/env python

class Resource(object):                 #父类的定义
def __init__(self):                #初始化方法,为了说明这里直接输出名字
print 'call me resource init'

def __new__(cls,*args,**kwargs):               #构造方法,这里使用这种传参可以接受任何类型的参数
print "resource new"
returnobject.__new__(cls,*args,**kwargs)         #返回值为object基类的构造方法的返回值

class DockerResource(Resource):         #子类的定义,继承了Resource类
def __new__(cls,*args,**kwargs):               #重新构造自己的构造方法
print "call me dockerresource new"
returnResource.__new__(cls,*args,**kwargs)            #返回值为Resource父类的构造方法的返回值

def __init__(self):                #定义自己的初始化方法
print 'call docker resourceinit'

def test(self):                #定义test方法
print 'dosker resource test'

r = DockerResource()                  #实例化DockerResource,并将返回值传递给r
print r                          #打印r,查看返回值是什么
print type(r)                  #查看r的类型
r.test()
输出结果如下:
call me docker resource new                #首先调用了DockerResource的构造方法
resource new                                      #构造方法返回的是Resource的构造方法,所以会执行Resource父类构造方法的print "resource new"
call docker resource init                      #然后会执行自己的初始化方法
<__main__.DockerResource object at0x7fa1a3edcf90>             #r现在接受的是Resource父类的构造方法的返回值,所以会有object出现
<class '__main__.DockerResource'>                    #类型为自己DockerResource
dosker resource test                                   #调用自己的test方法
在类中,首先会执行自己的构造方法,如果没有就会从父类继承,然后会执行自己的初始化方法,没有还是会从父类中继承,接下来就可以正常调用自己的实例方法了

二、继承:
下面的示例说明了子类继承父类
#!/usr/bin/env python

class Resource(object):                 #定义一个父类,继承于object基类

def __new__(cls,*args,**kwargs):        #构造方法
print 'class resource __new__'
obj =super(Resource,cls).__new__(cls,*args,**kwargs)            #利用super函数找到自己的父类,并将它的构造方法传递给obj
print obj.__class__        #打印obj的类型
return obj                     #返回值为obj

def __init__(self):                       #初始化方法
print "call me init forResource"

def test(self):
print "call me test forResource"

def create(self):
print "call me create forResource"

class subResource(Resource):               #定义子类,继承Resource父类

def __init__(self):                #定义自己的初始化方法
print 'sub resource init'

def test(self):
print 'sub resource test'

class Heat(object):                #定义一个Heat类,继承于基类object,是个新式类

def __new__(cls,*args,**kwargs):               #定义自己的构造方法
print "class __new__%s" % cls
returnobject.__new__(cls,*args,**kwargs)                #返回值为object基类的构造方法的返回值

def __init__(self):                #定义初始化方法
print 'heat init'

r = Heat()                     #实例化
print r
h = Resource()              #实例化
print h
f = subResource()          #实例化
print f
执行结果如下:
class __new__ <class '__main__.Heat'>               #实例化Heat类,首先执行自己的构造方法和初始化方法,所以先输出构造方法的print语句
heat init                        #执行了自己的初始化方法
<__main__.Heat object at0x7f43349ac050>                     #r实例化后继承的是object基类,打印返回值
class resource __new__                #实例化Resource类,首先执行自己的构造方法和初始化方法,所以先输出构造方法的print语句
<class '__main__.Resource'>         #打印父类构造方法的返回值的类名
call me init for Resource                     #执行自己的初始化方法
<__main__.Resource object at0x7f43349ac090>               # h实例化后继承的是object基类,打印返回值

class resource __new__                #实例化subResource类,首先执行父类的构造方法,所以先输出父类构造方法的print语句
<class '__main__.subResource'>           #父类构造方法里面打印自己的类名
sub resource init                   #执行自己的初始化方法
<__main__.subResource object at0x7f43349ac0d0>                 #f实例化后是执行了父类Resource类的构造方法,返回的依旧是object基类


三、多重继承:
#!/usr/bin/env python

class A(object):
def __init__(self):
pass
def ma(self):
print 'a.ma'
def m(self):
print 'it is A'
class B(object):
def mb(self):
print 'b.mb'
def m(self):
print 'it is B'

class C(A,B):
pass

c = C()
c.ma()
c.mb()
c.m()
执行结果如下:
a.ma
b.mb
it is A
通过执行结果,我们可以看出,C是继承了A和B的,所以它可以调用A的ma()方法,也可以调用B的mb()方法;但是当A和B里面有相同的方法时,它会优先去执行继承的第一个超类。

四、继承和重载:
#!/usr/bin/env python

class Phone(object):

def __init__(self,size,color,memory):
self.size = size
self.color = color
self.memory = memory

def call(self):
s = 'I can call'
return s
def sms(self):
s = 'Are you gua le mei?'
#!/usr/bin/env python

class Phone(object):

def __init__(self,size,color,memory):
self.size = size
self.color = color
self.memory = memory

def call(self):
s = 'I can call'
return s
def sms(self):
s = 'Are you gua le mei?'
return s

class Phones(Phone):            #继承了Phone类,重载了自己的初始化方法,又增加了自己的方法,既拥有超类的方法,又有自己特有的方法

def __init__(self,size,color,memory,pix):
self.pix = pix
super(Phones,self).__init__(size,color,memory)

def install_app(self,app):
s = 'install %s' % app
return s

class Huwei(Phone):                    #继承了Phone类,又增加了自己的方法,既拥有超类的方法,又有自己特有的方法

def weixin(self,msg):
if msg.find('gcd') == -1:
return 'sending....'
else:
return 'You can\'t sendthe msg'

p = Phone(1.2,'black','4M')                  #实例化

iphone =Phones(4.7,'white','4G','1280*766')        #实例化

h = Huwei(4.7,'yellow','4G')                #实例化

print iphone.install_app('weixin')          #执行特有的install_app方法

print h.sms()
print h.call()
print h.weixin('wansui')
sms = p.sms()
call = p.call()
print sms,call
执行结果如下:
install weixin
Are you gua le mei?
I can call
sending....
Are you gua le mei? I can call
方法的重载实际上就是在类中使用def关键字重载父类的方法。如果重载父类中的方法,但又需要
在类中使用父类的该方法,可以使用父类名加‘ .’加方法名的形式调用

五、魔术方法:
#!/usr/bin/env python

class Information(object):
'''This is a doc                #说明文档
example for test,please don'tchange it.
'''

def __init__(self,sch,cla,m,n):             #定义初始化方法
print "welecome to schoolsystem."
self.school = sch                   #实例变量
self.classroom = cla                     #实例变量
self.num = 100                     #实例变量
self.__money = m                #私有变量
self.num = n                        #实例变量

def school_name(self):                 #返回实例变量,即将实例变量传递出去
return self.school

def class_name(self):                   #返回实例变量,即将实例变量传递出去
return self.classroom

def class_money(self):                 #返回私有变量,即将私有变量传递出去
return self.__money
#魔术方法:以双下划线开头,以双下划线结尾的方法是魔术方法
def __eq__(self,another):             #当外部出现'=='比较的时候,调用此魔术方法
return self.__money ==another.__money           #返回两个私有变量的比较结果(布尔值),这里self是'=='左边的参数值,another是右边的参数值

def __gt__(self,another):                     #当外部出现'>'比较的时候,调用此魔术方法
return self.__money >another.__money             #返回两个私有变量的比较结果(布尔值),这里self是'>'左边的参数值,another是右边的参数值

def __ne__(self,another):             #当外部出现'!='比较的时候,调用此魔术方法
return self.__money !=another.__money            #返回两个私有变量的比较结果(布尔值),这里self是'!='左边的参数值,another是右边的参数值

def __add__(self,another):            #当外部出现'+'运算符的时候,调用此魔术方法
return self.__money +another.__money      #返回两个私有变量的相加结果,这里self是'!='左边的参数值,another是右边的参数值
#returnInformation('jiaoda','dz1302',self.__money + another.__money)
#return Information('jiaoda','dz1302',1024,self.num+ another.num)

def __str__(self):
return 'money = %d' %self.__money

def __hash__(self):               #获取hash值
return 1314521

def __getattr__(self,name):                  #当调用不存在的方法时,执行此方法进行输出
print "get attr %s" %name
return name

def __del__(self):          #析构方法,当不再使用此类时,会自动执行
print "Goodbye,welecomhere again."

f = Information('youdian','tg1312',9999,6)           #实例化
l = Information('ligong','jk1213',6666,4)             #实例化
print f == l            #调用魔术方法__eq__()
print f + l                     #调用魔术方法__add__()
print f > l                     #调用魔术方法__gt__()

s = f + l                 #
print s
print f.ccc              #名字不存在,调用__getatter__()方法


__str__是被print函数调用的,一般都是return一个什么东西。这个东西应该是以字符串的形式表现的。如果不是要用str()函数转换。当你打印一个类的时候,那么print首先调用的就是类里面的定义的__str__

执行结果如下:
welecome to school system.          #首先会在实例化的时候执行初始化方法
welecome to school system.          #第二次实例化调用初始化方法
False                     #打印__eq__()的返回值为False
16665                   #打印__add__()的返回值为两数相加
True                      #打印__gt__()的返回值为True
16665
get attr ccc             #执行__getattr__()方法
ccc
Goodbye,welecom here again.             #执行完会自动执行析构函数
Goodbye,welecom here again.


六、模块:
在python中,自带200多个模块,现在经过大家的不断完善以及改进,官网已经收集了两千多库模块,几乎可以实现任何你想要的功能。

在我们自己使用时,也可以使用自己的模块,任何一个.py都可以作为一个单独的模块进行导入;

现在我们首先定义一个自己的模块:module.py
#!/usr/bin/env python
#coding=utf-8

def test():
print'This is a test'

def test2():
print'test2'

class DB(object):
def__init__(self):
self.a= 101
deftest(self):
returnself.a
在同一目录下,打开python交互式就可以导入这个模块,名字就是文件的名module;
在文件中写入进行导入调用,,,,,这里是在同一目录下(同一层)
#!/usr/bin/env python

import module
module.test()
结果如下:
This is a test
改进一下,进行调用模块中的类:
#!/usr/bin/env python

import module
h = module.DB()
print h.test()
输出结果如下:
101
下面我们试着去导入一个目录下的模块:
新建一个目录heat,在里面写入几个模块文件
目录下必须有__init__.py才能被当做模块导入




在heat目录下的docker.py内容为:
#!/usr/bin/env python

def docker():
return'This is a docker in heat'

class Docker(object):
defcreate_c(self):
return'1314521aaa'

defstop_c(self):
return'it is stop'

print __name__

if __name__ == '__main__':
print__name__
d= Docker()


在heat目录下的nova.py内容为:
#!/usr/bin/env python

def nova():
return'This is a nova'

class Nova(object):
deftest(self):
return'This is a test in nova'


现在heat目录下只是有__init__这个文件,文件里面无内容

写一个调用的脚本文件:
#!/usr/bin/env python
#coding=utf-8

import heat.docker               #目录下__init__.py里面没有__all__
printheat.docker.docker()
执行结果如下:
heat.docker
This is a docker in heat
This is a docker in heat
现在只能导入目录下的具体的模块,像上面一样导入和调用;

为了将目录下的所有模块文件都可以被导入,可以在目录下的__init__.py里面加下以下内容:
__all__ = ['docker','nova']                    #将所有模块名字写入
改变执行文件内容:
#!/usr/bin/env python
#coding=utf-8

import heat.docker               #目录下__init__.py里面没有__all__
print heat.docker.docker()

from heat import *               #heat目录下__init__里面内容是:__all__ = ['docker',nova']
print docker.docker()
print nova.nova()
n = nova.Nova()
print n.test()
执行结果如下:
heat.docker
This is a docker in heat
This is a docker in heat
This is a nova
This is a test in nova
如果在目录下还有目录里面存在需要导入的模块,可以继续在里面写__init__.py文件,并把目录下模块文件的名字写进去,在调用时多加一层目录就可以了。



下面示例一下里面mod.py文件内容:
#!/usr/bin/env python
#coding=utf-8

def hello():
return'hello everyone'

class Hello(object):
def__init__(self):
self.a= 103
deftest(self):
return'This is a test in Hello'
执行下面的脚本进行测试:
#!/usr/bin/env python
#coding=utf-8

from heat.common import mod

print mod.hello()
h = mod.Hello()
print h.test()
执行结果如下:
hello everyone
This is a test in Hello


如果需要里面的所有模块文件,还是继续在__init__.py文件里写入就好了。

需要注意的是,文件被当做模块导入时,会产生.pyc文件,如果更改了模块,应该刷新.pyc文件,否则读取的还是旧信息。

为了防止文件是被作为模块使用的,我们应该在文件中加入
if __name__ == '__main__':
pass               #这里是要执行的语句

这样就可以防止当文件是被用作模块使用时,不会被执行if下面的语句,如果是当做程序来执行时,则会执行下面的语句,一般用作测试。

本文出自 “ptallrights” 博客,请务必保留此出处http://ptallrights.blog.51cto.com/11151122/1793746
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: