文章目录

  • 定义
  • 类 - 事物的共同属性
  • 声明类
  • 使用类
  • 对象
  • 实例化对象
  • 使用对象
  • 类的组合
  • 面向对象的三态 - 继承、多态、封装
  • 继承
  • 如何继承
  • 定义类时, 使用父类方法
  • 继承逻辑 和 继承顺序
  • 调用顺序示例
  • 封装
  • 如何封装
  • 调用顺序示例
  • 多态
  • 命名空间
  • 类对象指针



定义

  • 面向对象的思想就是把事物归类, 标准化
  • 模具 - 类; 根据模具生产的产品 - 对象
  • 造模具 - 面向对象; 造产品 - 实例化

类 - 事物的共同属性

声明类

# 类名为 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中, 处处都是多态

命名空间

  • 调用顺序永远遵循命名空间的查找顺序
  • 命名空间
  • 全局命名空间
  • 临时命名空间(局部命名空间), 当函数执行完毕时, 临时命名空间消失
  • 内置命名空间
  • 取值顺序(始终)
    局部命名空间(函数执行时) --> 全局命名空间 --> 内置命名空间
  • 加载顺序(始终)
    与取值相反

类对象指针

  • 在创建对象时, 会产生对象和类的联系, 称为类对象指针
  • 对象能通过类对象指针找到类, 但是类不能通过类对象指针找到对象