zoukankan      html  css  js  c++  java
  • 如何吃透Python的面向对象(OOP)

    ​本篇可乐和大家一起来吃透 Python 的面向对象,类和实例

    面向对象(OOP)

    解释:面向对象它是一种编程的思想,将现实事物抽象化为编程对象。
    举例说明:喝可乐
    ① 选择自己根据配方买对应的材料然后制作可乐,最后喝可乐。
    ② 自己去小卖部直接买可乐喝。
    第一种属于面向过程(对应到编程当中,也就是每一个步骤都需要一步一步实现)
    第二种就是面向对象,我们并不需要知道每一步是如何实现的,只需要知道最后能够喝可乐即可。

    一、类

    解释:类是面向对象的重要组成部分,类是对相同特征和行为事物的统称,是一个抽象的概念。

    ✔ 语法

    class 类名:
    实际代码

    ✔ 举例:以人为例子

    # 人有眼睛,鼻子,嘴巴这些特征。可以玩电脑,走路这些行为。
    # 代码如下:
    class Person:
        def __init__(self):
            self.eyes = "眼睛"
            self.nose = "鼻子"
            self.mouth = "嘴巴"
    ​
        def play_computer(self):
            print("我会玩电脑")
    ​
        def walk(self):
            print("我会走路")
    ​
    # self:下面会细讲,并用代码演示
    

    二、对象

    解释:对象是类创建出来真实存在的事物,对象又可以称为实例。

    ✔ 语法

    对象名 = 类名()

    ✔ 举例:以上述人为例子

    人是一个抽象的概念,并不能代表实实在在的事物,但是可乐和在座的各位同学都是实际存在的事物,我们都属于人。

    class Person:
        def __init__(self):
            self.eyes = "眼睛"
            self.nose = "鼻子"
            self.mouth = "嘴巴"
    ​
        def play_computer(self):
            print("我会玩电脑")
    ​
        def walk(self):
            print("我会走路")
            
    # 创建 kele 对象
    kele = Person()
    

    2.1 调用对象方法

    ✔ 语法

    对象.方法名(参数)

    ✔ 举例

    class Person:
        def __init__(self):
            self.eyes = "眼睛"
            self.nose = "鼻子"
            self.mouth = "嘴巴"
    ​
        def play_computer(self):
            print("我会玩电脑")
    ​
        def walk(self):
            print("我会走路")
    ​
    # 创建 kele 对象
    kele = Person()
    kele.play_computer()
    ​
    # 输出 我会玩电脑
    

    ✔ 解释实例方法中的 self 是什么

    先上代码

    class Person:
        def __init__(self):
            self.eyes = "眼睛"
            self.nose = "鼻子"
            self.mouth = "嘴巴"
    ​
        def play_computer(self):
            print("我会玩电脑")
    ​
        def eye(self):
            print(self.eyes)
            self.eyes = "卡兹然大眼睛"
            print(self.eyes)
    ​
    ​
    kele = Person()
    kele.eye()
    ​
    # 输出结果是 眼睛  卡兹然大眼睛
    ​
    ​
    class Person:
        def __init__(self):
            self.eyes = "眼睛"
            self.nose = "鼻子"
            self.mouth = "嘴巴"
    ​
        def play_computer(self):
            print("我会玩电脑")
    ​
        def eye(self):
            pass
    ​
    ​
    kele = Person()
    print(kele.eyes)
    kele.eyes = "卡兹然大眼睛"
    print(kele.eyes)
    ​
    # 输出 眼睛  卡兹然大眼睛
    

    到这里可能有一部分同学已经明白 self 实际上是个什么东东了,为了更加通俗易懂,可乐再举一个例子:

    class Person:
        def __init__(self):
            self.eyes = "眼睛"
            self.nose = "鼻子"
            self.mouth = "嘴巴"
    ​
        def play_computer(self):
            print(f"self是{self}")
    ​
    kele = Person()
    kele.play_computer()
    print(f"kele是{kele}")
    

    结果:

    根据上述两个示例,我们可以知道 self 实际上就是类创建出来的实例对象。

    ❗ 对象在调用方法的时候不需要手动传 self 值,因为 python 解释器会自动将实例引用传递给 self 。

    2.2 获取对象属性

    解释:属性就是特征。例如:人的手,人的鼻子,人的身高,人的体重。

    ✔ 语法

    ① 对象名.属性名 (这种在类外部使用)
    ② self.属性名 (这种在类内部使用)

    ✔ 举例1:还是以人为例子

    class Person:
        def __init__(self):
            self.eyes = "眼睛"
            self.nose = "鼻子"
            self.mouth = "嘴巴"
    ​
        def play_computer(self):
            print(f"self是{self}")
    ​
    ​
    kele = Person()
    print(kele.nose)
    ​
    # 输出 鼻子
    

    ✔ 举例2

    class Person:
        def __init__(self):
            self.eyes = "眼睛"
            self.nose = "鼻子"
            self.mouth = "嘴巴"
    ​
        def get_nose(self):
            print(self.nose)
    ​
    ​
    kele = Person()
    kele.get_nose()
    ​
    # 输出  鼻子
    

    2.3 修改/设置对象属性

    ✔ 语法

    ① 对象名.属性名 = 值 (这种在类外部使用)
    ② self.属性名 = 值 (这种在类内部使用)

    ✔ 举例1:依旧以人为例子

    class Person:
        def __init__(self):
            self.eyes = "眼睛"
            self.nose = "鼻子"
            self.mouth = "嘴巴"
    ​
        def play_computer(self):
            print(f"self是{self}")
    ​
    ​
    kele = Person()
    kele.nose = "卡兹然大鼻子"
    print(kele.nose)
    ​
    # 输出  卡兹然大鼻子
    

    ✔ 举例2

    class Person:
        def __init__(self):
            self.eyes = "眼睛"
            self.nose = "鼻子"
            self.mouth = "嘴巴"
    ​
        def modify_nose(self):
            self.nose = "卡兹然大鼻子"
    ​
    ​
    kele = Person()
    kele.modify_nose()
    print(kele.nose)
    ​
    # 输出  卡兹然大鼻子
    

    2.4 魔法方法

    解释:所谓的魔法方法也就是 python 内部已经提供的方法,他们的表现形式是 xxx 。

    2.4.1 魔法方法 init

    解释 init 方法它是用于对象生成之后进行初始化的函数,不需要程序员手动调用,python 解释器会在对象创建之后自动调用。
    例如:人与生俱来就有嘴巴,鼻子,眼睛。那么我们在构造类的时候,就可以将这些属性放进 init 方法中。

    ✔ 举例

    class Person:
        def __init__(self):
            self.eyes = "眼睛"
            self.nose = "鼻子"
            self.mouth = "嘴巴"
            print(self.eyes)
    ​
    ​
    kele = Person()
    ​
    # 输出 眼睛
    

    ❗ 他并不需要程序员手动调用。

    2.4.2 魔法方法 new

    解释:我们之前一直在说对象是由类创建出来的,那么类又是怎么创建出来的呢?就是通过 new 方法,这个方法的功能就是创建对象。

    ✔ 如何通过 new 方法实现单例

    解释:所谓的单例就是一个类创建出来的对象都是相同的。

    在默认情况下类创建出来的各个对象都是不一样的,如果我们想一个类创建出来的对象都是一样的,那该怎么做呢?答案就是通过 new 方法。

    ✔ 类创建不同的对象代码

    class Person:
        def __init__(self):
            self.eyes = "眼睛"
            self.nose = "鼻子"
            self.mouth = "嘴巴"
    ​
    ​
    kele1 = Person()
    kele2 = Person()
    print(kele1)
    print(kele2)
    

    结果如图:

    ✔ 单例代码

    class Person:
        instance = None
    ​
        def __new__(cls, *args, **kwargs):
            if not cls.instance:
                cls.instance = super(Person, cls).__new__(cls, *args, **kwargs)
            return cls.instance
    ​
        def __init__(self):
            self.eyes = "眼睛"
            self.nose = "鼻子"
            self.mouth = "嘴巴"
    ​
    ​
    kele1 = Person()
    kele2 = Person()
    print(kele1)
    print(kele2)
    

    先贴出结果:

    解释一下代码:

    具体代码在下面讲解完继承,类属性,类方法之后就知道什么含义了,可乐先讲一下代码的大致意思:用变量 instance 存储对象的内存地址,开始时只为 None ,当第一个对象创建之后,将该内存地址赋值给 instance 变量,后续的对象创建时判断变量 instance 是否有值了。如果有,那么将之前的对象地址给新对象。这样就保证了,后续的对象都和第一个对象的内存地址一样,即该类创建出来的对象都是同一个。

    2.5 类属性

    解释:类对象所拥有的属性,该类创建出来的所有对象共享同一个类属性,类属性在内存中只会有一个副本。

    ✔ 使用场景

    如果在一个类中所有的对象都有一个共同的属性,并且这个属性的值是一样的,那么我们就可以将属性设置为类属性,如果这个属性的值每个对象都有其自己的含义,那么我们可以将其定义为实例属性。

    ✔ 语法

    在类里面 属性名 = 值

    ✔ 举例

    class Person:
        nose = "鼻子"
    ​
        def __init__(self, name):
            self.name = name
    ​
    ​
    kele1 = Person("可乐1号")
    kele2 = Person("可乐2号")
    

    2.5.1 获取类属性

    ✔ 语法

    ① cls.属性名 (在类里面)
    ② 类.属性名 (在类外面)
    ③ 实例.属性名 (在类外面)

    ✔ 举例

    class Person:
        nose = "鼻子"
    ​
    kele = Person()
    ​
    print(kele.nose)
    print(Person.nose)
    ​
    # 输出 鼻子 鼻子
    

    2.5.2 修改类属性的值

    ✔ 语法

    ① cls.属性名 = 值 (在类里面)
    ② 类.属性名 = 值 (在类外面)

    ❗ 不可用实例.属性名 = 值来修改,这个含义代表添加实例属性。

    ✔ 举例

    class Person:
        nose = "鼻子"
    ​
    Person.nose = "卡自然大鼻子"
    print(Person.nose)
    ​
    # 输出 卡自然大鼻子
    

    2.6 类方法

    解释:类方法是类对象所拥有的方法,用 @classmethod 来对方法进行修饰。

    ✔ 使用场景

    类方法一般搭配类属性来使用,常常用于对类属性的修改。

    ✔ 语法

    @classmethod
    def 类方法名(cls):

    ✔ 举例

    class Person:
        nose = "鼻子"
    ​
        @classmethod
        def add(cls):
            pass
    

    2.6.1 调用类方法

    ✔ 语法

    ① 类.类方法名 (在类外面)
    ② 实例.类方法名 (在类外面)
    ③ cls.类方法名 (在类里面)

    ✔ 举例1

    class Person:
        nose = "鼻子"
    ​
        @classmethod
        def add(cls, nose):
            cls.nose = nose
    ​
        @classmethod
        def update(cls):
            cls.add("卡自然大鼻子")
    ​
    ​
    Person.update()
    print(Person.nose)
    ​
    # 输出 卡自然大鼻子
    

    ✔ 举例2

    class Person:
        nose = "鼻子"
    ​
        @classmethod
        def update(cls):
            cls.nose = "卡自然大鼻子"
    ​
    ​
    Person.update()
    print(Person.nose)
    ​
    # 输出 卡自然大鼻子
    

    ✔ 举例3

    class Person:
        nose = "鼻子"
    ​
        @classmethod
        def update(cls):
            cls.nose = "卡自然大鼻子"
    ​
    kele = Person()
    kele.update()
    print(kele.nose)
    ​
    # 输出 卡自然大鼻子
    

    2.7 静态方法

    解释:静态方法可以理解为就是普通的函数,只不过他的作用域限制于类里面,但是和类和实例本身并没有多大的关系,他通过 @staticmethod 来修饰。

    ✔ 使用场景

    如果想定义一个函数,但是该函数和类本身或者实例对象没有多大关系,但是限制于该类中就可以使用静态方法来定义。

    ✔ 举例

    class Person:
        @staticmethod
        def play_game():
            print("可乐打游戏")
    ​
    kele = Person()
    kele.play_game()
    ​
    # 输出 可乐打游戏
    

    三、面向对象三大特性

    特性:封装,继承,多态。

    3.1 封装

    解释:将代码写到类里面即是封装,并且封装还可以给属性或者方法设置权限。在上述代码中已经使用了封装的特性。

    3.2 继承

    解释:指的是类当中的从属关系,子类自动拥有父类所有的属性和方法。

    ❗ 所有的类都默认继承Object类。

    3.2.1 单继承

    单继承:只继承一个父类。

    ✔ 举例

    class Father:
    ​
        def __init__(self):
            self.name = "可乐家族"
    ​
        def get_name(self):
            print(self.name)
    ​
    ​
    class Son(Father):
        pass
    ​
    ​
    son = Son()
    son.get_name()
    ​
    # 输出 可乐家族
    

    3.2.2 多继承

    多继承:子类同时继承多个父类。

    ✔ 举例1

    class Father:
    ​
        def __init__(self):
            self.name = "可乐家族"
    ​
        def get_name(self):
            print(self.name)
    ​
    ​
    class Mother:
    ​
        def __init__(self):
            self.name = "妈妈家族"
    ​
        def get_name(self):
            print(self.name)
    ​
        def add_nose(self):
            self.nose = "鼻子"
    ​
    ​
    class Son(Mother, Father):
        pass
    ​
    ​
    son = Son()
    son.get_name()
    ​
    # 输出 妈妈家族
    

    ✔ 举例2

    class Father:
    ​
        def __init__(self):
            self.name = "可乐家族"
    ​
        def get_name(self):
            print(self.name)
    ​
    ​
    class Mother:
    ​
        def __init__(self):
            self.name = "妈妈家族"
    ​
        def get_name(self):
            print(self.name)
    ​
        def add_nose(self):
            self.nose = "鼻子"
    ​
    ​
    class Son(Father, Mother):
        pass
    ​
    ​
    son = Son()
    son.get_name()
    ​
    # 输出 可乐家族
    

    ❗ 如果继承的父类当中拥有相同的属性或者方法,那么优先继承第一个父类的属性和方法。

    3.2.3 mro确认继承顺序

    继承顺序:如果一个类继承多个父类,并且继承关系比较复杂,那么我们可以使用内置方法 mro 来确定继承顺序。

    ✔ 举例

    class Father:
    ​
        def __init__(self):
            self.name = "可乐家族"
    ​
        def get_name(self):
            print(self.name)
    ​
    ​
    class Mother:
    ​
        def __init__(self):
            self.name = "妈妈家族"
    ​
        def get_name(self):
            print(self.name)
    ​
        def add_nose(self):
            self.nose = "鼻子"
    ​
    ​
    class Son(Mother, Father):
        pass
    ​
    ​
    print(Son.__mro__)
    

    结果如图:
    3.2.4 重写父类的方法

    继承中,支持子类对父类的方法进行重写。

    ✔ 举例

    class Father:
    ​
        def __init__(self):
            self.name = "可乐家族"
    ​
        def get_name(self):
            print(self.name)
    ​
    ​
    class Mother:
    ​
        def __init__(self):
            self.name = "妈妈家族"
    ​
        def get_name(self):
            print(self.name)
    ​
        def add_nose(self):
            self.nose = "鼻子"
    ​
    ​
    class Son(Mother, Father):
    ​
        def get_name(self):
            print("子类重新方法")
    ​
    ​
    son = Son()
    son.get_name()
    ​
    # 输出 子类重新方法
    

    3.2.5 继承之super

    super:子类重写父类方法,但是还需要调用父类的其他方法或同名方法时,使用 super 可以不用关心继承的是哪个父类,在语法上只需要填写子类类名即可。

    ✔ 举例1

    class Father:
    ​
        def __init__(self):
            self.name = "可乐家族"
    ​
        def get_name(self):
            print(self.name)
    ​
    ​
    class Mother:
    ​
        def __init__(self):
            self.name = "妈妈家族"
    ​
        def get_name(self):
            print(self.name)
    ​
        def add_nose(self):
            self.nose = "鼻子"
    ​
    ​
    class Son(Mother, Father):
    ​
        def get_name(self):
            print("子类重新方法")
            Mother.get_name(self)
            Father.__init__(self)
            Father.get_name(self)
    ​
    ​
    son = Son()
    son.get_name()
    ​
    # 输出 子类重新方法  妈妈家族  可乐家族
    

    ✔ 举例2

    class Father:
    ​
        def __init__(self):
            self.name = "可乐家族"
    ​
        def get_name(self):
            print(self.name)
    ​
    ​
    class Mother:
    ​
        def __init__(self):
            self.name = "妈妈家族"
    ​
        def get_name(self):
            print(self.name)
            super(Mother, self).__init__()
            super(Mother, self).get_name()
    ​
        def add_nose(self):
            self.nose = "鼻子"
    ​
    ​
    class Son(Mother, Father):
    ​
        def get_name(self):
            print("子类重新方法")
            super(Son, self).get_name()
    ​
    ​
    son = Son()
    son.get_name()
    ​
    # 输出 子类重新方法 妈妈家族 可乐家族
    

    ❗ super 会自动查找父类,且顺序遵循__mro__顺序,适合单继承使用;
    ❗ super 只能继承最近的上一级父类,顺序按照__mro__顺序。

    3.3 多态

    解释:不同的对象,有不同的结果,子类重写父类的方法,并且调用不同的子类的相同父类方法,有不同的结果。

    我们先上代码来看:

    class Person:
    ​
        def get_sex(self):
            print("人")
    ​
    ​
    class Man(Person):
    ​
        def get_sex(self):
            print("男人")
    ​
    ​
    class Women(Person):
    ​
        def get_sex(self):
            print("女人")
    ​
    ​
    man = Man()
    women = Women()
    man.get_sex()
    women.get_sex()
    ​
    # 输出 男人  女人
    

    代码解释:

    一个 Person 类中有一个父类公共方法 get_sex ,子类 man 和 women 通过重写父类方法,产生不同的效果,这就是多态。那么多态有什么好处呢?多态可以使得代码变得更加灵活,更通用,适应的业务场景多。

    到此,我们在本篇中学习了 python 面向对象。各位同学在学习过程中遇到疑问可以私聊可乐,可乐看到了都会一一回复的。那么下一篇可乐将和大家看一下闭包,装饰器和深拷贝,浅拷贝。谢谢大家的支持~~~


    < END>

    在这里插入图片描述

  • 相关阅读:
    qt 自动产生 Guid 方法
    在QTableWidget中添加QCheckBox并使其居中显示(转)
    QTableWidget控件总结
    QTableWidget 使用及美化_QtableWidget_QtableView滚动条宽度及样式
    QT添加二次确认功能,QMessageBox的使用
    QTableWidget详解(样式、右键菜单、表头塌陷、多选等) 2013-10-23 10:54:04
    QTableWidget的美化
    004PHP基础知识——数据类型(一)
    laravel中修改默认时区
    laravel中Crypt加密方法
  • 原文地址:https://www.cnblogs.com/kele-develop/p/14451110.html
Copyright © 2011-2022 走看看