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是继承了AB的,所以它可以调用Ama()方法,也可以调用Bmb()方法;但是当AB里面有相同的方法时,它会优先去执行继承的第一个超类。


四、继承和重载:

#!/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.cla***oom = cla                     #实例变量
                self.num = 100                     #实例变量
                self.__money = m                #私有变量
                self.num = n                        #实例变量
 
       def school_name(self):                 #返回实例变量,即将实例变量传递出去
                return self.school
 
       def class_name(self):                   #返回实例变量,即将实例变量传递出去
                return self.cla***oom
 
       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才能被当做模块导入

wKioL1dyUHDRhVDnAAAkZOnsfJk723.png


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

wKiom1dyUYDS0d2sAAAh0jliVNM456.png

下面示例一下里面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下面的语句,如果是当做程序来执行时,则会执行下面的语句,一般用作测试。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章