【Python】封装、继承、多态、闭包、装饰器【属性、方法】

1. 封装

  • 定义:将属性和方法封装到类中,隐藏内部细节,对外只提供访问接口,控制数据读写。

  • 【注意】:

    • 共有:直接访问
    • 私有:双下划线__开头,外部不能直接访问。需要通过get/set方法取值,改值。
class Person:
    def __init__(self, name, age):
        self.name = name      # 公有
        self.__age = age      # 私有

    # 取值
    def get_age(self):
        return self.__age

    # 改值(带校验)
    def set_age(self, age):
        if 0 < age < 120:
            self.__age = age

2. 继承

  • 定义:子类复用父类已有的属性和方法,不用重复写代码;子类可扩展新方法重写父类方法
# 父类
class Animal:
    def eat(self):
        print("动物需要吃东西")

# 子类继承父类
class Dog(Animal):
    # 扩展自己的方法
    def bark(self):
        print("狗狗汪汪叫")

3. 多态

  • 定义:继承 + 方法重写 前提下,同一个父类方法,不同子类有不同实现
class Animal:
    def talk(self):
        pass

class Dog(Animal):
    def talk(self):
        print("汪汪")

class Cat(Animal):
    def talk(self):
        print("喵喵")

# 多态调用
def show(ani):
    ani.talk()

show(Dog())
show(Cat())

4. 类

  • 抽象类:(1)不能实例化(不能创建对象);(2)里面的抽象方法,只声明,不实现;(3)子类必须重写所有抽象方法,否则子类也不能实例化(4)继承ABC(5)用abcstractmethod装饰器装饰函数。

    • 注意:加了@abcstractmethod装饰器的抽象类函数,必须重写,而没有加装饰器的对象函数可以不用重写直接调用
from abc import ABC, abstractmethod

# 抽象类:继承 ABC
class Animal(ABC):
    # 抽象方法:没有方法体,只有定义
    @abstractmethod
    def speak(self):
        pass

    # 抽象类可以有普通方法
    def eat(self):
        print("动物都要吃东西")

# --------------------不能实例化对象,直接报错
a = Animal()   # 直接报错!

# --------------------子类重写抽象类函数
class Dog(Animal):
    # 必须实现父类抽象方法
    def speak(self):
        print("汪汪叫")

# 可以创建子类对象
d = Dog()
d.speak()
# 未加装饰器的对象函数可以直接调用
d.eat()

5. 属性

  • 类属性:写在类里面,方法外面;所有实例共享;因此修改类属性值时,所有对象获取都会变;类和对象都能访问。
class Person:
    # 类属性
    country = "中国"

p1 = Person()
p2 = Person()

# 所有对象共用
print(p1.country)
print(p2.country)
print(Person.country)  # 类也可以直接访问
  • 对象属性:定义在__init__里。每个对象独有,互不干扰。只能对象访问,类不能直接访问。
class Person:
    country = "中国"   # 类属性

    def __init__(self, name, age):
        # 对象属性
        self.name = name
        self.age = age

p1 = Person("小明", 18)
p2 = Person("小红", 20)
  • 私有属性:变量前有"__";外部不能直接访问,只能类内部访问;推荐使用get/set方法来操作
class Person:
    def __init__(self, name, age):
        self.name = name     # 公有
        self.__age = age     # 私有属性

	def get_age(self):
	    return self.__age

	def set_age(self, a):
	    if 0 < a < 120:
	        self.__age = a

6. 方法

  • 对象方法:默认创建的就是对象方法。
class Person:
    # 对象方法
    def run(self):
        print("人在跑步")

# 调用
p = Person()
p.run()
  • 类方法:必须带装饰器'@classmethod';第一参数必须是cls;可以用类调用,也可以用对象调用;默认只能访问类属性,不能直接访问对象属性,如果需要访问对象属性,用类名.对象属性名.。
class Person:
    count = 0  # 类属性
	def __init__(self, name):
		self.name = name

    @classmethod
    def show_count(cls):
        print("人数:", cls.count)
		print("姓名", self.name) # 注意:无法调用对象属性,因此这里会报错
		print("姓名", Person.name) # 注意:可行

if __name__ == '__main__':
    ps = Person("张三")
    ps.show_count()
  • 私有方法:方法名前面带有"__";外部不能调用,只允许类内部调用;
class Person:
    # 私有方法
    def __secret(self):
        print("这是私有内部逻辑")

    # 公有方法可以调用私有方法
    def work(self):
        self.__secret()
        print("正常工作")


if __name__ == '__main__':
	p = Person()
	p.work()
	# p.__secret()  报错,外部访问不了
  • 静态方法:既不访问类属性;也不访问对象属性;只是放在类里的普通函数,用@staticmethod装饰;调用: 类名.静态方法() / 对象.静态方法()
class Math:
    @staticmethod
    def add(a, b):
        return a + b

print(Math.add(1,2))

7. 闭包

  • 特点:(1) 函数嵌套(外层函数 + 内层函数) (2)内层嵌套使用外层函数的局部变量 (3)外层函数return返回内层函数。
  • 作用:(1)保存函数状态 (2)变量私有化,不用全局变量 (3)装饰器底层就是闭包
  • 闭包三要素:(1) 外层函数里定义局部变量;(2)内层函数使用外层变量(3)外层函数返回内层函数名
def outer():
    # 外层局部变量
    num = 10

    # 内层函数
    def inner():
        print(num)  # 内层用外层变量

    # 返回内层函数
    return inner

# 接收内层函数
f = outer()
f()   # 输出 10
  • 闭包如果想要修改外层变量:需要用nonlocal
def count():
    n = 0
    def add():
        nonlocal n   # 声明不是局部变量,用外层的
        n += 1
        return n
    return add

c = count()
print(c())  # 1
print(c())  # 2
print(c())  # 3

8. 装饰器:本质是闭包

  • 作用:不修改原函数代码,不改变调用方式,给函数加新功能。

  • 三要素:(1)外层函数接收原函数当参数;(2)内层函数写前置 + 后置 扩展逻辑。 (3)外层返回内层函数

  • 代码示例

    • 语法结构
    # 第一层:收装饰器参数
    def 外层(装饰器参数):
        # 第二层:收原函数
        def 中间层(func):
            # 第三层:包装执行
            def 内层(*args, **kwargs):
                # 前置逻辑
                res = func(*args, **kwargs)
                # 后置逻辑
                return res
            return 内层
        return 中间层
    
    • 无参装饰器
    # 1. 定义装饰器
    def deco(func):
        # 内层包装函数
        def wrapper():
            print("函数开始")   # 前置
            func()             # 执行原函数
            print("函数结束")   # 后置
        return wrapper
    
    # 2. 使用装饰器 @语法糖
    @deco
    def hello():
        print("我是原函数")
    
    # 3. 直接调用
    hello()
    
    • 装饰带参数的函数
    def deco(func):
        def wrapper(*args, **kwargs):
            print("开始执行")
            res = func(*args, **kwargs)  # 接收原函数返回值
            print("执行完毕")
            return res
        return wrapper
    
    @deco
    def add(a,b):
        return a + b
    
    print(add(3,5))
    
    • 带开关参数的装饰器
    # 第一层:接收装饰器参数 flag
    def log_switch(flag):
        # 第二层:接收被装饰函数 func
        def deco(func):
            # 第三层:包装函数
            def wrapper(*args, **kwargs):
                if flag:
                    print("【日志开启】开始执行函数")
                res = func(*args, **kwargs)
                if flag:
                    print("【日志开启】函数执行结束")
                return res
            return wrapper
        return deco
    
    # 使用:给装饰器传参数 True
    @log_switch(flag=True)
    def hello(name):
        print(f"你好:{name}")
    
    hello("张三")
    
    • 传字符串参数
    def tip(msg):
        def deco(func):
            def wrapper():
                print(f"提示:{msg}")
                func()
            return wrapper
        return deco
    
    @tip("正在执行加法函数")
    def add():
        print(10 + 20)
    
    add()
    
    • 多装饰器

      • 装饰器从上往下装饰,从下往上执行
    # 装饰器1
    def deco1(func):
        print("【deco1 装饰阶段】")
        def wrapper():
            print("deco1 执行前")
            func()
            print("deco1 执行后")
        return wrapper
    
    # 装饰器2
    def deco2(func):
        print("【deco2 装饰阶段】")
        def wrapper():
            print("deco2 执行前")
            func()
            print("deco2 执行后")
        return wrapper
    
    # 装饰器3
    def deco3(func):
        print("【deco3 装饰阶段】")
        def wrapper():
            print("deco3 执行前")
            func()
            print("deco3 执行后")
        return wrapper
    
    # ------------------------执行结果
    【deco3 装饰阶段】
    【deco2 装饰阶段】
    【deco1 装饰阶段】
    
    deco1 执行前
    deco2 执行前
    deco3 执行前
    ===== 原函数 hello 执行 =====
    deco3 执行后
    deco2 执行后
    deco1 执行后
    

9. 鸭子类型

  • 定义:不看类型,只看方法。只要长得像鸭子、叫起来像鸭子、它就是鸭子。
  • 特点:(1) Python不强制继承关系;(2) 只要对象有这个方法,就能调用。(3) 多态的简化版
class Duck:
    def speak(self):
        print("嘎嘎")

class Dog:
    def speak(self):
        print("汪汪")

# 函数不关心类型,只关心有没有 speak 方法
def say(animal):
    animal.speak()

say(Duck())
say(Dog())
posted @ 2026-05-15 20:20  静心笃行。  阅读(22)  评论(0)    收藏  举报