Python-面向对象

# 开闭原则 对扩展开放,对修改关闭

面向对象

  组织和构建代码逻辑的一种思路,面向对象是主流的一种编程范式而已,还有面向过程和面向函数编程范式,但在在Python中面向对象最为彻底,一切皆对象

 

与类相关的概念

  类、实例 、类方法、类变量、实例方法、实例变量

 

类相关的关键字 class @ staricmethod classmethod property setter

 

类考虑的主体是什么?

  1. 类考虑的是群体与群体的统计数据和公共行为

  2. 对象考虑单个个体的特征数据和行为

 

什么是抽象?

  移除细节,看主干,从众多的事物中抽出共同的、本质性的特征,舍弃其非本质的特征,总体归结4个字: 提取共性 

 

类的作用是什么?

  1. 封装和组织代码架构

  2. 只定义不运行,一个模块一个或多个类,通过导入实例化使用

 

什么是类?

  人以类聚,物以群分。考虑的是群体的特征,把群体的特征抽象出来形成单独的类,依据有的群体有那就其他的群体没有的界限进行群体分类,这就是类。

 

什么是实例?

  我们不一样,这就说明同时身为人类这个大类,但我们身上的具体特征属性各不相同,也就是通过差异化数据填充到类中,从而实现实例化,考虑的是类中单个个体的具体的特性数据和行为,是一种粒度比类小的一种抽象

 

什么是类变量?

  群体相关的统计特征数据,每个实例都共享这个数据

 

什么是类方法?

  群体都具有的行为,可以对群体特征数据进行操作

 

什么是实例变量?

  单个个体的特征数据,也是一种抽象,粒度比较小的抽象,通过填充不同的数据值,生成完全不同的实例对象

 

什么是实例方法?

  单个个体的特征行为,对个体实例变量进行操作,是粒度比较小的抽象,赋予实例对象行为

 

Python 类整体架构 

class ExtendClass:
    pass


class ClassName(ExtendClass):
    """通过实例变量和实例方法前加 _ 前缀约定为私有"""

    # 类变量
    class_variable = class_value

    def __init__(self):
        """初始化实例变量"""
        # 调用父类中析构函数
        super().__init__()
        # 私有属性,约定外部不可访问
        _variable = object_value
        # 公有属性,外部可以访问
        variable = object_value
        pass

    def func(self):
        """公有实例方法,约定外部可访问"""
        pass

    def _func(self):
        """私有实例方法,约定外部不可方法"""
        # 调用父类方法
        super().func()
        pass

    def __func__(self):
        """Python协议又被称为魔法方法,给对象增强属性,重要的鸭子类型的实现"""
        pass

    @classmethod
    def func(cls):
        """类方法,有个@classmethod装饰器,只能访问类变量"""
        pass

    @staticmethod
    def func():
        """静态方法,不需要访问任何类变量和实例变量"""
        pass

    @property
    def func(self):
        """调用属性一样调用方法"""
        pass

  # 这只是类的架构图(伪代码)

 

类名命名规范:

  1. 遵循变量名命名规范

  2. 驼峰命名方式,首字母大写并且通过首字母大写区分单词

 

类变量和类方法特性

  1. 同类的实例共享

  2. 通过类方法进行访问和修改,当前也可以直接访问

class BeiMenChuiXue:
    object_number = 0

    @classmethod
    def add_one_object(cls):
        cls.object_number += 1

    @classmethod
    def get_object_number(cls):
        return cls.object_number


if __name__ == '__main__':
    bei_men_chui_xue = BeiMenChuiXue()
    BeiMenChuiXue.add_one_object()
    xi_men_chui_feng = BeiMenChuiXue()
    BeiMenChuiXue.add_one_object()
    # 通过类名和方法访问
    print(BeiMenChuiXue.get_object_number())
    print(BeiMenChuiXue.get_object_number())
    # 通过直接访问
    print(BeiMenChuiXue.object_number)
    print(bei_men_chui_xue.__class__.object_number)
    # 也可以通过实例访问,这个根实例属性查找策略相关
    print(bei_men_chui_xue.get_object_number())

  

析构函数和实例方法特性

  1. 当实例化对象的时候,会自动调用__init__函数,不需要显式调用

  2. 如果显示调用__init__函数则相当于普通函数,除了能返回None,其他都不能返回

  3. 如果__init__传递参数,则实例化对象的时候需要传递参数,约定实例变量和形参同名

  4. 定义实例方法的时候,self必须作为第一个参数,其实是当前调用实例本身,Python中显胜于隐原则

  5. 通过添加 _前缀约定为私有

class BeiMenChuiXue:
    def __init__(self, name, age):
        self.name = name
        self.age = age
        self._country = None

    def get_name(self):
        return self.name

    def get_age(self):
        return self.name

    def _get_country(self):
        return self._country

    def set_country(self, country):
        if country == self._get_country():
            pass
        else:
            self._country = country

    def user_country(self):
        return self._country


if __name__ == '__main__':
    bei_men_chui_xue = BeiMenChuiXue(name="北门吹雪", age=18)
    print(bei_men_chui_xue.get_age())
    print(bei_men_chui_xue.get_name())
    bei_men_chui_xue.set_country("中国")
    print(bei_men_chui_xue.user_country())

 

其实本质上,通过__双下划线进行约束实例变量和方法为私有方法,Python会将这个变量或实例方法前添加了__ClassName前缀,本质上还是能访问到的

class BeiMenChuiXue:

    # def __get_name(self):
    #     print("北门吹雪")
    def __init__(self, name):
        self.__name = name


if __name__ == '__main__':
    bei_men_chui_xue = BeiMenChuiXue("北门吹雪")
    print(vars(bei_men_chui_xue))
    print(bei_men_chui_xue._BeiMenChuiXue__name)

 

使用类的过程

  1. 定义类

  2. 实例类

  3. 调用实例方法或类方法

 

相关概念理清:

  1. 成员函数就是实例方法

  2. 成员变量就是实例变量

 

静态方法

  属于这个类的一部分,不访问类变量和实例变量的方法

class BeiMenChuiXue:
    country = None

    def __init__(self, name):
        self.name = name

    @staticmethod
    def go_hello():
        print("Hello World!")


if __name__ == '__main__':
    bei_men_chui_xue = BeiMenChuiXue("北门吹雪")
    bei_men_chui_xue.go_hello()

  

属性方法

  可以像访问属性和属性赋值访问实例方法,必须先定义 property方法才能定义 setter方法,在 property方法的基础上, 以 property装饰的函数为基础

class BeiMenChuiXue:
    country = None

    def __init__(self, name):
        self.name = name

    @property
    def get_name(self):
        return self.name

    @get_name.setter
    def set_name(self, new_name):
        self.name = new_name
        pass


if __name__ == '__main__':
    bei_men_chui_xue = BeiMenChuiXue("北门吹雪")
    bei_men_chui_xue.set_name = "beimenchuixue"
    print(bei_men_chui_xue.get_name)

Python super查找路径  

  super其实本质上和父类没有一点关系,查找__mro__属性(类名.mor())的下一个类,只要其中一个属性或多个属性符合,则调用这个类的方法和实例变量,而不再调用其他类中__init__方法,需要核心注意,并不是完全继承。

class Student:
    def __int__(self, age, school):
        self.name = age
        self.school = school


class Person:
    def __init__(self, name, skin):
        self.name = name
        self.skin = skin


class BeiMenChuiXue(Person, Student):
    def __init__(self, name, skin, age, school):
        print(BeiMenChuiXue.__mro__)
        # 这句会报错,因为 满足 name 和 skin的类是 Person类,就调用Person的析构函数__init__
        # 但是Person的析构函数__init__没有对age和school进行初始化,所以报参数给多的错误
        super().__init__(name, skin, age, school)


if __name__ == '__main__':
    bei_men_chui_xue = BeiMenChuiXue(name="北门吹雪", skin='yellow', age=19, school="Python")
    print(vars(bei_men_chui_xue))

面向对象三大特性

  1. 封装, 类变量、实例变量、类方法、实例方法放在了一个类中

  2. 继承,Python支持多继承,不推荐,推荐使用单继承树,多继承使用Minix思想继承,继承的类之间完全隔离不相干

  3. 多态,Python通过鸭子类型实现多态,上面的属性方法也是多态的一种,但更多的是Python协议实现多态,也被称为魔法方法

经验:

  1. 类将数据和数据的操作放在了一起,刻画某些事物的特性,总体上是一种抽象,核心为特征和行为,考虑的方式是群体与群体的划分

  2. 实例对象是类中个体与个体之间的抽象,同填充具体的数据生成具体的个体对象

  3. 约定属性前面添加一个下划线为私有属性,虽然双下划线也可以,但很多的优秀的库都是如此写的,Python并没有真正意义上限制属性的访问

  4. 变量刻画特征,方法刻画行为并改变特征变量

  5. 类查找相关变量首先找实例变量,然后找类变量,最后去父类中去找,约定按 __mro__顺序找

  6. 封装最基本的原则,接收定义复杂不接受调用复杂

原文地址:https://www.cnblogs.com/2bjiujiu/p/9139600.html