您好,欢迎访问一九零五行业门户网

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 #然后会执行自己的初始化方法 <__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
以上就是python学习之面向对象编程特性(二) 的详细内容。
其它类似信息

推荐信息