Python从设计之初就已经是一门面向对象的语言,因为如此,在Python中创建一个类和对象是很容易的。
    面向对象技术介绍

    • 类(Class): 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。
    • 类变量:类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用。
    • 数据成员:类变量或者实例变量, 用于处理类及其实例对象的相关的数据。
    • 方法重写:如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(override),也称为方法的重写。
    • 实例变量:定义在方法中的变量,只作用于当前实例的类。
    • 继承:即一个派生类(derived class)继承基类(base class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。例如,有这样一个设计:一个Dog类型的对象派生自Animal类,这是模拟”是一个(is-a)”关系(例图,Dog是一个Animal)。
    • 实例化:创建一个类的实例,类的具体对象。
    • 方法:类中定义的函数。
    • 对象:通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。

    创建类
    使用class语句来创建一个新类,class之后为类的名称并以冒号结尾。
    语法:

    1. class ClassName:
    2. '类的帮助信息' #类文档字符串
    3. class_suite #类体

    实例:

    1. #!/usr/bin/python
    2. # -*- coding: UTF-8 -*-
    3. class Employee:
    4. '所有员工的基类'
    5. empCount = 0
    6. def __init__(self, name, salary):
    7. self.name = name
    8. self.salary = salary
    9. Employee.empCount += 1
    10. def displayCount(self):
    11. print "Total Employee %d" % Employee.empCount
    12. def displayEmployee(self):
    13. print "Name : ", self.name, ", Salary: ", self.salary

    说明:empCount 变量是一个类变量,它的值将在这个类的所有实例之间共享。可以在内部类或外部类使用 Employee.empCount 访问。第一种方法init()方法是一种特殊的方法,被称为类的构造函数或初始化方法,当创建了这个类的实例时就会调用该方法。self 代表类的实例,self 在定义类的方法时是必须有的,虽然在调用时不必传入相应的参数。
    创建实例对象
    要创建一个类的实例,可以使用类的名称,并通过init方法接受参数。

    1. "创建 Employee 类的第一个对象"
    2. emp1 = Employee("Sherlock", 2000)
    3. "创建 Employee 类的第二个对象"
    4. emp2 = Employee("John", 5000)

    访问属性
    可以使用点(.)来访问对象的属性。
    使用如下类的名称访问类变量:

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

    实例:

    1. #coding=utf-8
    2. #!/usr/bin/python
    3. class Employee:
    4. '所有员工的基类'
    5. empCount = 0
    6. def __init__(self, name, salary):
    7. self.name = name
    8. self.salary = salary
    9. Employee.empCount += 1
    10. def displayCount(self):
    11. print "Total Employee %d" % Employee.empCount
    12. def displayEmployee(self):
    13. print "Name : ", self.name, ", Salary: ", self.salary
    14. "创建 Employee 类的第一个对象"
    15. emp1 = Employee("Sherlock", 2000)
    16. "创建 Employee 类的第二个对象"
    17. emp2 = Employee("John", 5000)
    18. emp1.displayEmployee()
    19. emp2.displayEmployee()
    20. print "Total Employee %d" % Employee.empCount

    运行案例
    可以添加、删除、修改类的属性。
    语法:

    1. emp1.age = 18 # 添加一个 'age' 属性
    2. emp1.age = 20 # 修改 'age' 属性
    3. del emp1.age # 删除 'age' 属性

    可以使用如下函数来访问属性:

    1. getattr(obj, name[, default]) : 访问对象的属性。
    2. hasattr(obj,name) : 检查是否存在一个属性。
    3. setattr(obj,name,value) : 设置一个属性。如果属性不存在,会创建一个新属性。
    4. delattr(obj, name) : 删除属性。

    实例:

    1. hasattr(emp1, 'age') # 如果存在 'age' 属性返回 True。
    2. getattr(emp1, 'age') # 返回 'age' 属性的值
    3. setattr(emp1, 'age', 18) # 添加属性 'age' 值为 18
    4. delattr(empl, 'age') # 删除属性 'age'

    Python内置类属性
    Python有如下几种内置属性:

    • dict : 类的属性(包含一个字典,由类的数据属性组成)
    • doc :类的文档字符串
    • name: 类名
    • module: 类定义所在的模块(类的全名是’main.className’,如果类位于一个导入模块mymod中,那么className.module 等于 mymod)
    • bases : 类的所有父类构成元素(包含了以个由所有父类组成的元组)

    实例:

    1. #coding=utf-8
    2. #!/usr/bin/python
    3. class Employee:
    4. '所有员工的基类'
    5. empCount = 0
    6. def __init__(self, name, salary):
    7. self.name = name
    8. self.salary = salary
    9. Employee.empCount += 1
    10. def displayCount(self):
    11. print "Total Employee %d" % Employee.empCount
    12. def displayEmployee(self):
    13. print "Name : ", self.name, ", Salary: ", self.salary
    14. print "Employee.__doc__:", Employee.__doc__
    15. print "Employee.__name__:", Employee.__name__
    16. print "Employee.__module__:", Employee.__module__
    17. print "Employee.__bases__:", Employee.__bases__
    18. print "Employee.__dict__:", Employee.__dict__

    运行案例
    Python对象销毁
    Pythonzhu引用计数来追踪内存中的对象。
    在Python内部记录着所有使用中的对象各有多少引用。
    一个内部跟踪变量称为一个引用计数器。
    当对象被创建时,就创建了一个引用计数,当这个对象不在需要时,即这个对象的引用计数变为0时,被垃圾回收。回收不是立即回收,由解释器在适当的时机,将垃圾对象占用的内存空间回收。
    垃圾回收机制不仅针对引用计数为0的对象,同样也可以处理循环引用的情况。循环引用指的是,两个对象相互引用,但是没有其他变量引用他们。这种情况下,仅使用引用计数是不够的。Python 的垃圾收集器实际上是一个引用计数器和一个循环垃圾收集器。作为引用计数的补充, 垃圾收集器也会留心被分配的总量很大(及未通过引用计数销毁的那些)的对象。 在这种情况下, 解释器会暂停下来, 试图清理所有未引用的循环。
    实例:

    1. #coding=utf-8
    2. #!/usr/bin/python
    3. class Point:
    4. def __init( self, x=0, y=0):
    5. self.x = x
    6. self.y = y
    7. def __del__(self):
    8. class_name = self.__class__.__name__
    9. print class_name, "destroyed"
    10. pt1 = Point()
    11. pt2 = pt1
    12. pt3 = pt1
    13. print id(pt1), id(pt2), id(pt3) # 打印对象的id
    14. del pt1
    15. del pt2
    16. del pt3

    运行案例
    说明:析构函数 deldel在对象消逝的时候被调用,当对象不再被使用时,del方法运行。
    类的继承
    面向对象的编程带来的主要好处之一是代码的重用,实现这种重用的方法之一是通过继承机制。继承完全可以理解成类之间的类型和子类型关系。
    需要注意的地方:继承语法 class 派生类名(基类名)://… 基类名写作括号里,基本类是在类定义的时候,在元组之中指明的。
    在python中继承中的一些特点:
    1:在继承中基类的构造(init()方法)不会被自动调用,它需要在其派生类的构造中亲自专门调用。
    2:在调用基类的方法时,需要加上基类的类名前缀,且需要带上self参数变量。区别于在类中调用普通函数时并不需要带上self参数
    3:Python总是首先查找对应类型的方法,如果它不能在派生类中找到对应的方法,它才开始到基类中逐个查找。(先在本类中查找调用的方法,找不到才去基类中找)。
    如果在继承元组中列了一个以上的类,那么它就被称作”多重继承” 。
    语法:

    1. class SubClassName (ParentClass1[, ParentClass2, ...]):
    2. 'Optional class documentation string'
    3. class_suite

    实例:

    1. #coding=utf-8
    2. #!/usr/bin/python
    3. class Parent: # 定义父类
    4. parentAttr = 100
    5. def __init__(self):
    6. print "调用父类构造函数"
    7. def parentMethod(self):
    8. print '调用父类方法'
    9. def setAttr(self, attr):
    10. Parent.parentAttr = attr
    11. def getAttr(self):
    12. print "父类属性 :", Parent.parentAttr
    13. class Child(Parent): # 定义子类
    14. def __init__(self):
    15. print "调用子类构造方法"
    16. def childMethod(self):
    17. print '调用子类方法 child method'
    18. c = Child() # 实例化子类
    19. c.childMethod() # 调用子类的方法
    20. c.parentMethod() # 调用父类方法
    21. c.setAttr(200) # 再次调用父类的方法
    22. c.getAttr() # 再次调用父类的方法

    运行案例
    Python还允许继承多个类。
    语法:

    1. class A: # 定义类 A
    2. .....
    3. class B: # 定义类 B
    4. .....
    5. class C(A, B): # 继承类 A 和 B
    6. .....

    可以使用issubclass()或者isinstance()方法来检测。

    • issubclass() - 布尔函数判断一个类是另一个类的子类或者子孙类,语法:issubclass(sub,sup)
    • isinstance(obj, Class) 布尔函数如果obj是Class类的实例对象或者是一个Class子类的实例对象则返回true。

    方法重写
    如果父类方法的功能不能满足需求,可以在子类重写父类的方法。
    实例:

    #coding=utf-8
    #!/usr/bin/python
    
    class Parent:        # 定义父类
       def myMethod(self):
          print '调用父类方法'
    
    class Child(Parent): # 定义子类
       def myMethod(self):
          print '调用子类方法'
    
    c = Child()          # 子类实例
    c.myMethod()         # 子类调用重写方法
    

    运行案例
    基础重载方法

    方法 说明 调用示例
    init ( self [,args…] ) 构造函数 obj = className(args)
    del( self ) 析构方法, 删除一个对象 dell obj
    repr( self ) 转化为供解释器读取的形式 repr(obj)
    str( self ) 用于将值转化为适于人阅读的形式 str(obj)
    cmp ( self, x ) 对象比较 cmp(obj, x)

    运算符重载
    实例:

    #!/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
    

    运行案例
    类属性/方法
    类的私有属性
    private_attrs:两个下划线开头,声明该属性为私有,不能在类地外部被使用或直接访问。
    在类内部的方法中使用时 self.
    private_attrs。
    类的方法
    在类的内部,使用def关键字可以为类定义一个方法,与一般函数定义不同,类方法必须包含参数self,且为第一个参数。
    类的私有方法
    private_method:两个下划线开头,声明该方法为私有方法,不能在类地外部调用。
    在类的内部调用 self.
    private_methods。
    实例:

    #coding=utf-8
    #!/usr/bin/python
    
    class JustCounter:
        __secretCount = 0  # 私有变量
        publicCount = 0    # 公开变量
    
        def count(self):
            self.__secretCount += 1
            self.publicCount += 1
            print self.__secretCount
    
    counter = JustCounter()
    counter.count()
    counter.count()
    print counter.publicCount
    print counter.__secretCount  # 报错,实例不能访问私有变量
    

    运行案例
    Python不允许实例化的类访问私有数据,但可以使用 object.className__attrName( 对象名.类名__私有属性名 )访问属性。
    实例:

    #!/usr/bin/python
    # -*- coding: UTF-8 -*-
    
    class Imooc:
        __site = "www.imooc.com"
    
    imooc = Imooc()
    print imooc._Imooc__site