python基础之面向对象

面向对象编程

  • 面向过程编程:根据业务逻辑从上到下写代码,主要突出在流程上
  • 函数式编程:将某些功能封装在函数里,日后不用重复编写,仅调用函数即可
  • 面向对象编程:对函数进行分类和封装,让开发“更快,更好,更强

面向过程编程最易被初学者接受,其往往用一长段代码来实现指定功能,开发过程中最常见的操作就是粘贴复制,即:将之前实现的代码块复制到现需功能处。

创建类和对象

面向对象编程是一种编程范式,此编程方式的落地需要使用‘类’和‘对象’来实现,面向对象编程其实就是对‘类’和‘对象’的使用

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

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

  • class是关键字,表示类
  • 创建一个对象在类名后面加括号即可
  •  1 # 创建类(object代表基类,最大的类 包括万物)
     2 class Dog(object):
     3     def run(self):
     4         print('run')
     5 
     6     def woof(self):
     7         print('woof')
     8 
     9 # 创建对象
    10 dog = Dog()
    11 dog.run()       # 执行run方法
    12 dog.woof()      # 执行woof方法

面向对象的三大特征

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

一、封装

封装,就是把内容封装在某个地方,以后再去调用被封在某处的内容

所以,在使用封装特性时,需要:

1、将内容封装在某处

扫描二维码关注公众号,回复: 5206680 查看本文章

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

将内容封装到某处

class Foo(object):   # 创建一个Foo类 类名一般首字母大写
    def __init__(self, name, age):  # __init__为构造方法,根据类创建对象时自动执行
        self.name = name            # self 为形式参数 当执行 obj1 = Foo('wupeiqi', 18 ) 时,self 等于 obj1
        self.age = age              # 当执行 obj2 = Foo('alex', 78 ) 时,self 等于 obj2
    

# 根据Foo创建对象
# 自动执行Foo类的__init__方法
obj1 = Foo('huihui', 16)    # 将huihui和18封装到obj1的name和age属性中

# 根据Foo创建对象
# 自动执行Foo类的__init__方法
obj2 = Foo('zhowhen', 18)   # 将zhowhen和18封装的obj2的name和age属性中

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

调用某处的被封装内容

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

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

1、通过对象直接调用

class Foo(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age


obj1 = Foo('huihui', 18)
print(obj1.name)  # 直接调用obj1对象的name属性
print(obj1.age)  # 直接调用obj1对象的age属性

obj2 = Foo('zhow', 20)
print(obj2.name)  # 直接调用obj2对象的name属性
print(obj2.age)  # 直接调用obj2对象的age属性

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

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

class Foo(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def detail(self):
        print(self.name)
        print(self.age)

obj1 = Foo('huihui', 18)
obj1.detail()   # python默认会把obj1传给self参数,所有此时方法内部的self=obj1
                # 即self.name<==>obj1.name是huihui self.age<==>obj1.age是18

obj2 = Foo('zhowhen', 20)
obj2.detail()   # python默认会把obj2传给self参数,所有此时方法内部的self=obj2
                # 即self.name<==>obj2.name是zhowhen self.age<==>obj2.age是20

综上所述,对于面向对象的封装来说,其实就是使用构造方法将内容封装到 对象 中,然后通过对象直接或者self间接获取被封装的内容。

 二、继承

面向对象中的继承跟现实中的继承相同,即:子可以继承父的内容;

例如:

猫:跑,喵喵叫,吃饭

狗:跑,旺旺叫,吃饭

可以看出猫和狗有共同的行为:跑,吃饭

所以我们可以创建一个父类,里面有跑和吃饭,猫和狗只要继承了父类就也同时有个跑和吃饭

示例如下:

class Animal(object):

    def run(self):
        print('%s 在跑' % self.name)

    def eat(self):
        print('%s 在吃饭' % self.name)

class Dog(Animal):
    def __init__(self, name):
        self.name = name

    def call(self):
        print('%s旺旺叫' % self.name)


class Cat(Animal):
    def __init__(self, name):
        self.name = name

    def call(self):
        print('%s喵喵叫' % self.name)

c1 = Cat('小红的小花猫')
d1 = Dog('小明的哈巴狗')

c1.run()
d1.eat()

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

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

 so,是否可以继承多个呢?

yes,python的类可以继承多个类,Java和C#只能继承一个类

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

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

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

 

python3中都是新式类

 1 class D(object):
 2 
 3     def bar(self):
 4         print('D.bar')
 5 
 6 
 7 class C(D):
 8 
 9     def bar(self):
10         print('C.bar')
11 
12 
13 class B(D):
14 
15     def bar(self):
16         print('B.bar')
17 
18 
19 class A(B, C):
20 
21     def bar(self):
22         print('A.bar')
23 
24 a = A()
25 # 执行bar方法时
26 # 首先去A类中查找,如果A类中没有,则继续去B类中找,如果B类中么有,则继续去C类中找,如果C类中么有,则继续去D类中找,如果还是未找到,则报错
27 # 所以,查找顺序:A --> B --> C --> D
28 # 在上述查找bar方法的过程中,一旦找到,则寻找过程立即中断,便不会再继续找了
29 a.bar()

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

三、多态

Pyhon不支持Java和C#这一类强类型语言中多态的写法,但是原生多态,其Python崇尚“鸭子类型”。

 1 class F1:
 2     pass
 3 
 4 
 5 class S1(F1):
 6 
 7     def show(self):
 8         print 'S1.show'
 9 
10 
11 class S2(F1):
12 
13     def show(self):
14         print 'S2.show'
15 
16 
17 # 由于在Java或C#中定义函数参数时,必须指定参数的类型
18 # 为了让Func函数既可以执行S1对象的show方法,又可以执行S2对象的show方法,所以,定义了一个S1和S2类的父类
19 # 而实际传入的参数是:S1对象和S2对象
20 
21 def Func(F1 obj):
22     """Func函数需要接收一个F1类型或者F1子类的类型"""
23     
24     print obj.show()
25     
26 s1_obj = S1()
27 Func(s1_obj) # 在Func函数中传入S1类的对象 s1_obj,执行 S1 的show方法,结果:S1.show
28 
29 s2_obj = S2()
30 Func(s2_obj) # 在Func函数中传入Ss类的对象 ss_obj,执行 Ss 的show方法,结果:S2.show
View Code
 1 class F1:
 2     pass
 3 
 4 
 5 class S1(F1):
 6 
 7     def show(self):
 8         print 'S1.show'
 9 
10 
11 class S2(F1):
12 
13     def show(self):
14         print 'S2.show'
15 
16 def Func(obj):
17     print obj.show()
18 
19 s1_obj = S1()
20 Func(s1_obj) 
21 
22 s2_obj = S2()
23 Func(s2_obj) 
View Code

类和对象在内存中是如何保存?

 

猜你喜欢

转载自www.cnblogs.com/zhowhen/p/10397138.html