欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

面向对象基础篇

程序员文章站 2022-04-28 14:09:20
面向对象的基本格式 1 # ###### 定义类 ###### 2 class 类名: 3 def 方法名(self,name): 4 print(name) 5 return 123 6 def 方法名(self,name): 7 print(name) 8 return 123 9 def 方法 ......

面向对象的基本格式

 1 # ###### 定义类 ###### 
 2 class 类名:
 3     def 方法名(self,name):
 4         print(name)
 5         return 123
 6     def 方法名(self,name):
 7         print(name)
 8         return 123
 9     def 方法名(self,name):
10         print(name)
11         return 123
12 # ###### 调用类中的方法 ###### 
13 # 1.创建该类的对象
14 obj = 类名()
15 # 2.通过对象调用方法
16 result = obj.方法名('alex')
17 print(result)

应用场景:遇到很多函数,需要给函数进行归类和划分

创建类与对象

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

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

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

面向对象基础篇

  • class是关键字,表示类
  • 创建对象,类名称后加括号即可

ps:类中的函数第一个参数必须是self(详细见:类的三大特性之封装)
   类中定义的函数叫做 “方法”

 1 # 创建类
 2 class foo:
 3      
 4     def bar(self):
 5         print 'bar'
 6  
 7     def hello(self, name):
 8         print 'i am %s' %name
 9  
10 # 根据类foo创建对象obj
11 obj = foo()
12 obj.bar()            #执行bar方法
13 obj.hello('wupeiqi') #执行hello方法

面向对象的三大特性

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

一、封装

封装,顾名思义就是将内容封装到某个地方,以后再去调用被封装在某处的内容。

所以,在使用面向对象的封装特性时,需要:

  • 将内容封装到某处
  • 从某处调用被封装的内容

第一步:将内容封装到某处

面向对象基础篇

 self 是一个形式参数,当执行 obj1 = foo('wupeiqi', 18 ) 时,self 等于 obj1

                              当执行 obj2 = foo('alex', 78 ) 时,self 等于 obj2

所以,内容其实被封装到了对象 obj1 和 obj2 中,每个对象中都有 name 和 age 属性,在内存里类似于下图来保存。

面向对象基础篇

第二步:从某处调用被封装的内容

调用被封装的内容时,有两种情况:

  • 通过对象直接调用
  • 通过self间接调用

1、通过对象直接调用被封装的内容

上图展示了对象 obj1 和 obj2 在内存中保存的方式,根据保存格式可以如此调用被封装的内容:对象.属性名

 1 class foo:
 2  
 3     def __init__(self, name, age):
 4         self.name = name
 5         self.age = age
 6  
 7 obj1 = foo('wupeiqi', 18)
 8 print obj1.name    # 直接调用obj1对象的name属性
 9 print obj1.age     # 直接调用obj1对象的age属性
10  
11 obj2 = foo('alex', 73)
12 print obj2.name    # 直接调用obj2对象的name属性
13 print obj2.age     # 直接调用obj2对象的age属性

2、通过self间接调用被封装的内容

执行类中的方法时,需要通过self间接调用被封装的内容

 1 class foo:
 2   
 3     def __init__(self, name, age):
 4         self.name = name
 5         self.age = age
 6   
 7     def detail(self):
 8         print self.name
 9         print self.age
10   
11 obj1 = foo('wupeiqi', 18)
12 obj1.detail()  # python默认会将obj1传给self参数,即:obj1.detail(obj1),所以,此时方法内部的 self = obj1,即:self.name 是 wupeiqi ;self.age 是 18
13   
14 obj2 = foo('alex', 73)
15 obj2.detail()  # python默认会将obj2传给self参数,即:obj1.detail(obj2),所以,此时方法内部的 self = obj2,即:self.name 是 alex ; self.age 是 78

举个例子(面向对象与面向函数)

练习一:在终端输出如下信息

  • 小明,10岁,男,上山去砍柴
  • 小明,10岁,男,开车去东北
  • 小明,10岁,男,最爱大保健
  • 老李,90岁,男,上山去砍柴
  • 老李,90岁,男,开车去东北
  • 老李,90岁,男,最爱大保健
  • 老张...

面向函数编程

 1 def kanchai(name, age, gender):
 2     print "%s,%s岁,%s,上山去砍柴" %(name, age, gender)
 3 
 4 
 5 def qudongbei(name, age, gender):
 6     print "%s,%s岁,%s,开车去东北" %(name, age, gender)
 7 
 8 
 9 def dabaojian(name, age, gender):
10     print "%s,%s岁,%s,最爱大保健" %(name, age, gender)
11 
12 
13 kanchai('小明', 10, '男')
14 qudongbei('小明', 10, '男')
15 dabaojian('小明', 10, '男')
16 
17 
18 kanchai('老李', 90, '男')
19 qudongbei('老李', 90, '男')
20 dabaojian('老李', 90, '男')
21 
22 函数式编程
class foo:
    
    def __init__(self, name, age ,gender):
        self.name = name
        self.age = age
        self.gender = gender

    def kanchai(self):
        print "%s,%s岁,%s,上山去砍柴" %(self.name, self.age, self.gender)

    def qudongbei(self):
        print "%s,%s岁,%s,开车去东北" %(self.name, self.age, self.gender)

    def dabaojian(self):
        print "%s,%s岁,%s,最爱大保健" %(self.name, self.age, self.gender)


xiaoming = foo('小明', 10, '男')
xiaoming.kanchai()
xiaoming.qudongbei()
xiaoming.dabaojian()

laoli = foo('老李', 90, '男')
laoli.kanchai()
laoli.qudongbei()
laoli.dabaojian()

面向对象

继承

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

例如:

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

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

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

 

class 猫:

    def 喵喵叫(self):
        print '喵喵叫'

    def 吃(self):
        # do something

    def 喝(self):
        # do something

    def 拉(self):
        # do something

    def 撒(self):
        # do something

class 狗:

    def 汪汪叫(self):
        print '喵喵叫'

    def 吃(self):
        # do something

    def 喝(self):
        # do something

    def 拉(self):
        # do something

    def 撒(self):
        # do something

伪代码

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

注:除了子类和父类的称谓,你可能看到过 派生类 和 基类 ,他们与子类和父类只是叫法不同而已。

面向对象基础篇

学习了继承的写法之后,我们用代码来是上述阿猫阿狗的功能:

class animal:

    def eat(self):
        print "%s 吃 " %self.name

    def drink(self):
        print "%s 喝 " %self.name

    def shit(self):
        print "%s 拉 " %self.name

    def pee(self):
        print "%s 撒 " %self.name


class cat(animal):

    def __init__(self, name):
        self.name = name
        self.breed = '猫'

    def cry(self):
        print '喵喵叫'

class dog(animal):
    
    def __init__(self, name):
        self.name = name
        self.breed = '狗'
        
    def cry(self):
        print '汪汪叫'
        

# ######### 执行 #########

c1 = cat('小白家的小黑猫')
c1.eat()

c2 = cat('小黑的小白猫')
c2.drink()

d1 = dog('胖子家的小瘦狗')
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类中找,如果还是未找到,则报错

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

三、多态 

 pyhon不支持java和c#这一类强类型语言中多态的写法,但是原生多态,其python崇尚“鸭子类型”。

class f1:
    pass


class s1(f1):

    def show(self):
        print 's1.show'


class s2(f1):

    def show(self):
        print 's2.show'


# 由于在java或c#中定义函数参数时,必须指定参数的类型
# 为了让func函数既可以执行s1对象的show方法,又可以执行s2对象的show方法,所以,定义了一个s1和s2类的父类
# 而实际传入的参数是:s1对象和s2对象

def func(f1 obj):
    """func函数需要接收一个f1类型或者f1子类的类型"""
    
    print obj.show()
    
s1_obj = s1()
func(s1_obj) # 在func函数中传入s1类的对象 s1_obj,执行 s1 的show方法,结果:s1.show

s2_obj = s2()
func(s2_obj) # 在func函数中传入ss类的对象 ss_obj,执行 ss 的show方法,结果:s2.show

python伪代码实现java或c#的多态

总结

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

  • 面向对象是一种编程方式,此编程方式的实现是基于对  和 对象 的使用
  • 类 是一个模板,模板中包装了多个“函数”供使用
  • 对象,根据模板创建的实例(即:对象),实例用于调用被包装在类中的函数
  • 面向对象三大特性:封装、继承和多态