代码的编写一般分为三个阶段:

1、面向过程编程

针对具体需求的逻辑从上到下实现功能,当逻辑中出现重复的功能,采用的就是复制粘贴代码的方式来实现。

2、函数式编程

将需求中重复的功能封装到一个函数中,当逻辑中需要用到时则调用该函数,而无需重复编写。

3、面向对象编程

Python中一切都是对象,而对象是基于类创建的,根据类创建对象的过程叫实例化,被创建的对象又叫实例,具体到怎么实现Python的面向对象编程。简单的解释就是:

先定义一个类,然后在类中定义不同的方法(函数),不同的方法之间可以共用一组变量,然后根据这个类创建对象,被创建的对象就可以使用类中的方法。

Python面向对象具有以下特性:

1、封装

  简单解释:隐藏对象所使用方法的具体细节。

  普通解释:在由类创建对象时,每个被创建的对象中都有一个类对象指针,指向创建它的类,对象所使用的方法全部保存在类当中,类中的方法在执行的时候,需要使用的变量保存在对象中,这样对象所使用的方法对对象来说就是隐藏的,对象只能使用而不能修改这些方法。

  详细解释:

class Person:              #class是语法关键字 Person是类的名称
    def __init__(self,name):     #构造方法,根据类创建对象时自动执行
        self.name = name    #构造普通字段(变量),具体意思后面会解释
        print 'Name is:%s'%self.name

    def say(self):          #定义一个方法,参数self为必填,且不能改变
        print 'Name Say:%s'%self.name

p1 = Person('zhangsan') #根据Person类创建一个p1对象,在创建的时候会自动执行Person类中的__init__方法将传入的参数zhangsan封装到p1的name属性中,也就是p1.name='zhangsan'。同时会自动生成一个隐藏的类对象指针指向Person类,用来标示p1是由Person类创建的。

p1.say()          #执行p1的say方法,这时p1本身是没有say方法的,它会根据类对象指针来找到用来创建它的Person类,然后执行Person类中的say方法,say方法需要用到self.name变量,这个变量是保存在对象本身中的,也就是self.name=p1.name,而p1.name在创建p1时已经构造完成,p1.name='zhangsan'
         
p2 = Person('lisi')    #根据Person类创建一个p2对象,在创建的时候会自动执行Person类中的__init__方法将传入的参数zhangsan封装到p2的name属性中,也就是p2.name='lisi'。同时会自动生成一个隐藏的类对象指针指向Person类,用来标示p2是由Person类创建的。

p2.say()          #执行p2的say方法,这时p2本身是没有say方法的,它会根据类对象指针来找到用来创建它的Person类,然后执行Person类中的say方法,say方法需要用到self.name变量,这个变量是保存在对象本身中的,也就是self.name=p2.name,而p2.name在创建p2时已经构造完成,p2.name='lisi'

执行结果:

Name is:zhangsan 
Name Say:zhangsan
Name is:lisi 
Name Say:lisi

以上例子的语法很简单,比较绕的可能就是一个self。封装的重点和难点也就在这个self,下面来具体解释这个self的意义:

面向对象中同一个类可以创建多个对象,这些对象所具有的方法都是来自于创建他们的类(对照上述例子中的say方法)。

那么问题来了:多个对象调用的都是同一个类中的同一个方法,那么方法在执行的时候是怎么区分是谁在调用它呢?怎么知道self.name的值该是什么呢?

这就是self的用处所在:在使用类创建对象的时候,会自动把对象的名称赋值给类中的self参数。

比如:

p1 = Person('zhangsan')     #使用Person类创建一个名称叫p1的对象。这时Person类中的__init__方法将会被执行,执行过程就是:
def __init__('p1','zhangsan'):
    p1.name = 'zhangsan'
    print 'Name is:%s'%p1.name
#当执行p1.say()方法时,执行过程是:
def say('p1'):
    print 'Name Say:%s'%p1.name
#其实相当于执行 Person.say('p1')

总结:对象在调用类方法的时候,对象是谁,那么方法中self的值就是谁。(self本质就是一个形式参数)


2、继承

  简单解释:派生类(子类)继承基类(父类)的方法。(子承父业)

  普通解释:Python中支持多继承(一个类可以继承多个类),当类是经典类的时候,如果继承的方法重复则广度优先(先横着找),当类是新式类的时候,如果继承的方法重复则深度优先(先竖着找)。

经典类和新式类的区别就是在定义的时候,新式类会继承object,如果一个类继承的父类是新式类,那么他也是新式类。这里我们不过多的去解释新式类和经典类在继承上的区别,因为容易把自己绕晕,记住新式类的继承规则就可以了。

  详细解释:

class D(object):        #定义一个新式类D
    def f1(self):       #在类中定义一个f1方法
        print 'D:f1'
class C(D):             #定义一个类C,继承类D
    def f1(self):       #在类中也定义一个f1方法
        print 'C:f1'
class B(D):             #定义一个类B,继承类D
    pass                #不定义任何方法
class A(B,C):           #定义一个类A,同时继承类B和C
    pass                #不定义任何方法

obj = A()               #根据类A创建对象
obj.f1()                #执行f1方法

执行结果:
C:f1

上面程序的执行过程如下:

由于类D继承了object,所以它是一个新式类。C继承了D,所以C也是新式类,B也一样。A继承了B和C,所以A也是新式类。

对象obj执行f1方法,根据新式类继承的查找原则,顺序如下:

第一步:去A中查找f1方法,未找到。

第二步:去B中查找f1方法,未找到。

    这里虽然B继承了D的f1方法,但是由于新式类是先横着查找,所以不会执行D中的f1方法

第三步:去C中查找f1方法,找到,然后执行,所以结果是C:f1。


继承中的其他需求用法:

如果在继承的时候同时希望使用基类(父类)中的字段(变量),该如何实现:

class Person:
        def __init__(self,name):
                print 'Person build self.name'
                self.name = name
        def say(self):
                print 'Person.say'

class Son(Person):                            #定义一个类继承Person类
        def __init__(self,name,age):
                Person.__init__(self,name)    #执行父类中的构造方法
                print 'Son build self.age'
                self.age = age
                print 'Person name is %s age is %s'%(self.name,self.age)

p1 = Son('lily',17)
p1.say()

执行结果:

Person build self.name

Son build self.age

Person name is lily age is 17

Person.say


下一篇再介绍类的成员和类成员修饰符。