您的当前位置:首页正文

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

2020-11-27 来源:好兔宠物网

面向对象程序设计中的术语对象(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

-->