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

面向对象程序设计中的术语对象(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 #然后会执行自己的初始化方法
#r现在接受的是resource父类的构造方法的返回值,所以会有object出现
#类型为自己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__ #实例化heat类,首先执行自己的构造方法和初始化方法,所以先输出构造方法的print语句
heat init #执行了自己的初始化方法
#r实例化后继承的是object基类,打印返回值
class resource __new__ #实例化resource类,首先执行自己的构造方法和初始化方法,所以先输出构造方法的print语句
#打印父类构造方法的返回值的类名
call me init for resource #执行自己的初始化方法
# h实例化后继承的是object基类,打印返回值
class resource __new__ #实例化subresource类,首先执行父类的构造方法,所以先输出父类构造方法的print语句
#父类构造方法里面打印自己的类名
sub resource init #执行自己的初始化方法
#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才能被当做模块导入

#!/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文件,并把目录下模块文件的名字写进去,在调用时多加一层目录就可以了。

#!/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

以上就是python学习之面向对象编程特性(二) 的详细内容,更多请关注 第一php社区 其它相关文章!

Posted in 未分类