面向对象有三大特征:多态(对应方法覆写)、封装、继承(对应方法重载),这个在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'

运行结果:

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

  另外方法中的局部变量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'

  显然报错了,也就是私有的属性不能被实例化对象访问。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

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

说明:上面代码中,使用内置属性__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

  上面代码中,在类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

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)
一个例子:

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关键字来实现上面的功能

3.2 多继承

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

3.3 类的命名空间

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

3.4 继承检查

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

  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 

最新文章

  1. [Python核心编程] 第1章 欢迎来到Python世界
  2. jmeter(二)录制脚本
  3. ajax文件下载
  4. 关于如何来构造一个String类
  5. Linux字符设备
  6. JS高级程序设计2nd部分知识要点1
  7. Unity3D MainCamera和NGUI UICamera的小插曲
  8. Android Bitmap 全面解析(四)图片处理效果对比 ...
  9. 【Android 界面效果21】Android ViewPager使用详解
  10. VS2013 调试卡顿
  11. overlay
  12. 第1阶段——关于u-boot目标文件start.o中.globl 和.balignl理解(3)
  13. jumpserver 堡垒机环境搭建(图文具体解释)
  14. [Swift]动态变化顶部状态栏(statusBar)的颜色
  15. VB.NET或C#报错:You must hava a license to use this ActiveX control.
  16. MyBatis注解-动态SQL 一个 SqlProvider的demo
  17. BZOJ4077 : [Wf2014]Messenger
  18. pycharm的小问题之光标
  19. 【题解】Luogu CF343D Water Tree
  20. Laravel 更新数据时在表单请求验证中排除自己,检查指定字段唯一性

热门文章

  1. Directx 9 VS2015环境搭建
  2. git之cherry-pick
  3. 前端优化规范 webApp
  4. 1.react的基础知识
  5. 一段shallowCopy和deepCopy的认识
  6. 蓝桥杯 算法训练 ALGO-119 寂寞的数
  7. VisualGDB系列10:快速调试Linux应用程序
  8. PowerDesigner CDM中取消默认不能存在同名主键的方法
  9. 问题:oracle DECLARE 变量重复利用;结果:Oracle 定义变量总结
  10. springmvc+spring3+hibernate4框架简单整合,简单实现增删改查功能