Python初级008-面向对象

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python初级008-面向对象相关的知识,希望对你有一定的参考价值。

 

面向对象

 

目录

1:类与对象

-------什么是类和对象

-------什么是属性与方法

2:面向对象的三大类型

-------封装

-------继承

-------多态

 

 

 

一、类与对象

   -------什么是类和对象

Python中什么是对象?object=对象

   Python中一切皆为对象,所谓对象:我自己就是一个对象,我玩的电脑就是对象,坐着的椅子就是对象,家里养的小狗也是一个对象。对象是存在的。

Python中什么是类?class=

python中,把具有相同属性和方法的对象归为一个类(class

比如人类,动物,植物等等,这些都是类的概念。

我们在描述一个真实对象(物体)时包括两个方面:

它可以做什么(行为--动态)

它是什么样的(属性或特征---静态固有的)。

 结论:

类是对象的模板或蓝图,类是对象的抽象化,对象是类的实例化。类不代表具体的事物,而对象表示具体的事物。也可以说类就是对象,对象=属性+方法。

 

 -------什么是属性与方法

通过描述属性(特征)和行为来描述一个对象的。比如家里的小狗,它的颜色,大小,年龄,体重等是它的属性或特征。它会汪汪叫,会摇尾巴等是它的行为。在python中,一个对象的特征也称为属性(attribute)。它所具有的行为也称为方法(method

总结:实际上对象的属性就是定义的变量,方法就是定义的函数。

 

例子:简单的认识类,对象,属性和方法

>>> class people:                #定义的一个类,类名为people  
...     def speak(self):            #定义了speak函数,即为对象的方法                
...             print ("hello!")                
>>> jack = people()    #对象是类的实例,即创建了jack对象

>>> tom = people()    #创建tom实例(对象)
>>> import tab        #导入table键功能模块

>>> jack.            #输入jack.(对象),可以看到以下方法
jack.__class__   j ack.__doc__      jack.__module__ 

Jack.speak     jack.height       jack.age   
>>> jack.speak()    #引用speak方法
hello!
>>> jack.age=39            #定义了变量,即对象的属性---->添加对象jack的属性,age=39
>>> jack.height=120        #添加height属性

 

例子:初始化对象
    创建类时,可以先给方法定义定义一个特定的方法,语法是__init__(),括号中放的是定义对象特定的方法。,只要创建这个类的一个实例(对象),就会运行这个方法。可以向__init__()方法传递参数,这样创建对象时就可以把属性设置为你希望的值__init__()这个方法会在创建对象时完成初始化
>>> class peo:
...     def __init__(self,name,age,sex):
...             self.Name = name
...             self.Age = age
...             self.Sex = sex
...     def speak(self):
...             print "my name" + self.Name

例子:

>>> class Ball:

def setName(self,name):

self.name = name

def kick(self):

print("我叫%s,你好。" % self.name)

>>> a = Ball()

>>> a.setName(‘Genal‘)

>>> b = Ball()

>>> b.setName (‘Alix‘)

>>> a.kick()

我叫Genal,你好。

>>> b.kick()

我叫Alix,你好。

 

二、面向对象的三大特性

1、多态 : 可以对不同类的对象使用同样的操作(指就算不知道变量所引用的对象类型是什么,还是能对他进行操作,而它也会根据对象或类的类型的不同而表现出不同的行为)

2、封装 : 对外部事件对象工作的具体细节

3、继承 : 通用的类为基础建立专门的类对象

 

-------封装

1、将内容封装到某处:对象的变量封装给类的变量

class People:                        #定义一个People

    def __init__(self,name,age,sex): #构造方法,(当实例化对象时,自动执行这个方法)

        self.name = name #指定对象的变量封装给类的变量

        self.age = age

        self.sex = sex

P1 = People(‘Alix‘,‘28‘,‘male‘) #实例化对象P1,将"allen"25"male"分别封装

                                  到了 P1/self 中的nameagesex属性中

P2 = People(‘Genal‘,‘15‘,‘man‘)   #P2 ,同上

    

分析:

1__init__ 属于python语言的构造函数,一个类只能有一个__init__方法当实例化对象时,自动执行这个方法

2__init__中的self是一个形式参数,在所有定义的方法当中,括号()里面的参数第一个必须是self参数,当然,python语言中是自带的,可以不写。Self参数表示的是对象的自己,如上述的例子中,self所代表的对象就是P1P2

3(self,name,age,sex)括号中的参数除了self外,都可以把他看做是变量(变量是对象的属性),

4的概念:属于一个对象或类的变量被称为域,其实就是类里面定义的变量

——类的变量和对象的变量

1类的变量:由一个类的所有对象(实例)共享使用(self,name,age,sex)nameagesex三个就是类的变量,只有一个类变量的拷贝,所以当某个对象对类的变量做了改动的时候,这个改动会反映到所有其他的实例上。我理解为:其实它就是一个类的全局变量,类实例化后的对象都可以调用该变量。

2对象的变量: 由类的每个对象/实例拥有(‘Alix‘,‘28‘,‘male‘)中的三个变量就是对象的变量,不能给其他对象使用。因此每个对象有自己对这个域的一份拷贝,即它们不是共享的,在同一个类的不同实例中,虽然对象的变量有相同的名称,但是是互不相关的。我理解的是:不同的对象调用该变量,其值改变后互不影响

3)变量的应用

属于类级别的变量,在使用它的时候一定要带上类型名字 比如 MyClass.count

属于每个对象级别的变量,在调用的时候一定要带上self表明属于当前对象。self.name

5self.name = nameself.name 可以看做是自己的变量,是一个变量,名字叫做name,它是对象的变量(看上面的定义)。等于号后面的name也是一个变量,它是一个对类的变量(看上面的定义),这两个变量的名称虽然相同但是他们的域不同,所以代表不同的变量,区别就在于,第一个变量name的前面有个“点”。

6在实例化对象P1P2的过程中(封装)self分别等于P1P2, 相对于内容被分别封装到了P1P2中,每个对象都有nameagesex属性。

 

封装过程如下

技术分享 

 

 

2、从某处调用被封装的内容:

例子:通过对象直接调用被封装的内容

class People:

    def __init__(self,name,age,sex):

        self.name = name

        self.age = age

        self.sex = sex

P1 = People(‘Alix‘,‘28‘,‘male‘)

P2 = People(‘‘Genal‘,‘15‘,‘man‘)

print P1.name       #直接调用P1对象的name属性

print P2.name       #直接调用P2对象的name属性

执行结果如下

Alix

Genal

 

    ---------继承

例子:多个子类继承父类

class Fruit:

    def __init__(self,color):

        self.color = color

        print "fruit‘s color: %s" % self.color

    def grow(self):

        print "This is grow ..."

class Apple(Fruit):                             #继承了父类Apple称为子类

    def __init__(self, color):                  #显示调用父类的__init__方法

        Fruit.__init__(self, color)

        print "apple‘s color: %s" % self.color

class Banana(Fruit):                           #继承了父类

    def __init__(self,color):                  #显示调用父类的__init__方法

        Fruit.__init__(self,color)

        print "banana‘s color:%s" % self.color

 

    def grow(self):                            #覆盖了父类的grow方法

        print "banana grow..."

 

apple = Apple(‘red‘) 

apple.grow()

banana = Banana(‘yellow‘)

banana.grow()

 

执行结果如下:

======================= RESTART: C:/Python27/class.py =======================

fruit‘s color: red

apple‘s color: red

This is grow ...

fruit‘s color: yellow

banana‘s color:yellow

banana grow...

 

结果解析:

>>> apple = Apple(‘red‘)

fruit‘s color: red

apple‘s color: red

#定义了子类Apple的对象是apple。调用了子类Apple的方法,输出的是父类和子类,这就是继承-先输出父类在输出子类

>>> apple.grow()

This is grow ...

#apple是子类Apple的对象,这里调用的方法是父类的,输出的只有父类,没有子类。因为这里的子类Apple没有覆盖父类grow的方法。

>>> banana = Banana(‘yellow‘)

fruit‘s color: yellow

banana‘s color:yellow

#同上

>>> banana.grow()

banana grow...

#这里的banana是子类Banana的对象,覆盖了父类的grow方法,所以输出的直接是子类。

 

总结:

对于面向对象的继承来说,其实就是将多个类共有的方法提取到父类中,子类仅需继承父类而以,不必一一实现每个方法。

 

 

////////////////////////////////////////////////////////////////////////////////////////////////////

那么问题又来了,多继承呢?

是否可以继承多个类

如果继承的多个类每个类中都定了相同的函数,那么那一个会被使用呢?

1Python的类可以继承多个类,JavaC#中则只能继承一个类

2Python的类如果继承了多个类,那么其寻找方法的方式有两种,分别是:深度优先广度优先

技术分享 

当类是经典类时,多继承情况下,会按照深度优先方式查找

当类是新式类时,多继承情况下,会按照广度优先方式查找

经典类和新式类,从字面上可以看出一个老一个新,新的必然包含了跟多的功能,也是之后推荐的写法,从写法上区分的话,如果 当前类或者父类继承了object,那么该类便是新式类,否则便是经典类。

 

技术分享

技术分享

 

 

例子:子类继承多个父类---经典类多继承

class D:                  #经典类     

    def bar1(self):

        print "D.bar1"

class C(D):                #子类C继承父类D

    def bar1(self):

        print "C.bar1"

class B(D):                #子类B继承父类D

    # def bar1(self):

    #     print "B.bar1"

    pass                  #pass 代表什么也不做

class A(B,C):              #子类A继承父类BC

    # def bar1(self):

    #     print "A.bar1"

    pass                  #pass 代表什么也不做

 

op = A()                  #实例化对象op

op.bar1()                 #访问opbar1方法,但是具体访问到哪个方法呢???

 

执行结果如下:

======================= RESTART: C:/Python27/class.py =======================

D.bar1

 

问题:为什么是访问到了D.bar1 ?

 

分析如下:

当我们实例化op,并且调用bar1方法时,由于在类中有多个bar1方法,因此对于经典类,它自己有一个查找顺序,A ---> B --> D --> C, python中查找的方法是从子类开始找,一层一层的往父类上找。首先找A,如果A中没有,则找B,如果B中没有,再找D,如果D中也没有,最后找C如果都没有找到则报错;这种访问方式叫做深度优先.对于我们上面这个例子,由于找A B 时都没有找到,则找到了D,因此打印了D.bar1

 

例子:子类继承多种父类----新式类多继承

class D(object):          #新式类    

    def bar1(self):

        print "D.bar1"

class C(D):               

    def bar1(self):

        print "C.bar1"

class B(D):

    # def bar1(self):

    #     print "B.bar1"

    pass                  #pass 代表什么也不做

class A(B,C):

    # def bar1(self):

    #     print "A.bar1"

    pass                  #pass 代表什么也不做

 

op = A()                  #实例化对象op

op.bar1()                 #访问opbar1方法,但是具体访问到哪个方法呢???

执行结果如下

======================= RESTART: C:/Python27/class2.py =======================

C.bar1     

问题:

为什么是C.bar1 ?? 和经典类结果相差很大...为什么?

 

分析如下:

新式类追寻的规律如下:A --> B --> D --> C意思是,首先找A,如果A中没有,则找B,如果B中没有,则找C,如果C中也没有,则找D,最后都没找到,则报错;这种访问方式叫广度优先对于我们上面的例子,由于A B 中都没有,则找CC中找到了则打印C.bar1,

对于广度优先,你可以理解为找最近的点,比如上面的例子,A继承B,C ,由于在B中找不到,则去找C,(因为A继承C,离A最近,)找到C,则直接打印C.bar1

 

      ------------------多态

Pyhon不支持多态并且也用不到多态,多态的概念是应用于JavaC#这一类强类型语言中,而Python崇尚鸭子类型

以下是维基百科中对鸭子类型得论述:

在程序设计中,鸭子类型(英语:duck typing)是动态类型的一种风格。在这种风格中,

一个对象有效的语义,不是由继承自特定的类或实现特定的接口,而是由当前方法和属性的

集合决定。这个概念的名字来源于由James Whitcomb Riley提出的鸭子测试,鸭子测试

可以这样表述:当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。

例子:Python “鸭子类型”

class F1:

    pass

class S1(F1):

    def show(self):

        print ‘S1.show‘

class S2(F1):

    def show(self):

        print ‘S2.show‘

def Func(obj):

    print obj.show()

s1_obj = S1()

Func(s1_obj)

s2_obj = S2()

Func(s2_obj)

Python “鸭子类型”

 

以上就是本节对于面向对象初级知识的介绍,总结如下:

· 面向对象是一种编程方式,此编程方式的实现是基于对   对象 的使用

·  是一个模板,模板中包装了多个函数供使用

· 对象,根据模板创建的实例(即:对象),实例用于调用被包装在类中的函数

· 面向对象三大特性:封装、继承和多态

 

 

 

 

 

 

 

 

 

 


本文出自 “末班车” 博客,请务必保留此出处http://blxueyuan.blog.51cto.com/9673381/1877387

以上是关于Python初级008-面向对象的主要内容,如果未能解决你的问题,请参考以下文章

面向对象编程其实很简单--python面向对象(初级篇)

Python 面向对象初级篇

Python 面向对象初级篇

python 高级之面向对象初级

python 面向对象初级篇

面向对象编程其实很简单——Python 面向对象(初级篇)