装饰器property用法及使用它重构代码时的应用实例

简介:   我们知道装饰器可以将所需要的函数作为对象返回给需要用此函数处理的对象。而property装饰器则是将一个函数或者方法成为一个属性以供使用。@property这种语法糖形式简化了装饰器的使用。 ### 二、引导  在面向对象类型的语言中访问修改类中的属性时通常会自己写set或者get函数,对输出结果进行修饰或者对输入进行合法化检查。然而python可以提供一种优美的更直观的方法就是使用装饰器@property。

### 一、装饰器
  我们知道装饰器可以将所需要的函数作为对象返回给需要用此函数处理的对象。而property装饰器则是将一个函数或者方法成为一个属性以供使用。@property这种语法糖形式简化了装饰器的使用。
### 二、引导
  在面向对象类型的语言中访问修改类中的属性时通常会自己写set或者get函数,对输出结果进行修饰或者对输入进行合法化检查。然而python可以提供一种优美的更直观的方法就是使用装饰器@property。

三、用法

实例:对属性进行正整数检查

class Inter:

    def __init__(self, value=0):
        self.inter = value

    def get_int(self):
        """
        将输出转化为字符串
        :return:
        """

        return str(self.inter)

    def set_int(self, value):
        if(value < 0) | (not isinstance(value, int)):
            raise ValueError('inter is error.')
        self.inter = value
        return self.inter

a = Inter()
a.set_int(3)
print(a.get_int())

  这样写是不是很不直观,所以我们采用property来写,并使用语法糖@property

class Inter:

    def __init__(self, value=0):
        self._inter = value

    @property
    def inter(self):
        """
        将输出转化为字符串
        :return:
        """

        return str(self._inter)

    @inter.setter
    def inter(self, value):
        if(value < 0) | (not isinstance(value, int)):
            raise ValueError('inter is error.')
        self._inter = value
        return self._inter

a = Inter()
a.inter = 3
print(a.inter)

四、重构代码的应用实例

  很久以前,Python程序员Tom写了一个代表金钱的类。他的实现的形式下面这样:

# 首个版本
class Money:
    def __init__(self, dollars, cents):
        self.dollars = dollars
        self.cents = cents

  这个类后来被打包到一个公共库里,慢慢地被不同的应用使用。公司另一个团队中的Bob是这样使用Money类的:

# 创建一个money对象
money = Money(34, 1)
print("{} dollars and {} cents.".format(money.dollars, money.cents))
# 修改money类的属性
money.dollars = 23
money.cents = 2
print("{} dollars and {} cents.".format(money.dollars, money.cents))

结果:
    34 dollars and 1 cents.
    23 dollars and 2 cents.

  一段时间后,公司业务变化原来的money只需要记录美分。pm找到开发,然而Tom却离职了,只能找到刚接手的Jerry。Jerry看过代码后说没问题,他是这样改的:

# 第二个版本
class Money:
    def __init__(self, dollars, cents):
        self.total_cents = dollars * 100 + cents

  改完后Jerry突然想到:如果很多业务部门引用Money类的话,每一处都必须要调整。幸好他是一个机智的少年,知道装饰器property的使用方法,马上做出如下的修改。

# 最终版本
class Money:
    def __init__(self, dollars, cents):
        self.total_cents = dollars * 100 + cents

    # dollars使用property装饰器的输入、输出
    @property
    def dollars(self):
        return self.total_cents // 100;
    @dollars.setter
    def dollars(self, new_dollars):
        self.total_cents = 100 * new_dollars + self.cents

    # cents使用property装饰器的输入、输出
    @property
    def cents(self):
        return self.total_cents % 100;
    @cents.setter
    def cents(self, new_cents):
        self.total_cents = 100 * self.dollars + new_cents

上面代码使用@property装饰器定义了dollars、cents属性(相当于get函数),还利用@dollars.setter、@cents.setter创建了一个setter(相当于set函数)。

Jerry对刚才自己机智的行为很是满意,奖励自己晚餐一个大大的鸡腿,而另一个团队Bob并没有感觉到任何的变化。

目录
相关文章
|
8月前
【建议】强烈推荐ES6函数自由传参的写法,针对方法体的可扩展性很有帮助
【建议】强烈推荐ES6函数自由传参的写法,针对方法体的可扩展性很有帮助
|
7月前
|
缓存 监控 程序员
Python中的装饰器是一种特殊类型的声明,它允许程序员在不修改原有函数或类代码的基础上,通过在函数定义前添加额外的逻辑来增强或修改其行为。
【6月更文挑战第30天】Python装饰器是无侵入性地增强函数行为的工具,它们是接收函数并返回新函数的可调用对象。通过`@decorator`语法,可以在不修改原函数代码的情况下,添加如日志、性能监控等功能。装饰器促进代码复用、模块化,并保持源代码整洁。例如,`timer_decorator`能测量函数运行时间,展示其灵活性。
53 0
|
4月前
|
JavaScript
代码缺乏装饰?使用ts装饰器来装饰你的代码
该文章详细介绍了TypeScript中的装饰器特性,包括类装饰器、方法装饰器、属性装饰器和参数装饰器的定义与使用方法,并通过具体示例展示了装饰器在实际编码中的应用技巧。
ES6学习(3)模板字符串、简化对象和函数写法
ES6学习(3)模板字符串、简化对象和函数写法
|
6月前
|
设计模式 Go
Go语言设计模式:使用Option模式简化类的初始化
在Go语言中,面对构造函数参数过多导致的复杂性问题,可以采用Option模式。Option模式通过函数选项提供灵活的配置,增强了构造函数的可读性和可扩展性。以`Foo`为例,通过定义如`WithName`、`WithAge`、`WithDB`等设置器函数,调用者可以选择性地传递所需参数,避免了记忆参数顺序和类型。这种模式提升了代码的维护性和灵活性,特别是在处理多配置场景时。
77 8
|
7月前
|
数据安全/隐私保护 Python
Python装饰器是高阶函数,用于在不修改代码的情况下扩展或修改函数行为。它们提供可重用性、模块化和无侵入性的功能增强。
【6月更文挑战第20天】Python装饰器是高阶函数,用于在不修改代码的情况下扩展或修改函数行为。它们提供可重用性、模块化和无侵入性的功能增强。例如,`@simple_decorator` 包装`my_function`,在调用前后添加额外操作。装饰器还能接受参数,如`@logged(&quot;INFO&quot;, &quot;msg&quot;)`,允许动态定制功能。
50 6
|
8月前
|
JavaScript 开发者 索引
【亮剑】探讨了在TypeScript中为对象动态添加属性的三种方式
【4月更文挑战第30天】本文探讨了在TypeScript中为对象动态添加属性的三种方式:1) 使用索引签名允许添加任意属性,如`[key: string]: any`;2) 通过接口和类型别名提供编译时类型检查,例如`interface Person { name: string; age: number; }`;3) 利用类创建具有属性的对象,如`class Person { name: string; age: number; }`。每种方法有其适用场景,开发者可根据需求选择。
766 0
|
8月前
|
前端开发 JavaScript 安全
对象属性值的黑魔法:ES8的简化语法让你的代码更简洁
对象属性值的黑魔法:ES8的简化语法让你的代码更简洁
|
8月前
|
JavaScript 前端开发 编译器
TypeScript【可选属性、只读属性、额外的属性检查、函数类型、类类型、继承接口】(四)-全面详解(学习总结---从入门到深化)
TypeScript【可选属性、只读属性、额外的属性检查、函数类型、类类型、继承接口】(四)-全面详解(学习总结---从入门到深化)
81 0
简化对象和函数写法
简化对象和函数写法
45 1