文章目录
- 定义
- 类 - 事物的共同属性
- 声明类
- 使用类
- 对象
- 实例化对象
- 使用对象
- 类的组合
- 面向对象的三态 - 继承、多态、封装
- 继承
- 如何继承
- 定义类时, 使用父类方法
- 继承逻辑 和 继承顺序
- 调用顺序示例
- 封装
- 如何封装
- 调用顺序示例
- 多态
- 命名空间
- 类对象指针
定义
- 面向对象的思想就是把事物归类, 标准化
- 模具 - 类; 根据模具生产的产品 - 对象
- 造模具 - 面向对象; 造产品 - 实例化
类 - 事物的共同属性
声明类
# 类名为 X
class X:
# 静态属性
a = '静态属性'
# 动态属性
def funcA(self):
return '动态属性'
使用类
""" 一般情况下, 类名不直接调用方法 """
# 添加属性
X.b = 10
print(X.__dict__)
# 查看属性
print(X.b)
# 设置属性
X.a = 100
print(X.a)
# 删除属性
del X.b
print(X.__dict__)
对象
实例化对象
""" 创造具有共同属性的具体事物 """
class X():
"""
将对象作为第一个参数self, 并将其他参数传给__init__方法,
自动执行__init__方法中的代码
自动把self作为返回值, 返回给对象
__init__方法可以不写, 默认会执行无额外参数方法
"""
def __init__(self, name, age):
self.name = name
self.age = age
# 这就是实例化
x = X("Tom", 18)
使用对象
# 查看单独属性
print(x.name)
# 查看全部属性
print(x.__dict__)
# 修改属性
x.name = "Tim"
print(x. name)
# 删除属性
del x.name
print(x.__dict__)
类的组合
- 在一个类中以另外一个类的对象作为数据属性,称为类的组合
- 描述一种 什么中有什么 的关系, 比如: 圆环内有圆
""" 计算圆环面积 """
class C:
def __init__(self, r):
self.r = r
# 这个装饰器可以使在外部调用方法的时候, 不加括号, 视觉像是调用属性
@property
def s(self):
return 3.14*self.r**2
class R:
def __init__(self, r1, r2):
self.c1 = C(r1)
self.c2 = C(r2)
def s(self):
# 由于 C 类中增加了装饰器, 所以直接 self.c1.s 即可, 不需要 self.c1.s()
return self.c1.s - self.c2.s
# 实例化一个圆环
r = R(2, 1)
# 求的面积
print(r.s())
面向对象的三态 - 继承、多态、封装
继承
- 新建的类可以继承一个或多个父类
- 父类: 又称为基类或超类
- 子类: 又称为派生类
- 单继承: 只有一个父类; 多继承: 有多个父类
如何继承
class A: pass
class B: pass
# 单继承
class C(A): pass
# 多继承
class C(A, B): pass
定义类时, 使用父类方法
class X:
a = 10
def funcX(self):
print("a")
# Y 继承 X, 父类.方法调用, 需要传参 self
class Y(X):
# 直接指定类.属性, 不需要继承即可使用
b = X.a
# 方法也一样
def funcY(self):
# 这里使用需要传参
X.funcX(self)
# Z 继承 X, 用super().方法调用, 不需要传参
class Z(X):
c = 30
def funcZ(self):
# 这里使用 X 的方法就不需要传参
super().funcX()
继承逻辑 和 继承顺序
- 找对象的内存空间 - 找对应类的内存空间 - 找父类的内存空间
- 创建一个对象, 初始化, 本身没有的初始化函数, 则找父类的初始化函数
- 遵循广度优先算法
# 钻石继承, 溯源顺序 D -> B -> C -> A
class A:pass
class B(A):pass
class C(A):pass
class D(B,C):pass
# 乌龟继承, 溯源顺序 F -> D -> B -> E -> C -> A
class A:pass
class B(A):pass
class C(A):pass
class D(B):pass
class E(C):pass
class F(D,E):pass
# 查看向上继承顺序
print(F.mro())
调用顺序示例
"""
调用流程
1. 实例化一个 B 类, 执行 a.a()
2. a 对象中没有 a(), B 类中没有 a(), A 类中有 a(), 执行 A 类中的 a()
3. 执行 self.p()
4. a 对象中没有 p(), B 类中有 p(), 执行 B 类中的 p()
5. 输出 from B
"""
class A:
def p(self):
print('from A')
def a(self):
self.p()
class B(A):
def p(self):
print('from B')
a = B()
a.a() # from B
封装
如何封装
"""
广义的封装: 把变量和函数都放在类中
狭义的封装: 把变量和方法隐藏起来, 不对外公开, 只在内部引用
"隐藏"严格意义上仅仅是一种变型操作, 变形为 objName._className__attrName
"""
class Stu:
def __init__(self, name, mathScore, chineseScore):
# 模拟公共属性
self.name = name
# 模拟私有属性
self.__mathScore = mathScore
self.__chineseScore = chineseScore
# 定义公共方法, 用于查看私有属性
def get_math_score(self):
return self.__mathScore
# 私有方法
def __whole_score(self):
return self.__mathScore + self.__chineseScore
# 定义公共方法, 用于执行私有方法
def get_whole_score(self):
return self.__whole_score()
# 实例化
s = Stu("Tom", 99, 100)
# 查看公共属性
print(s.name)
# 推荐使用公共方法查看私有属性
print(s.get_math_score())
# 查看私有属性也可以使用 objName._className__attrName
print(s._Stu__mathScore)
# 推荐使用公共方法执行私有方法
print(s.get_whole_score())
调用顺序示例
""" 序号顺序即为执行顺序 """
class Foo:
# 3. 找到 Foo 中的 __init__(), 并执行
# 4. 需要执行 self.__func(), 由于是私有方法, 翻译后为 _Foo__func(), 回到 Son 类中
def __init__(self):
self.__func()
# 6. 找到 _Foo__func(), 执行并拿到结果
def __func(self):
print('in Foo')
class Son(Foo):
# 2. 需要执行 __init__(), 因为 Son 中没有 __init__(), 去父类 Foo 中寻找
# 5. 没有找到_Foo__func(), 再去父类中寻找
def __func(self):
print('in Son')
# 1. 实例化一个 Son 的对象
s = Son()
多态
- python中, 处处都是多态
命名空间
- 调用顺序永远遵循命名空间的查找顺序
- 命名空间
- 全局命名空间
- 临时命名空间(局部命名空间), 当函数执行完毕时, 临时命名空间消失
- 内置命名空间
- 取值顺序(始终)
局部命名空间(函数执行时) --> 全局命名空间 --> 内置命名空间 - 加载顺序(始终)
与取值相反
类对象指针
- 在创建对象时, 会产生对象和类的联系, 称为类对象指针
- 对象能通过类对象指针找到类, 但是类不能通过类对象指针找到对象