一、面向对象三大特性
封装
将属性和方法书写到类的里面的操作即为封装
封装可以为属性和方法添加私有权限
继承 (实现代码的重用,相同的代码不需要重复的编写)
子类默认继承父类的所有属性和方法
子类可以重写父类属性和方法
多态
不同的 子类对象 调用相同的 父类方法,产生不同的执行结果
传入不同的对象,产生不同的结果
二、类结构
2.1 术语—实例
使用面相对象开发,第 1 步 是设计 类
使用 类名() 创建对象,创建对象 的动作有两步:
在内存中为对象 分配空间
调用初始化方法 __init__ 为 对象初始化
3.对象创建后,内存 中就有了一个对象的 实实在在 的存在 —— 实例
因此,通常也会把:
创建出来的 对象 叫做 类 的 实例
创建对象的 动作 叫做 实例化
对象的属性 叫做 实例属性
对象调用的方法 叫做 实例方法
在程序执行时:
对象各自拥有自己的 实例属性
调用对象方法,可以通过 self.
访问自己的属性
调用自己的方法
结论
每一个对象 都有自己 独立的内存空间,保存各自不同的属性
多个对象的方法,在内存中只有一份,在调用方法时,需要把对象的引用 传递到方法内部
2.2 类是一个特殊的对象
Python 中 一切皆对象:
class A: 定义的类属于 类对象
obj = A() 属于 实例对象
在程序运行时,类 同样 会被加载到内存
在 Python 中,类 是一个特殊的对象 —— 类对象
在程序运行时,类对象 在内存中 只有一份,使用 一个类 可以创建出 很多个对象实例
除了封装 实例 的 属性 和 方法外,类对象 还可以拥有自己的 属性 和 方法
类属性
类方法
通过 类名. 的方式可以 访问类的属性 或者 调用类的方法
三、类属性和实例属性
3.1 类属性(两种访问方式)
类属性 就是给 类对象 中定义的 属性
通常用来记录 与这个类相关 的特征
类属性 不会用于记录 具体对象的特征
3.1.1 设置和访问类属性
1)设置类属性
类属性就是 类对象 所拥有的属性,它被 该类的所有实例对象 所共有。
属性 = 值
2)访问类属性
类属性可以使用 类对象 或 实例对象 访问。
类名.类属性
对象.类属性 (不推荐)
注意
- 如果使用
对象.类属性 = 值
赋值语句,只会 给对象添加一个属性,而不会影响到 类属性的
# 1. 定义类,定义类属性 class Dog(object): tooth = 10 # 设置类属性 # 2. 创建对象 wangcai = Dog() xiaohei = Dog() # 3. 访问类属性(两种方法): 类和对象 print(Dog.tooth) # 10 print(wangcai.tooth) # 10 print(xiaohei.tooth) # 10
类属性的优点
记录的某项数据 始终保持一致时,则定义类属性。
实例属性 要求 每个对象 为其 单独开辟一份内存空间 来记录数据,而 类属性 为全类所共有 ,仅占用一份内存,更加节省内存空间。
3.1.2 修改类属性(一种修改方式)
类属性只能通过类对象修改,不能通过实例对象修改,如果通过实例对象修改类属性,表示的是创建了一个实例属性。
在类外部修改类属性
类名.类属性 = 值 # 修改类属性
class Dog(object): tooth = 10 wangcai = Dog() xiaohei = Dog() # 修改类属性 Dog.tooth = 12 print(Dog.tooth) # 12 print(wangcai.tooth) # 12 print(xiaohei.tooth) # 12 # 不能通过对象修改属性,如果这样操作,实则是创建了一个实例属性 wangcai.tooth = 20 print(Dog.tooth) # 12 print(wangcai.tooth) # 20 print(xiaohei.tooth) # 12
3.2 实例属性
实例属性:描述事物的特征。
class Dog(object): def __init__(self): self.age = 5 def info_print(self): print(self.age) wangcai = Dog() print(wangcai.age) # 5 # print(Dog.age) # 报错:实例属性不能通过类访问 wangcai.info_print() # 5
四、类方法和静态方法
4.1 类方法(两种访问方式)
4.1.1 类方法语法
- 类方法就是针对类对象定义的方法
- 在 类方法 内部可以直接访问 类属性 或者调用其他的 类方法
语法如下
@classmethod def 类方法名(cls): pass
类方法需要用 修饰器 @classmethod 来标识,告诉解释器这是一个类方法
类方法的 第一个参数 应该是 cls
由 哪一个类 调用的方法,方法内的 cls 就是 哪一个类的引用
这个参数和 实例方法 的第一个参数是 self 类似
提示 使用其他名称也可以,不过习惯使用 cls
4.1.2 类方法特点
需要用装饰器@classmethod来标识其为类方法,对于类方法,第一个参数必须是类对象,一般以cls作为第一个参数。
在方法内部
可以通过 cls. 访问类的属性
也可以通过 cls. 调用其他的类方法
4.1.3 类方法使用场景
当方法中 需要使用类对象 (如访问私有类属性等)时,定义类方法
类方法一般和类属性配合使用
调用类方法(两种)
类名.类方法() # 不需要传递 cls 参数
对象名.类方法()
# 1. 定义类:私有类属性,类方法获取这个私有类属性 class Dog(object): __tooth = 10 # 定义私有类属性 # 定义类方法 @classmethod def get_tooth(cls): # cls指代Dog这个类 return cls.__tooth # 2. 创建对象,调用类方法 wangcai = Dog() result = wangcai.get_tooth() print(result) # 10 result = Dog.get_tooth() print(result) # 10
4.2 静态方法(两种访问方式)
4.2.1 静态方法语法
- 在开发时,如果需要在类中封装一个方法,这个方法:
- 既 不需要 访问 实例属性 或者调用 实例方法
- 也 不需要 访问 类属性 或者调用 类方法
- 这个时候,可以把这个方法封装成一个 静态方法
语法如下
@staticmethod def 静态方法名(): pass
静态方法 需要用 修饰器 @staticmethod 来标识,告诉解释器这是一个静态方法
通过 类名. 调用 静态方法
4.2.2 静态方法特点
需要通过装饰器@staticmethod来进行修饰,静态方法既不需要传递类对象也不需要传递实例对象(形参没有self/cls)。
静态方法 也能够通过 实例对象 和 类对象 去访问。
类名.静态方法名()
对象名.静态方法名()
4.2.3 静态方法使用场景
- 当方法中 既不需要使用实例对象(如实例对象,实例属性),也不需要使用类对象 (如类属性、类方法、创建实例等)时,定义静态方法
- 取消不需要的参数传递,有利于 减少不必要的内存占用和性能消耗
# 1. 定义类,定义静态方法 class Dog(object): @staticmethod def info_print(): print('这是一个静态方法') # 2. 创建对象 wangcai = Dog() # 3. 调用静态方法:类 和 对象 wangcai.info_print() # 这是一个静态方法 Dog.info_print() # 这是一个静态方法
五、总结
- 面向对象三大特性
- 封装
- 继承
- 多态
- 类属性
- 归属于类对象的属性,所有对象共有的属性
- 实例属性
- 类方法
@classmethod def xx(): 代码
- 静态方法
@staticmethod def xx(): 代码