026.Python面向对象_类&属性

无奋斗不青春

我 的 个 人 主 页: 失心疯的个人主页
入 门 教 程 推 荐 : Python零基础入门教程合集
虚 拟 环 境 搭 建 : Python项目虚拟环境(超详细讲解)
PyQt5 系 列 教 程: Python GUI(PyQt5)文章合集
Oracle数据库教程: Oracle数据库文章合集
优 质 资 源 下 载 : 资源下载合集

分隔线

Python面向对象_类&属性

    • 类的基本理论
      • 什么是类
      • 类的作用
      • 类的组成
      • 列举生活中的类
      • 对象和类的关系
    • 面向对象在Python中的实践
      • 定义经典类
      • 根据类创建对象
      • 创建对象时底层运作图
    • 属性相关
      • 属性和变量的区别及判断
      • 对象属性
        • 增加属性
        • 查询属性
        • 修改属性
        • 删除属性
      • 类属性
        • 增加属性
        • 查询属性
        • 修改属性
        • 删除属性
        • 属性的内存存储
        • 类属性被各个对象共享
        • 类属性与对象属性之间的区别联系
      • 限制对象属性的添加:`__slots__`

类的基本理论

什么是类

  • 某一个具体对象特征的抽象
  • 例如:
    • 一个具体的对象026.Python面向对象_类&属性_第1张图片

    • 根据这个具体对象抽象出来的类(抽象类),其属性和行为是没有具体的值026.Python面向对象_类&属性_第2张图片

类的作用

  • 作用
    • 根据抽象的类,生产具体的对象(属性和行为有具体的值),这些具体对象的属性值和行为值都有各自的特点

类的组成

  • 组成
    • 名称
    • 属性
    • 方法
    • 注意:以上属性和方法,都是抽象的概念,没有具体值。在产生对象之后,对象才用友具体的属性值和方法实现

列举生活中的类

  • 示例
    # 类:钱
    # 对象:1元的,5元的,10元的....
    
    # 类:熊类
    # 对象:熊大、熊二....
    
    # 类:汽车类
    # 对象:比亚迪、奥迪、大众....
    

对象和类的关系

  • 对象和类的关系
    • 对象 — 抽象 —> 类:通过对象的具体属性、行为抽象出来一个类
    • 类 — 实例化 —> 对象:通过类实例化出来多个具体对象,这些对象具有相同的属性和行为(方法)

面向对象在Python中的实践

  • 经典类
  • 新式类

定义经典类

  • 语法
    class ClassName:
        # 类执行体
        pass
    
    

根据类创建对象

  • 语法
    # 根据类创建对象,并赋值给变量
    
    cl = ClassName()
    
    

创建对象时底层运作图

  • 示例代码
    class Money:
        pass
    
    
    one = Money()
    
    print(Money)                    # 
    print(Money.__name__)           # 获取类名:Money
    
    # Money = 666                     # Money 能被赋值,说明Money也是一个变量
    # print(Money)                    # 666
    
    print(one)                      # <__main__.Money object at 0x0000018FAAB6E640>
    print(one.__class__)            # 
    
    two = Money                     # 将 Money 类赋值给变量 two
    print(two)                      # 
    print(two.__name__)             # 获取类名:Money
    
  • 图解026.Python面向对象_类&属性_第3张图片

属性相关

属性和变量的区别及判断

  • 概念层面
    • 变量:是可以改变的量值(num = 5, num = 6)
    • 属性:是属于某个对象的特性(one.__class__
  • 访问权限
    • 变量:根据不同的位置,存在不同额访问权限(全局变量、局部变量、…)
    • 属性:只能通过对象来进行访问,必须先找到对象
      对象也是通过变量名来引用,所以对象也有对应的访问权限<全局、局部>
  • 判断依据
    • 是否存在宿主(变量没有宿主,属性有宿主)
  • 根据宿主的不同,属性分为两种:类属性对象属性

对象属性

增加属性
  • 方式1:通过对象动态添加

    对象.属性 =
  • 方式2:通过类的初始化方法(构造方法):__init__

    class ClassName:
        def __init__():
            属性1 =1
            属性2 =2
    
  • 区别

    • 通过对象动态添加的属性,仅仅只是当前对象都有这些属性
    • 通过类的初始化方法添加的属性,通过类创建的所有对象都有这些属性
  • 示例1

    # 1. 定义一个类
    class Person:
        pass
    
    
    # 2. 根据类,实例化一个对象
    zs = Person()
    zl = Person()
    
    # 3. 给zs对象增加一些属性
    zs.name = '张三'
    zs.age = 36
    
    # 4. 验证属性是否添加成功
    print(zs.name)              # 张三
    print(zs.age)               # 36
    # 查看对象的所有属性
    print(zs.__dict__)          # {'name': '张三', 'age': 36}
    
    # print(zl.name)              # AttributeError: 'Person' object has no attribute 'name'
    # print(zl.age)               # AttributeError: 'Person' object has no attribute 'age'
    print(zl.__dict__)          # {}
    
  • 图解026.Python面向对象_类&属性_第4张图片

  • 示例2

    # 1. 定义一个类
    class Person:
        # 2. 通过__init__方法添加属性
        def __init__(self):
            self.age = 38
            self.height = 140
    
    
    # 3. 根据类,实例化一个对象
    ls = Person()
    ww = Person()
    
    # 4. 验证属性是否添加成功
    print(ls.age)               # 38
    print(ls.height)            # 140
    print(ls.__dict__)          # {'age': 38, 'height': 140}
    
    print(ww.age)               # 38
    print(ww.height)            # 140
    print(ww.__dict__)          # {'age': 38, 'height': 140}
    
  • 图解026.Python面向对象_类&属性_第5张图片

查询属性
  • 查询单个属性
    对象.属性
    
  • 查询所有属性
    对象.__dict__
    
  • 示例
    # 定义一个类
    class Person:
        pass
    
    
    # 根据类,实例化一个对象
    zs = Person()
    zl = Person()
    
    # 给zs对象增加一些属性
    zs.name = '张三'
    zs.age = 36
    
    # 1. 查询单个属性
    print(zs.name)              # 张三
    print(zs.age)               # 36
    
    # 2. 查看对象的所有属性
    print(zs.__dict__)          # {'name': '张三', 'age': 36}
    
  • 访问一个属性经历的步骤
    1. 通过变量zs存储的唯一标识,找到对应的对象
    2. 再根据对象的属性name/age存储的唯一标识,找到对应的值
    
    
修改属性
  • 修改属性的时候,内部会进行判断,如果属性存在,则修改;如果属性不存在,则新增
  • 对象属性直接修改
    对象.属性 = 新值
    
    注意:当属性的值是可变类型时
    对象.属性 = 新的可变类型 ---> 属性会重新指向另一个内存
    对象.属性.append(新值) ---> 属性不会重新指向另一个内存,而是在原内存内追加一个新值
  • 示例
    # 1. 定义一个类
    class Person:
        pass
    
    
    # 2. 根据类,实例化一个对象
    zs = Person()
    
    # 3. 给zs对象增加一些属性
    zs.name = '张三'
    print(zs.name, id(zs.name))              # 张三 2036918235664
    
    zs.name = '曾帅'
    print(zs.name, id(zs.name))              # 曾帅 2036918235856
    
    # 属性值是可变类型
    zs.pets = ['小花', '小黄']
    print(zs.pets, id(zs.pets))              # ['小花', '小黄'] 2006228365440
    
    # 通过获取对象追加新值的方式,属性不会指向新的内存
    zs.pets.append('小黑')
    print(zs.pets, id(zs.pets))              # ['小花', '小黄', '小黑'] 2006228365440
    
    # 通过属性赋值一个新的可变类型值,属性会重新指向一个新的内存
    zs.pets = ['来福', '旺仔']
    print(zs.pets, id(zs.pets))              # ['来福', '旺仔'] 1870377827584
    
删除属性
  • 通过del语句删除
    # 1. 定义一个类
    class Person:
        pass
    
    
    # 2. 根据类,实例化一个对象
    zs = Person()
    
    # 3. 给zs对象增加一些属性
    zs.name = '张三'
    print(zs.name, id(zs.name))              # 张三 2036918235664
    
    # 通过del语句删除对象属性
    del zs.name                              # 删除对象的属性
    
    # 属性被删除之后,再次访问会报错
    print(zs.name, id(zs.name))              # AttributeError: 'Person' object has no attribute 'name'
    
  • 执行步骤
    • 1、del zs.name 删除zs对象的name属性
    • 2、zs对象的name属性被删除,属性指向值的链接也被断开
    • 3、如果这个值没有被其他变量引用,那么Python会自动回收这个值的内存
  • 注意事项
    • 不同对象直接不能互相访问对方的属性
  • 示例
    # 1. 定义一个类
    class Person:
        pass
    
    
    # 2. 根据类,实例化一个对象
    zs = Person()
    ls = Person()
    
    # 3. 给zs对象增加一些属性
    zs.name = '张三'
    
    ls.age = 30
    
    # print(zs.name, id(zs.name))              # 张三 2036918235664
    
    # 不同对象之间不能互相访问对方的属性
    # print(zs.age, id(zs.age))                # AttributeError: 'Person' object has no attribute 'age'
    
    
    print(ls.age, id(ls.age))                  # 30 2224037194960
    
    # 不同对象之间不能互相访问对方的属性
    print(ls.name, id(ls.name))                # AttributeError: 'Person' object has no attribute 'name'
    

类属性

  • 在Python中,万物皆对象,所以从本质上来说,类也是对象
增加属性
  • 方式1:通过对象属性赋值方式
    类名.属性 =
  • 方式2:在类内部添加变量赋值方式(常用方式)
    class ClassName:
        变量1 =1
        变量2 =2
    
    
  • 示例1
    class Person:
        pass
    
    
    p = Person()
    
    Person.age = 100
    Person.height = 160
    
    print(Person.age)               # 100
    print(Person.height)            # 160
    print(Person.__dict__)          # {'__module__': '__main__',..., 'age': 100, 'height': 160}
    print()
    
    print(p.age)                    # 100
    print(p.height)                 # 160
    print(p.__dict__)               # {}
    
  • 示例2
    class Person:
        age = 100
        height = 160
    
    
    p = Person()
    
    print(Person.age)               # 100
    print(Person.height)            # 160
    print(Person.__dict__)          # {'__module__': '__main__', 'age': 100, 'height': 160, ......}
    print()
    
    print(p.age)                    # 100
    print(p.height)                 # 160
    print(p.__dict__)               # {}
    
查询属性
  • 方式1:通过类名查询单个属性
    类名.属性
    
  • 方式2:查询所有属性
    类名.__dict__
    
  • 方式3:通过实例化的对象查询属性
    对象.属性
    
    # 注意:对象的属性查找机制
    # 优先到对象自身去查找属性,找到则结束
    # 没有找到,则根据__class__找到对象对应的类,然后到这个类里面查找属性
    
修改属性
  • 修改属性的时候,内部会进行判断,如果属性存在,则修改;如果属性不存在,则新增
  • 方式1:通过类名进行修改
    类名.属性 = 新值
    
  • 注意:属性的修改不能通过 对象.属性 = 新值 的方式进行修改
  • 原因:对象属性的修改规则,内部会判断,对象本身没有这个属性,则会给这个对象新增一个属性
  • 示例
    class Person:
        age = 100
        height = 160
    
    
    p = Person()
    
    print(Person.age)               # 100
    print(Person.height)            # 160
    print(Person.__dict__)          # {'__module__': '__main__', 'age': 100, 'height': 160, ...}
    
    print(p.age)                    # 100
    print(p.height)                 # 160
    print(p.__dict__)               # {}
    
    Person.age = 200                # 通过 类名.属性 = 新值 直接修改属性值
    p.height = 260                  # 不能通过 对象.属性 = 新值 修改类属性,因为对象没有这个属性,会直接给对象新增属性
    
    print(Person.age)               # 200
    print(Person.height)            # 160
    print(Person.__dict__)          # {'__module__': '__main__', 'age': 200, 'height': 160, ...}
    
    print(p.age)                    # 200
    print(p.height)                 # 260
    print(p.__dict__)               # {'height': 260}
    
    
删除属性
  • 通过 del 语句删除属性
    del 类名.属性
    
  • 注意:
    • 1、不能通过 del 对象.属性 的方式删除类属性
    • 2、del 语句只能删除直系属性,不能通过类删除对象的属性
属性的内存存储
  • 对象属性

  • 对象属性是存放在对象的 __dict__ 属性中,也可以通过 __dict__ 属性来进行新增和修改(一般不这么操作)

  • 但是,有些内置对象没有 __dict__ 属性

    class Person:
        pass
    
    
    zs = Person()
    
    zs.name = '张三'
    zs.age = 36
    
    print(zs.__dict__)          # {'name': '张三', 'age': 36}
    
  • 图解026.Python面向对象_类&属性_第6张图片

  • 那么,我们就可以通过__dict__这个属性来对对象的属性来进行新增和修改(一般不会这么操作)

    class Person:
        pass
    
    
    zs = Person()
    
    zs.__dict__ = {"name": "张三", "age": 30}
    
    print(zs.name)              # 张三
    print(zs.age)               # 30
    
  • 类属性

  • 类对象的属性也是存放在 __dict__ 属性中,但是类对象的 __dict__属性默认无法修改,需要通过 setattr 方法修改

    class Person:
        name = '张三'
        age = 36
    
    
    zs = Person()
    
    print(Person.__dict__)          # {'__module__': '__main__', 'name': '张三', 'age': 36, ......}
    
  • 图解026.Python面向对象_类&属性_第7张图片

  • 但是,类对象的 __dict__属性默认不允许被修改

    class Person:
        name = '张三'
        age = 36
    
    
    zs = Person()
    
    # 类对象的 __dict__属性默认不允许修改,会报错
    # Person.__dict__['name'] = '李四'      # TypeError: 'mappingproxy' object does not support item assignment
    # Person.__dict__['sex'] = '男'         # TypeError: 'mappingproxy' object does not support item assignment
    
类属性被各个对象共享
  • 类属性能被通过当前类创建的所有对象共同访问
  • 修改类属性的值之后,所有对象的当前属性的值都会发生改变
类属性与对象属性之间的区别联系
  • 新增方式
    # 类属性
        # 方式1
            类名.属性 =# 方式2
            class ClassName:
                属性1 =1
                属性2 =2
                
    # 对象属性
        # 方式1
            对象.属性 =# 方式2
            class ClassName:
                def __init__(self):
                    self.属性1 =1
                    self.属性2 =2
        # 方式3
            对象.__dict__[属性] = 值
            
            对象.__dict__ = {'属性1':1, '属性2':2}
    
  • 查询方式
    # 类属性
        # 方式1:查询单个属性
            类名.属性
            对象.属性
        # 方式2:查询所有属性
            类名.__dict__
    
    
    # 对象属性
        # 方式1:查询单个属性
            对象.属性
        # 方式2:查询所有属性
            对象.__dict__
    
  • 修改方式
    # 类属性
        # 方式1
            类名.属性 =  新值
    
    # 对象属性
        # 方式1
            对象.属性 = 新值
        # 方式2
            对象.__dict__[属性] = 新值
    
  • 删除方式
    # 类属性
        del 类名.属性
        
    # 对象属性
        del 对象.属性
    
    

限制对象属性的添加:__slots__

  • 在其他语言中,在创建类的时候,就确定了对象的属性,所有通过类创建的对象,属性都一致
  • 在Python中,对象可以随意添加和删除属性,这样就导致通过同一个对象创建出来的多个对象,每一个对象都可能有不同的属性
  • 通过类的 __slots__ 属性可以限定对象允许添加的属性
  • 语法
    class Person:
        __slots__ = ['属性1', '属性2']
    
  • 示例1:未限定前
    class Person:
        pass
    
    
    p1 = Person()
    p1.age = 30
    p1.name = '张三'
    
    p2 = Person()
    p2.height = 160
    p2.weight = 63
    
    print(p1.age)           # 30
    print(p1.name)          # 张三
    print(p2.height)        # 160
    print(p2.weight)        # 63
    
    • 没有限制前,可以通过对象随意添加属性,导致多个对象间属性不一致
  • 示例2:限定后
    class Person:
        __slots__ = ['name', 'age']
        pass
    
    
    p1 = Person()
    p1.age = 30
    p1.name = '张三'
    
    p2 = Person()
    # 添加的属性不在类的__slots__属性限定范围内,会报错
    # p2.height = 160         # AttributeError: 'Person' object has no attribute 'height'
    # p2.weight = 63          # AttributeError: 'Person' object has no attribute 'weight'
    
    p2.name = '李四'
    p2.age = 28
    
    print(p1.age)           # 30
    print(p1.name)          # 张三
    
    print(p2.age)           # 李四
    print(p2.name)          # 28
    
    • 限定之后,所有对象均只能添加类的 __slots__ 属性中限定的属性

你可能感兴趣的:(Python零基础入门,python,开发语言)