Python程序设计6——面向对象

  面向对象有三大特征:多态(对应方法覆写)、封装、继承(对应方法重载),这个在Java中已经说得很详细了,这里面只是介绍Python在这三个特性方面的实现。

1 创建自定义类                                                            

  Python和Java一样使用class关键字来创建对象。语法格式如下:

class 类名:
  def 方法名1(参数列表):
    pass

  从上述语法来看,类必须使用class关键字来定义,接着是类名,然后使用pass占位。

一个例子如下:

class Person:
    def getName(self):
        print 'My name is AIQI'
    def getAge(self):
        print 'My age is 27'
    def getHoppy(self):
        print 'My hobby is love you'
>>> import Person
>>> person = Person.Person()
>>> person.getName()
My name is AIQI
>>> person.getAge()
My age is 27
>>> person.getHoppy()
My hobby is love you

实例应用

myStr = raw_input('Please input one object:')
class MyWorld:
    #define one person method
    def printPerson(self):
        self.myTalk = 'I can speak'
        self.myLimbs = 'I can move'
        print 'I am a person so,I can %s, %s' % (self.myTalk, self.myLimbs)
    #define one pig method
    def printPig(self):
        self.myTalk = 'Hengheng...'
        self.myWeight = 'I am fat'
        print 'I am a pig so,%s, %s' % (self.myTalk, self.myWeight)
if __name__ == '__main__':
    myWorld = MyWorld()
    if myStr == 'Person':
        myWorld.printPerson()
    elif myStr == 'Pig':
        myWorld.printPig()
    else:
        print 'No this object'
View Code

运行结果:

Please input one object:Person
I am a person so,I can I can speak, I can move

2 属性和方法                                                             

  类是忧属性和方法组成的,属性是对数据的封装,方法是对行为的描述。在Java中,属性和方法都有访问权限控制符,在python中没有这样的封装级别控制符,在Python中,构造函数、析构函数、私有属性方法、公有属性方法都是通过名称的约定来辨别的。如果函数、方法或者属性的名称以两个下划线开始,则说明为私有类型。相反,如果没有以两个下划线开始,则表示为公有属性。在Java中还有一个受保护的类型修饰符protected 在python中不存在这种类型。
  在python中也有静态属性和实例属性。实例属性即以self作为前缀的属性,如果在类的方法中定义的变量没有使用self作为前缀声明,那么该变量就是一个普通的局部变量。

2.1 类属性                           

class Fly:
    #define one class attribute
    price = 23
    def __init__(self):
        self.direction = 'To Paris'
        speed = 32
if __name__ == '__main__':
    print Fly.price
    fly = Fly()
    print fly.direction
    Fly.price = fly.price + 10
    print 'fly,fly away'
    print 'the price increase:' + str(fly.price)
    myFly = Fly()
    print myFly.price
输出结果:
23
To Paris
fly,fly away
the price increase:33
33
View Code

  另外方法中的局部变量speed是不能被实例及类来引用的

2.2 私有属性                        

  将公有的实例属性direction修改成私有__direction

class Fly:
    #define one class attribute
    price = 23
    def __init__(self):
        self.__direction = 'To Paris'
        self.speed = 32
if __name__ == '__main__':
    print Fly.price
    fly = Fly()
    print fly.__direction
    Fly.price = fly.price + 10
    print 'fly,fly away'
    print 'the price increase:' + str(fly.price)
    myFly = Fly()
    print myFly.price
输出结果:
23
Traceback (most recent call last):
  File "Fly.py", line 10, in <module>
    print fly.__direction
AttributeError: Fly instance has no attribute '__direction'
View Code

  显然报错了,也就是私有的属性不能被实例化对象访问。Python提供了直接访问私有属性的方式
实例化对象名._类名__私有属性名

class Fly:
    #define one class attribute
    price = 23
    def __init__(self):
        self.__direction = 'To Paris'
        self.speed = 32
if __name__ == '__main__':
    print Fly.price
    fly = Fly()
    print fly._Fly__direction
    Fly.price = fly.price + 10
    print 'fly,fly away'
    print 'the price increase:' + str(fly.price)
输出结果:
23
To Paris
fly,fly away
the price increase:33
View Code

2.3 数据属性                       

  数据属性不需要预先定义,当数据属性初次被使用时,即被创建并赋值。

class DataAttribute:
    pass
if __name__ == '__main__':
    data = DataAttribute()
    data.name = 'I am not defined'
    print data.name
输出结果:I am not defined

2.4 内置属性                      

  前面已经提到的__doc__就是内置属性。

class FatherClass:
    def __init__(self):
        self.built = 'I am the method __init__ \'s attribute'
class SonClass(FatherClass):
    def accept(self):
        self.acceptAttribute = "I am the attribute of SonClass's method accept"
if __name__ == '__main__':
    f = FatherClass()
    s = SonClass()
    print "Inherite attribute from father class:", s.built
    print "the tuple formed by base class:", SonClass.__bases__
    print "the dict formed by neizhi:", s.__dict__
    print s.__module__
    print s.__doc__
    print SonClass.__name__
输出结果:
Inherite attribute from father class: I am the method __init__ 's attribute
the tuple formed by base class: (<class __main__.FatherClass at 0x7f8d92e4ea10>,)
the dict formed by neizhi: {'built': "I am the method __init__ 's attribute"}
__main__
None
SonClass
View Code

说明:上面代码中,使用内置属性__bases__来输出其父类组成的元组。__dict__属性用例输出子类实例属性组成的字典,__module__属性用来输出当前运行的模块名称,__doc__属性用来输出doc文档,而__name__属性用例输出当前对象的类名。

2.5 类的方法                         

  类似属性,方法也有类方法和实例方法,定义规则相同,在Java中用static来定义,而python中没有static关键字,而是使用函数staticmethod()或者@staticmethod指令的方式来定义静态方法。

2.5.1 类方法         

class Methods:
    @staticmethod
    def myMethod():
        print 'This is a static method'
    def __myMethod():
        print 'This is a private method'
    def getMyMethod():
        print 'I willbe converted to static method'
    conversion = staticmethod(getMyMethod)
    conPrivate = staticmethod(__myMethod)
if __name__ == '__main__':
    methods = Methods()
    methods.myMethod()
    Methods.myMethod()
    #访问转换为静态方法后的原有方法
    methods.conversion()
    Methods.conversion()
    methods.conPrivate()
    Methods.conPrivate()
输出结果:
This is a static method
This is a static method
I willbe converted to static method
I willbe converted to static method
This is a private method
This is a private method
View Code

  上面代码中,在类Methods中分别声明了一个静态方法myMethod,一个私有方法__myMethod和一个普通方法getMyMethod,然后用函数staticmethod()将普通方法getMyMethod转换为静态方法conversion,将私有方法__myMethod转换为静态方法conPrivate

2.5.2 内置方法     

  有许多类内置的方法,这些方法可能会被封装起来被别的函数调用。

 

下面介绍几个重要的__init__方法
1.__init__方法
  这个方法在Python中是构造函数,与Java不同的是,Java中的构造函数和类名是一样的,Python中不必如此,实际上构造函数更严谨的说法是初始化函数,所以__init__还是可以的。

class People:
    def __init__(self, name):
        self.name = name
    def sayHi(self):
        print 'Hello, My name is:', self.name
p = People('AiQi')
p.sayHi()
输出结果:Hello, My name is: AiQi

2.__del__方法
  __del__方法的主要作用是释放被占用的资源,在Python中是析构函数。
  所谓析构函数是:析构函数(destructor) 与构造函数相反,当对象脱离其作用域时(例如对象所在的函数已调用完毕),系统自动执行析构函数。析构函数往往用来做“清理善后” 的工作(例如在建立对象时用new开辟了一片内存空间,应在退出前在析构函数中用delete释放)。

class Room:
    count = 0
    def __init__(self, name):
        self.name = name
        print 'Initing, name is %s' % self.name
        Room.count += 1
    def __del__(self):
        print '%s say byebye:' % self.name
        Room.count -= 1
        if Room.count == 0:
            print 'I am the last one'
        else:
            print 'There is %d persons left' % Room.count
    def sayHi(self):
        print 'Hello,My name is %s ' % self.name
    def howMany(self):
        if Room.count == 1:
            print 'I am the last one'
        else:
            print 'There is %d persons left' % Room.count
if __name__ == '__main__':
    room = Room('AiQi')
    room.sayHi()
运行结果:
Initing, name is AiQi
Hello,My name is AiQi 
I am the last one
Initing, name is Ren
Hello,My name is Ren 
There is 2 persons left
AiQi say byebye:
There is 1 persons left
Ren say byebye:
Exception AttributeError: "'NoneType' object has no attribute 'count'" in <bound method Room.__del__ of <__main__.Room instance at 0x7fc513263200>> ignored
AiQi say byebye:
Exception AttributeError: "'NoneType' object has no attribute 'count'" in <bound method Room.__del__ of <__main__.Room instance at 0x7fc5132631b8>> ignored
View Code

3. __new__方法
  __new__方法在创建对象时被调用,返回当前对象的一个实例。看起来和__init__方法没有什么区别。实际上,__init__方法在创建完对象之后才被调用,对当前对象的实例进行初始化,而__new__方法则是在创建对象时被调用的。

class MyNew:
    def __init__(self):
        print ("__init__")
    def __new__(self):
        print ("__new__")
if __name__ == '__main__':
    myNew = MyNew()

4.__setitem__方法
  _setitem__专用方法的含义是进行赋值时,创建字典对象

class MySetitem:
    def __setitem__(self, key, value):
        print 'key=%s, value=%s' % (key, value)
mySetitem = MySetitem()
mySetitem['a'] = 'Alice'
mySetitem['b'] = 'Quinta'
mySetitem['c'] = 'Amy'
执行结果:
key=a, value=Alice
key=b, value=Quinta
key=c, value=Amy

5.__getitem__方法
  __getitem__用于返回字典的值。这两个方法和java的setter和getter方法是类似的。
6.__delitem__方法
  __delitem__方法是在调用"del 实例对象[key]"语句时调用。

class MyDelitem:
    def __delitem__(self, key):
        print 'delete item:%s' % key
myDelitem = MyDelitem()
del myDelitem['dcy']
输出结果:delete item:dcy

7.__cmp__方法
  这个内置方法被封装用于给==比较累实例时候进行调用。

class MyCmp:
    def __cmp__(self, other):
        print '__cmp__ is called'
        return 0
if __name__ == '__main__':
    mycmp1 = MyCmp()
    mycmp2 = MyCmp()
    print mycmp1 == mycmp2
输出:
__cmp__ is called
True

2.6 方法的动态特性               

 

  python语言是一种完全面向对象的动态语言,主要体现在:可以动态添加类的方法,将某个已经定义的方法添加到类中。如果类本身已经有了同名的方法,那么将会替换掉类中的方法体。

 

class_name.method_name = exist_name
class Yesterday:
    pass
def today(self):
    print 'Today is a nice day'
if __name__ == '__main__':
    Yesterday.yesterday = today
    yes = Yesterday()
    yes.yesterday()
输出结果:Today is a nice day

 

3 继承                                                              

 

  继承是子类继承父类的属性和方法,python中没有extends关键字,用括号

 

class class_name(father_class_name)
一个例子:

 

View Code

 

3.1 super调用父类方法         

 

  python支持用super关键字来调用父类的方法

 

'''
Created on 2013-8-6

@author: Landau
'''
class Father:
    def __init__(self):
        print 'I am the __init__ of father'
        print 'Use later'
class Son(Father):
    def __init__(self):
        print 'I am the __init__ of son'
        Father.__init__(self)
b = Son()

 

  我们也可以使用super关键字来实现上面的功能

 

View Code

 

3.2 多继承                          

 

  python允许多重继承。语法格式如下:
class class_name(fatherclass1_name,fatherclass2_name)
  多继承是这样的,比如一个人,眼睛像妈妈,肤色像爸爸。这就是多继承。

 

 

 

View Code

 

3.3 类的命名空间                 

 

  类和类成员的名称是丰富的,为了描述一个具体的对象,需要对类和类成员进行设计,在设计类和类成员过程中,难免会出现类的名称或类成员中的方法相同的情况,这样就会造成代码混乱,从而使代码的可读性降低。使用命名空间可以解决此问题。
  在java中,我们只要把类放到各自的包中,就可以避免类的名称或者类成员重复了,我们可以认为package是java的命名空间。
  在python中,定义类时,所有位于class语句中的代码都在特殊的命名空间中执行,该命名空间被称为类命名空间(class namespace)。这个类命名空间不仅可以被类中所有成员访问,还可以被类的实例方法访问。

 

3.4 继承检查                        

 

  python提供了内建的issubclass函数用于继承检查

 

View Code

 

  issubclass函数的第一个参数是子类,第二个参数是可能的父类,类似还有一个函数isinstance,用于检查一个对象是不是一个类的实例,第一个参数是对象,第二个参数是可能的类。

 

3.5 新式类                            

 

  新式类是指从python2.2开始引入的类。通常情况下,从object或者其他内置类型衍生的类,都被称为新式类。
__slots__类属性
  这个类属性用于替代__dict__属性
  __slots__是一个类变量,可以由一系列对象组成,使用所有合法标识构成的实例属性的集合来表示。它也可以是一个列表、元组或可迭代对象,总之,任何试图创建一个其名不在__slots__中的实例属性的操作都将引发AttributeError异常,而且实例属性必须初始化。
  一般情况下,__slots__类属性在class语句顶层设置。下面通过一个例子说明:

 

class MyLimiter(object):
    __slots__ = 'my_name', 'my_age', 'my_hobby'
if __name__ == '__main__':
    x = MyLimiter()
    x.my_name = 'AiQi'
    print x.my_name 

 

posted @ 2013-08-09 21:14  朗道二级相变  阅读(377)  评论(0编辑  收藏  举报