首页 > 代码库 > 十一、PYTHON 面向对象编程

十一、PYTHON 面向对象编程

如果你没有任何以往的经验与面向对象(OO)编程,你可能想咨询或至少某种教程的入门课程,所以,你必须掌握的基本概念.

然而,这里是小推出的面向对象编程(OOP)给你带来更好的学习速度:

面向对象术语

类: 用户定义的一个对象,它定义了一套类的任何对象的属性特点的原型。属性数据成员(类变量和实例变量)和方法,通过点符号访问.

类变量: 一个类的所有实例共享变量。类变量被定义在一个类以外的任何类的方法。不作为类变量经常作为实例变量.

数据成员: A类变量或实例变量持有一个类和它的对象的相关数据.

函数重载: 分配到一个特定功能的多个行为。执行的操作,因涉及的对象(参数)的类型。

实例变量: 一个方法内定义的变量只属于一类的当前实例.

继承 : 传递类的特点是从它派生的其他类.

实例: 某个类的一个单独的对象。例如,一个对象obj属于类Circle,是类Circle的一个实例.

实例化 : 创建一个类的实例.

方法 : 一个是定义在类定义中的一种特殊功能.

对象: 这是由它的类定义一个数据结构的一个唯一的实例。对象包括数据成员(类变量和实例变量)和方法.

运算符重载: 多个函数分配到一个特定的运算符.

创建类:

类的语句创建一个新的类定义。类名紧跟在class关键字,随后由一个冒号如下:

class ClassName:
   ‘Optional class documentation string‘
   class_suite
  • 类有一个文档可以是通过ClassName.__doc__访问的字符串.

  • 该class_suite组成的所有组件的语句,定义类的成员,属性数据和函数.

例子:

下面是一个简单的Python类的例子:

class Employee:
   ‘Common base class for all employees‘
   empCount = 0

   def __init__(self, name, salary):
      self.name = name
      self.salary = salary
      Employee.empCount += 1
   
   def displayCount(self):
     print "Total Employee %d" % Employee.empCount

   def displayEmployee(self):
      print "Name : ", self.name,  ", Salary: ", self.salary
  • 在的变量empCount是一个类变量,它的值将这个类的所有实例之间共享。这可以作为Employee.empCount类或内部类的外部访问.

  • 第一种方法__init__()方法是一种特殊的方法,被称为类的构造函数或初始化方法,当你创建了这个类的新实例时Python就会调用.

  • 你声明异常,每个方法的第一个参数是自我的正常功能等其他类的方法。 Python中添加自参数到你的列表,当你调用的方法,你不需要包括它.

创建实例对象:

要创建一个类的实例,调用类,使用类的名称,并通过在其__init__方法接受任何参数.

"This would create first object of Employee class"
emp1 = Employee("Zara", 2000)
"This would create second object of Employee class"
emp2 = Employee("Manni", 5000)

访问属性:

您可以使用点运算对象访问对象的属性。使用如下类的名称将访问类变量:

emp1.displayEmployee()
emp2.displayEmployee()
print "Total Employee %d" % Employee.empCount

现在把它一起:

#!/usr/bin/python

class Employee:
   ‘Common base class for all employees‘
   empCount = 0

   def __init__(self, name, salary):
      self.name = name
      self.salary = salary
      Employee.empCount += 1
   
   def displayCount(self):
     print "Total Employee %d" % Employee.empCount

   def displayEmployee(self):
      print "Name : ", self.name,  ", Salary: ", self.salary

"This would create first object of Employee class"
emp1 = Employee("Zara", 2000)
"This would create second object of Employee class"
emp2 = Employee("Manni", 5000)
emp1.displayEmployee()
emp2.displayEmployee()
print "Total Employee %d" % Employee.empCount

这将产生以下结果:

Name :  Zara ,Salary:  2000
Name :  Manni ,Salary:  5000
Total Employee 2

在任何时候,您可以添加,删除或修改类和对象的属性:

emp1.age = 7  # Add an ‘age‘ attribute.
emp1.age = 8  # Modify ‘age‘ attribute.
del emp1.age  # Delete ‘age‘ attribute.

而不是使用正常的语句来访问属性,可以使用以下功能:

  • getattr(obj, name[, default]) : 访问对象的属性.

  • The hasattr(obj,name) : 检查是否存在一个属性.

  • The setattr(obj,name,value) : 设置一个属性。如果属性不存在,然后将它创建.

  • The delattr(obj, name) : 删除属性.

hasattr(emp1, ‘age‘)    # Returns true if ‘age‘ attribute exists
getattr(emp1, ‘age‘)    # Returns value of ‘age‘ attribute
setattr(emp1, ‘age‘, 8) # Set attribute ‘age‘ at 8
delattr(empl, ‘age‘)    # Delete attribute ‘age‘

内建类属性:

每个Python类继内置属性,他们可以使用点运算符像任何其他属性:

  • __dict__ : 字典,包含类的命名空间.

  • __doc__ : 如果未定义类的文档字符串,则没有.

  • __name__: 类名.

  • __module__: 在类定义的模块名称。此属性是“__main__”的交互模式.

  • __bases__ : 一个基类包含在其发生在基类列表中的顺序可能是空的元组,.

对于上面的类,让我们尝试访问所有这些属性:

print "Employee.__doc__:", Employee.__doc__
print "Employee.__name__:", Employee.__name__
print "Employee.__module__:", Employee.__module__
print "Employee.__bases__:", Employee.__bases__
print "Employee.__dict__:", Employee.__dict__

这将产生以下结果:

Employee.__doc__: Common base class for all employees
Employee.__name__: Employee
Employee.__module__: __main__
Employee.__bases__: ()
Employee.__dict__: {‘__module__‘: ‘__main__‘, ‘displayCount‘:, ‘empCount‘: 2, 
‘displayEmployee‘:, 
‘__doc__‘: ‘Common base class for all employees‘, 
‘__init__‘:}

销毁对象(垃圾收集):

Python中删除不必要的对象(内置类型或类的实例),自动释放内存空间。其中Python的定期回收不再使用的内存块的过程被称为垃圾收集.

Python的垃圾收集器运行程序执行过程中被触发时,一个对象的引用计数达到零。别名对象的引用计数的变化,指出它的变化:

一个对象的引用计数增加时,它分配一个新的名称或放置在一个容器(列表,元组或字典)。该对象的引用计数减少,其引用被重新分配,或者其引用超出范围时,它用del删除。当一个对象的引用计数达到零时,Python它会自动收集.


a = 40      # Create objectb = a       # Increase ref. count  ofc = [b]     # Increase ref. count  ofdel a       # Decrease ref. count  ofb = 100     # Decrease ref. count  ofc[0] = -1   # Decrease ref. count  of


你通常不会注意到,当垃圾收集器会破坏一个孤立的实例,并回收其空间。但是,一个类可以实现特殊方法__del__(),称为析构函数,实例是即将被销毁时被调用。这种方法可用于任何一个实例的非内存资源用于清理.

例子:

__del__()析构函数打印一个实例的类的名称,是即将被销毁:

#!/usr/bin/python

class Point:
   def __init( self, x=0, y=0):
      self.x = x
      self.y = y
   def __del__(self):
      class_name = self.__class__.__name__
      print class_name, "destroyed"

pt1 = Point()
pt2 = pt1
pt3 = pt1
print id(pt1), id(pt2), id(pt3) # prints the ids of the obejcts
del pt1
del pt2
del pt3

这将产生以下结果:

3083401324 3083401324 3083401324
Point destroyed

注: 理想的情况下,你应该在单独的文件中定义的类,那么你应该在你的主程序文件使用import语句导入。 - 更多细节,请查看Python的导入模块和类模块章节.

类的继承:

而非从头开始,你可以创建一个类,它从一个已经存在的类派生新类的名称后括号中的父类列出:

子类继承它的父类的属性,如果他们在子类中定义,你可以使用这些属性。子类也可以覆盖从父数据成员和方法.

语法:

派生类的声明,就像他们的父类;但是继承的基类列表类名后:

class SubClassName (ParentClass1[, ParentClass2, ...]):
   ‘Optional class documentation string‘
   class_suite

例子:

#!/usr/bin/python

class Parent:        # define parent class
   parentAttr = 100
   def __init__(self):
      print "Calling parent constructor"

   def parentMethod(self):
      print ‘Calling parent method‘

   def setAttr(self, attr):
      Parent.parentAttr = attr

   def getAttr(self):
      print "Parent attribute :", Parent.parentAttr

class Child(Parent): # define child class
   def __init__(self):
      print "Calling child constructor"

   def childMethod(self):
      print ‘Calling child method‘

c = Child()          # instance of child
c.childMethod()      # child calls its method
c.parentMethod()     # calls parent‘s method
c.setAttr(200)       # again call parent‘s method
c.getAttr()          # again call parent‘s method

这将产生以下结果:

Calling child constructor
Calling child method
Calling parent method
Parent attribute : 200

类似的方式,你可以从多个父类的类如下:

class A:        # define your class A
.....

class B:         # define your calss B
.....

class C(A, B):   # subclass of A and B
.....

您可以使用issubclass()或isinstance()函数来检查一个关系两个类和实例:

  • issubclass(sub, sup) 布尔函数返回true,如果给定的子类subis的确是一个超类的子类sup.

  • isinstance(obj, Class) 布尔函数返回true,如果obj是一个Class类的实例,或者是一类的子类的一个实例.

重写方法:

你总是可以覆盖父类方法。覆盖父方法的原因之一是因为你可能想在你的子类特殊或不同的功能.

例如:

#!/usr/bin/python

class Parent:        # define parent class
   def myMethod(self):
      print ‘Calling parent method‘

class Child(Parent): # define child class
   def myMethod(self):
      print ‘Calling child method‘

c = Child()          # instance of child
c.myMethod()         # child calls overridden method

这将产生以下结果:

Calling child method

相应重载方法:

下表列出了一些通用的功能,你可以在自己的类覆盖:

SN方法、描述和简单调用
1__init__ ( self [,args...] )
Constructor (with any optional arguments)
Sample Call : obj = className(args)
2__del__( self )
Destructor, deletes an object
Sample Call : dell obj
3__repr__( self )
Evaluatable string representation
Sample Call : repr(obj)
4__str__( self )
Printable string representation
Sample Call : str(obj)
5__cmp__ ( self, x )
Object comparison
Sample Call : cmp(obj, x)


重载操作符:

假设你已经创建了一个Vector类来表示二维向量。当您使用加运算,将它们添加,会发生什么?最有可能的Python会骂你.

但是,你可以在类中定义__ add__方法进行向量相加,然后加上运算符将表现为每个期望:

例子:

#!/usr/bin/python

class Vector:
   def __init__(self, a, b):
      self.a = a
      self.b = b

   def __str__(self):
      return ‘Vector (%d, %d)‘ % (self.a, self.b)
   
   def __add__(self,other):
      return Vector(self.a + other.a, self.b + other.b)

v1 = Vector(2,10)
v2 = Vector(5,-2)
print v1 + v2

This would produce following result:

Vector(7,8)

Data Hiding:

An object‘s attributes may or may not be visible outside the class definition. For these cases, you can name attributes with a double underscore prefix, and those attributes will not be directly visible to outsiders:

Example:

#!/usr/bin/python

class JustCounter:
   __secretCount = 0
  
   def count(self):
      self.__secretCount += 1
      print self.__secretCount

counter = JustCounter()
counter.count()
counter.count()
print counter.__secretCount

结果如下:

1
2
Traceback (most recent call last):
  File "test.py", line 12, inprint counter.__secretCountAttributeError: JustCounter instance has no attribute ‘__secretCount‘

你可以通过 object._className__attrName的形式来访问.

如果你替换最后一行如下:

.........................
print counter._JustCounter__secretCount

最终的结果将会是:

1
2
2

十一、PYTHON 面向对象编程