我 的 个 人 主 页:👉👉 失心疯的个人主页 👈👈
入 门 教 程 推 荐 :👉👉 Python零基础入门教程合集 👈👈
虚 拟 环 境 搭 建 :👉👉 Python项目虚拟环境(超详细讲解) 👈👈
PyQt5 系 列 教 程:👉👉 Python GUI(PyQt5)文章合集 👈👈
Oracle数据库教程:👉👉 Oracle数据库文章合集 👈👈
优 质 资 源 下 载 :👉👉 资源下载合集 👈👈
Python面向对象_类&属性
类的基本理论
什么是类
- 某一个具体对象特征的抽象
- 例如:
-
一个具体的对象
-
根据这个具体对象抽象出来的类(抽象类),其属性和行为是没有具体的值
-
类的作用
- 作用
- 根据抽象的类,生产具体的对象(属性和行为有具体的值),这些具体对象的属性值和行为值都有各自的特点
类的组成
- 组成
- 名称
- 属性
- 方法
- 注意:以上属性和方法,都是抽象的概念,没有具体值。在产生对象之后,对象才用友具体的属性值和方法实现
列举生活中的类
- 示例
# 类:钱 # 对象:1元的,5元的,10元的.... # 类:熊类 # 对象:熊大、熊二.... # 类:汽车类 # 对象:比亚迪、奥迪、大众....
对象和类的关系
- 对象和类的关系
- 对象 — 抽象 —> 类:通过对象的具体属性、行为抽象出来一个类
- 类 — 实例化 —> 对象:通过类实例化出来多个具体对象,这些对象具有相同的属性和行为(方法)
面向对象在Python中的实践
- 经典类
- 新式类
定义经典类
- 语法
class ClassName: # 类执行体 pass
根据类创建对象
- 语法
# 根据类创建对象,并赋值给变量 cl = ClassName()
创建对象时底层运作图
- 示例代码
class Money: pass one = Money() print(Money) # <class '__main__.Money'> print(Money.__name__) # 获取类名:Money # Money = 666 # Money 能被赋值,说明Money也是一个变量 # print(Money) # 666 print(one) # <__main__.Money object at 0x0000018FAAB6E640> print(one.__class__) # <class '__main__.Money'> two = Money # 将 Money 类赋值给变量 two print(two) # <class '__main__.Money'> print(two.__name__) # 获取类名:Money
- 图解
属性相关
属性和变量的区别及判断
- 概念层面
- 变量:是可以改变的量值(
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__) # {}
-
图解
-
示例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}
-
图解
查询属性
- 查询单个属性
对象.属性
- 查询所有属性
对象.__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、
- 注意事项
- 不同对象直接不能互相访问对方的属性
- 示例
# 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
语句只能删除直系属性,不能通过类删除对象的属性
- 1、不能通过
属性的内存存储
-
对象属性
-
对象属性是存放在对象的
__dict__
属性中,也可以通过__dict__
属性来进行新增和修改(一般不这么操作) -
但是,有些内置对象没有
__dict__
属性class Person: pass zs = Person() zs.name = '张三' zs.age = 36 print(zs.__dict__) # {'name': '张三', 'age': 36}
-
图解
-
那么,我们就可以通过
__dict__
这个属性来对对象的属性来进行新增和修改(一般不会这么操作)class Person: pass zs = Person() zs.__dict__ = {"name": "张三", "age": 30} print(zs.name) # 张三 print(zs.age) # 30
-
类属性
-
类对象的属性也是存放在
__dict__
属性中,但是类对象的__dict__
属性默认无法修改,需要通过set
、attr
方法修改class Person: name = '张三' age = 36 zs = Person() print(Person.__dict__) # {'__module__': '__main__', 'name': '张三', 'age': 36, ......}
-
图解
-
但是,类对象的
__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__
属性中限定的属性
- 限定之后,所有对象均只能添加类的