Python基础教程

第一章: 环境搭建,安装Python

第二章: 挑选一款趁手的IDE

第三章: 计算机基础知识

第四章: 命令行基础知识

第五章: 从全局把握Python

第六章: Python语言基础

第七章: Python流程控制

第八章: Python数据类型与运算

第九章: Python字符串类型

第十章: Python列表类型

第十一章: Python元组类型

第十二章: Python字典类型

第十三章: Python集合类型

第十四章: Python函数处理

第十五章: Python文件处理

第十六章: Python面向对象

第十七章: Python异常处理

第十八章: Python模块处理

第十九章: Python高级编程

第二十章: Python项目实战

首页 > Python基础教程 > 第十六章: Python面向对象 > 16.9节: 类装饰器与属性装饰器

16.9节: 类装饰器与属性装饰器

薯条老师 2022-11-30 15:38:49 26013 0

编辑 收藏

广州番禺Python, Java小班周末班培训

薯条老师在广州做Python和Java的小班培训,一个班最多10人,学员的平均就业薪资有11K。不在广州的同学可以报名线上直播班,跟线下小班的同学们同步学习。培训的课程有Python爬虫,Python后端开发,Python办公自动化,Python大数据分析,Python量化投资,Python机器学习,Java中高级后端开发。授课详情请点击:http://chipscoco.com/?cate=6

16.9.1 类装饰器

类装饰器的核心在于通过__init__方法和__call__方法来实现装饰器逻辑。 在14.5节中介绍了函数装饰器,类装饰器与函数装饰器的区别在于:函数装饰器将代码的扩展逻辑转移到函数中,而类装饰器将扩展逻辑转移到装饰器类中。类装饰器的语法结构:

"""
(1) 同函数装饰器一样,类装饰器也分为带参数和不带参数的结构
(2) 不带参数的类装饰器,通过__init__方法传递被装饰的函数,并在__call__方法中定义扩展逻辑 
"""

# 不带参数的类装饰器语法结构
class ClassName:
    def __init__(self, func):
    self.func = func
 
    def __call__(self, *args, **kwargs):
        # 在__call__方法内部定义扩展逻辑
        return self.func(*args, **kwargs)
 
 

"""
(3) 带参数的类装饰器,通过__init__方法来定义装饰器的参数,在__call__方法中
传递被装饰的函数
"""
 
# 带参数的类装饰器语法结构
class ClassName:
    # 在__init__方法中定义类装饰器的参数
    def __init__(self, *args, **kwargs):
        pass
 
    # 在__call__方法中传递被装饰的函数
    def __call__(self, func):
        # 需要再定义一个闭包函数,传递函数的参数
        def __closure(*args, **kwargs):
            func(*args, **kwargs)
        return __closure

现在通过类装饰的语法结构,来定义一个简单的验证器类Validator,用来验证函数的参数类型是否合法。

不带参数的Validator:

# __desc__ = 定义一个不带参数的类装饰器Validator
 
class Validator:
    def __init__(self, func):
        self.__func = func
        # __types表示合法的参数类型
        self.__types = (float, int)
 
    def __call__(self, *args):
        for _ in args:
            if not isinstance(_, self.__types):
                # 如果参数类型非法,直接返回0
                return 0
                
        # 参数合法,返回被装饰的函数的返回值
        return self.__func(*args)
 

# 使用Validator进行装饰
@Validator
def accumulate(*numbers):
    sum_of_numbers = 0
    for _ in numbers:
        sum_of_numbers += _
    return sum_of_numbers
 
 
print(accumulate(1,2,3,4))
# 函数的输出为10
 
# 传递一个非法的参数类型,比如字符串类型
print(accumulate(1,2,"3",4))
# 由于参数列表中包含非法的参数类型,所以函数的输出为0
带参数的Validator:

# __desc__ = 定义一个带参数的类装饰器Validator
 
class Validator:
    # 在__init__方法中定义类装饰器的参数
    def __init__(self, types):
        # __types表示合法的参数类型
        self.__types = types
 
 
    # 在__call__方法中传递被装饰的函数
    def __call__(self, func):
        def __verify(*args):
            for _ in args:
                if not isinstance(_, self.__types):
                # 如果参数类型不合法,则直接返回0
                    return 0
            return func(*args)
                        
                        
        # 返回该闭包函数 
        return __verify
 

# 使用带参数的Validator进行装饰,参数类型必须是int,bool的其中一种
@Validator((int,bool))
def accumulate(*numbers):
    sum_of_numbers = 0
    for _ in numbers:
        sum_of_numbers += _
    return sum_of_numbers
 
print(accumulate(1,2,3,4))
# 函数的输出为10
 
# 传递一个非法的参数类型,比如浮点类型
print(accumulate(1,2,3.0,4))
# 函数的输出为0

16.9.2 属性装饰器

如果在属性名前面加上双下划线的前缀,那么属性就变成了“私有”属性。私有属性只在类/对象作用域中可见,客户端如需访问私有属性,需要借助该类型的公有方法。在C++等编程语言中,通常定义get_xx方法来读取私有属性,定义set_xx方法来对私有属性进行修改,这里的xx即为对应的属性名。

代码实例:

# __desc__ = 定义get_xx和set_xx方法对私有属性进行读写操作
 
class Cat:
    def __init__(self,name):
        self.__name = name
 
    # 定义get_name方法来读取__name的值
    def get_name(self):
        return self.__name
 

    # 定义set_name方法来修改__name的值
    def set_name(self, new_name):
        self.__name = new_name
 

kitty = Cat("kitty")
 
# 执行get_name方法来读取私有属性__name
print(kitty.get_name())
 
# 执行set_name方法来为私有属性__name赋值
print(kitty.set_name("lisa"))
print(kitty.get_name())
# 输出为lisa
Python的设计目标是简单和优雅,为让客户端对属性进行更简单地操作,Python提供了属性装饰器:propery。使用property对成员方法进行装饰时,等同于实现了get_xx方法,该成员方法的函数名通常与属性名保持一致:

# __desc__ = 使用property进行装饰
 
class Cat:
    def __init__(self,name):
        self.__name = name
 
    # 使用property对name方法进行装饰
    @property
    def name(self):
        return self.__name
 
 
kitty = Cat("kitty")
 
# 可以像访问成员属性一样来调用name方法
print(kitty.name)
# 输出为kitty
Python同时提供了setter装饰器,用setter装饰器来装饰成员方法时,等同于实现了set_xx方法。使用setter进行装饰时,需要加上方法名的前缀, 在语义上表示该方法用来对属性进行设置:

# __desc__ = 使用property.setter进行装饰
 
class Cat:
    def __init__(self,name):
        self.__name = name
 
    # 使用property对name方法进行装饰
    @property
    def name(self):
        return self.__name
 

    # 使用name.setter进行装饰,表示该name方法用来对属性进行设置
    @name.setter
    def name(self, new_name):
        self.__name = new_name
 
kitty = Cat("kitty")
# 可以像直接赋值成员属性一样来调用name方法
kitty.name = "lisa"
print(kitty.name)
# 输出为lisa

16.9.3 最具实力的小班培训

薯条老师在广州做Python和Java的小班培训,一个班最多10人。不在广州的同学可以报名线上直播班,跟线下小班的同学们同步学习打算参加小班培训的同学,必须遵守薯条老师的学习安排,认真做作业和项目。把知识学好,学扎实,那么找到一份高薪的工作就是很简单的一件事。

(1) Python后端工程师高薪就业班,月薪11K-18K,免费领取课程大纲
(2) Python爬虫工程师高薪就业班,年薪十五万,免费领取课程大纲
(3) Java后端开发工程师高薪就业班,月薪11K-20K, 免费领取课程大纲
(4) Python大数据分析,量化投资就业班,月薪12K-25K,免费领取课程大纲

扫码免费领取Python学习资料:

关注微信公众号.jpg














欢迎 发表评论: