Python学习笔记11(面向对象)

面向对象编程是一种编程方式,此编程方式的落地需要使用 “类” 和 “对象” 来实现,所以,面向对象编程其实就是对 “类” 和 “对象” 的使用。

类就是一个模板,模板里可以包含多个函数,函数里实现一些功能。

对象则是根据模板创建的实例,通过实例对象可以执行类中的函数。

1.创建一个类

1 class Dog(object):   #创建一个类
2 
3     def say(self):
4         print("wang~wang~wang~")
5 
6 
7 d = Dog() #生成一个实例
8 d.say()     #实例调用类中的say方法

上面的代码是一个极其简单的一个类的定义,连狗的名字都添加不进去,如果想添加进去狗的名字该如何处理呢?

 1 class Dog(object):
 2 
 3     def __init__(self,name):
 4         self.name = name
 5 
 6     def say(self):
 7         print("wo shi %s,wang~wang~wang~"%self.name)
 8 
 9 d = Dog("zzz")
10 d.say()
11 
12 #输出
13 wo shi zzz,wang~wang~wang~

为什么有__init__? 为什么有self? 下面画图做一个解释。

即使类还未进行实例化,这个Dog类本身也是已经存在内存里的。其实self,就是实例本身!你实例化时python会自动把这个实例本身通过self参数传进去,类中的函数必传的一个self参数。

__init__构造方法是类在被实例化的时候自动执行的,在讲构造函数的时候会详细讲解。

2.面向对象三大特性

面向对象的三大特性是指:封装、继承和多态。

一、封装

封装,其实就是使用构造方法将内容封装到某个具体对象中,然后通过对象直接或者self间接获取被封装的内容。

例如:

 1 class Dog(object):
 2 
 3     def __init__(self,name,age):
 4         self.name = name
 5         self.age = age
 6 
 7     def say(self):
 8         print("name:",self.name)
 9         print("age:",self.age)
10 
11 d1 = Dog("zzz",22)  #“zzz”,22内容被封装在了对象d1之中
12 d2 = Dog("yyy",23) #"yyy",23内容被封装在了对象d2之中
13 
14 print(d1.name,d1.age)  #通过d1对象调用name,age内容
15 print(d2.name,d2.age)  #通过d2对象调用name,age内容
16 d1.say()                       #通过self间接调用被封装的内容
17 d2.say()                       #通过self间接调用被封装的内容

二、继承

继承,面向对象中的继承和现实生活中的继承相同,即:子可以继承父的内容。

例如:

  猫可以:喵喵叫、吃、喝、拉、撒

  狗可以:汪汪叫、吃、喝、拉、撒

如果我们要分别为猫和狗创建一个类,那么就需要为 猫 和 狗 实现他们所有的功能,如下所示:

 1 class 猫:
 2 
 3     def 喵喵叫(self):
 4         print('喵喵叫')
 5 
 6     def 吃(self):
 7         # do something
 8 
 9     def 喝(self):
10         # do something
11 
12     def 拉(self):
13         # do something
14 
15     def 撒(self):
16         # do something
17 
18 class 狗:
19 
20     def 汪汪叫(self):
21         print ('汪汪叫')
22 
23     def 吃(self):
24         # do something
25 
26     def 喝(self):
27         # do something
28 
29     def 拉(self):
30         # do something
31 
32     def 撒(self):
33         # do something

上述代码不难看出,吃、喝、拉、撒是猫和狗都具有的功能,而我们却分别的猫和狗的类中编写了两次。如果使用 继承 的思想,如下实现:

  动物:吃、喝、拉、撒

     猫:喵喵叫(猫继承动物的功能)

     狗:汪汪叫(狗继承动物的功能)

 1 class 动物:
 2 
 3     def 吃(self):
 4         # do something
 5 
 6     def 喝(self):
 7         # do something
 8 
 9     def 拉(self):
10         # do something
11 
12     def 撒(self):
13         # do something
14 
15 # 在类后面括号中写入另外一个类名,表示当前类继承另外一个类
16 class 猫(动物):
17 
18     def 喵喵叫(self):
19         print('喵喵叫')
20         
21 # 在类后面括号中写入另外一个类名,表示当前类继承另外一个类
22 class 狗(动物):
23 
24     def 汪汪叫(self):
25         print('喵喵叫')
 1 class Animal:
 2 
 3     def eat(self):
 4         print ("%s 吃 ") %self.name
 5 
 6     def drink(self):
 7         print ("%s 喝 ") %self.name
 8 
 9     def shit(self):
10         print ("%s 拉 " )%self.name
11 
12     def pee(self):
13         print ("%s 撒 ") %self.name
14 
15 
16 class Cat(Animal):
17 
18     def __init__(self, name):
19         self.name = name
20         self.breed = ''
21 
22     def cry(self):
23         print ('喵喵叫')
24 
25 class Dog(Animal):
26     
27     def __init__(self, name):
28         self.name = name
29         self.breed = ''
30         
31     def cry(self):
32         print ('汪汪叫')
33         
34 
35 # ######### 执行 #########
36 
37 c1 = Cat('小白家的小黑猫')
38 c1.eat()
39 
40 c2 = Cat('小黑的小白猫')
41 c2.drink()
42 
43 d1 = Dog('胖子家的小瘦狗')
44 d1.eat()

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

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

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

1、Python的类可以继承多个类,Java和C#中则只能继承一个类

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

 

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

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

class D:

    def bar(self):
        print 'D.bar'


class C(D):

    def bar(self):
        print 'C.bar'


class B(D):

    def bar(self):
        print 'B.bar'


class A(B, C):

    def bar(self):
        print 'A.bar'

a = A()
# 执行bar方法时
# 首先去A类中查找,如果A类中没有,则继续去B类中找,如果B类中么有,则继续去D类中找,如果D类中么有,则继续去C类中找,如果还是未找到,则报错
# 所以,查找顺序:A --> B --> D --> C
# 在上述查找bar方法的过程中,一旦找到,则寻找过程立即中断,便不会再继续找了
a.bar()
经典类多继承
class D(object):

    def bar(self):
        print 'D.bar'


class C(D):

    def bar(self):
        print 'C.bar'


class B(D):

    def bar(self):
        print 'B.bar'


class A(B, C):

    def bar(self):
        print 'A.bar'

a = A()
# 执行bar方法时
# 首先去A类中查找,如果A类中没有,则继续去B类中找,如果B类中么有,则继续去C类中找,如果C类中么有,则继续去D类中找,如果还是未找到,则报错
# 所以,查找顺序:A --> B --> C --> D
# 在上述查找bar方法的过程中,一旦找到,则寻找过程立即中断,便不会再继续找了
a.bar()
新式类多继承

经典类:首先去A类中查找,如果A类中没有,则继续去B类中找,如果B类中么有,则继续去D类中找,如果D类中么有,则继续去C类中找,如果还是未找到,则报错

新式类:首先去A类中查找,如果A类中没有,则继续去B类中找,如果B类中么有,则继续去C类中找,如果C类中么有,则继续去D类中找,如果还是未找到,则报错

注意:在上述查找过程中,一旦找到,则寻找过程立即中断,便不会再继续找了

三、多态

我们知道,封装可以隐藏实现细节,使得代码模块化;继承可以扩展已存在的代码模块(类);它们的目的都是为了——代码重用。而多态则是为了实现另一个目的——接口重用!多态的作用,就是为了类在继承和派生的时候,保证使用“家谱”中任一类的实例的某一属性时的正确调用。

class Animal(object):
    def __init__(self, name):  # Constructor of the class
        self.name = name
 
    def talk(self):              # Abstract method, defined by convention only
        raise NotImplementedError("Subclass must implement abstract method")
 
 
class Cat(Animal):
    def talk(self):
        print('%s: 喵喵喵!' %self.name)
 
 
class Dog(Animal):
    def talk(self):
        print('%s: 汪!汪!汪!' %self.name)
 
 
 
def func(obj): #一个接口,多种形态
    obj.talk()
 
c1 = Cat('小晴')
d1 = Dog('李磊')
 
func(c1)
func(d1)
多态实例

 

posted @ 2017-08-24 15:57  爱锁屏  阅读(149)  评论(0编辑  收藏  举报