面向对象三个常见装饰器

python面向对象三个常见装饰器

前言

本篇文章我要讲述的是python面向对象的三个常见装饰器,它们分别是封装能够访问私有属性之方法的**@property**,封装类方法的**@classmethod**,以及封装静态方法的**@staticmethod**。这三者之间的区别就在于使用的变量是来自对象的属性还是类本身的属性,亦或者二者皆不是。

​ 下面我将用一个案例来描述刚刚提到的不同属性的区别一个三种装饰器的应用。

不同的属性

​ 属性按外部是否可调用分为私有属性(外部不可访问)、非私有属性(外部可访问);按是否为所有对象共有分为公共属性(也叫类属性)和实例属性。

举个例子,现在老板给了一个工作任务,一个人的话大约需要100小时才能完成,假设该任务可以由同一部门的人接力完成,每个人都将按照自己的工作时长加上底薪来要计算薪资。由此,我们可以写一个打工人的类:

class Worker:
    work = 100
    def __init__(self,name):
        self.name = name
        self.working_hours = 0
        self.__money = 2000
    
     def worked_time(self,time):
        self.working_hours += time
        Worker.work -= time
        print(f"员工{self.name}已经工作{self.working_hours}小时")

​ 每个打工人(对象)都有属于自己的名字、工作时长、以及薪资,但是这三个属性值每个人的都不同,这样的属性叫做实例属性。而所有打工人都在接力做同一项工作,不论是谁工作一小时,总的工作时长都会减少一小时,那么这个剩余工作时长就是所有打工人共享的变量,这个变量就叫做公共属性。

daniu = Worker("大牛")
daniu.worked_time(10)
ergou = Worker("二狗")
ergou.worked_time(10)
print(f"还剩{Worker.work}小时就可以完成")  # 访问公共属性

​ 每个人的工资可能都不相同,但是我又不想人其他人知道打工人具体拿了多少钱,我们就可以将工资设置为外部不可访问的属性,这样的属性就叫做私有属性,其写法为两个下划线加变量名。同理还有私有方法也是一样的两个下划线加方法名。而外部可以访问并修改的属性就是非私有属性。

​ 引申:其实我们上面定义的私有化方法和属性是伪私有化方法/属性,可以通过_类名__属性名或方法名的方式访问:

# print(daniu.__money)  # 直接访问私有属性,会报错
print(daniu._Worker__money) #可访问

装饰器@property,方法属性化

​ 装饰器@property封装的方法实际上就是一个返回私有属性的方法,其作用就是将该方法属性化。还是接着上面的例子接着说,每个打工人的工资都是底薪加上完成的工时所对应的酬劳,再减去每月固定的保险支出。

class Worker:
    """..."""
    def set_money(self):
        self.__money += self.working_hours * 10
        print(f"员工{self.name}应发工资{self.__money}元")

    @property
    def gongzi(self):
        self.__money -= 500
        print("扣除保险费用500元")
        return self.__money

​ 注意:@property装饰器的作用是将方法属性化,所以该方法的最后一定是要返回一个值的,而且在调用时不用再加括号。

daniu.set_money()
print(daniu.gongzi)

装饰器@classmethod,定义类方法

类属性 在python中用于创建对象的类也是一个对象,叫类对象(如Worker)。通过类(类对象)创建对象的动作叫做类(类对象)的实例化,通过类(类对象)创建的对象的属性叫实例属性(如daniu.name),而类属性是给类队形中定义的属性(如Worker.work),通常用来记录与这个类相关的特征,类属性不会用于记录具体对象的特征。实际上类属性就是公共属性的另一种理解或和描述

​ **类方法 ** 通过类创建的对象调用的方法叫做实例方法,而针对类对象(类)定义的方法就叫类方法,在类方法内部可以直接访问类属性或者调用其他的类方法,其关键字是cls,原理同self。定义类方法是在方法名前加装饰器@classmethod

class Worker:
    """..."""
    @classmethod
    def add_work(cls,n):
        cls.work += n
        print(f"万恶的老板又增加了{n}小时的工作量,要把工作做完还需要{cls.work}小时")

​ 在外部调用add_work()这个类方法的时,格式跟实例方法没多大区别,实例方法的调用时实例名加方法名,类方法的调用是类名加方法名或者实例名加方法名都可以:

Worker.add_work(20) # 用类名加方法名调用,共享属性Worker.work增加了20
daniu.add_work(20) # 用实例名加方法名调用,共享属性Worker.work第二次增加20
ergou.add_work(20) # 用另外的实例名加方法名调用,共享属性Worker.work第三次增加20

​ 引申:除了使用装饰器以外,也可以直接在实例方法中直接调用共享属性,只不过此时共享属性得写全名(类名加属性名)。反正有装饰器不用,就是玩儿。

当然了,如果你想写一个类,里面有一整套方法,但你又不想创建实例就直接调用,就可以封装一个完全由类属性(共享属性)和类方法组成的类。

装饰器@staticmethod,定义静态方法

​ 如果说一个类里面不加任何装饰器写的实例方法是涉及实例属性,加装饰器classmethod写的类方法是涉及类属性(共享属性),那么与前二者相对应的就是静态方法。静态方法不涉及任何实例属性或方法也不涉及任何类属性或类方法,定义静态方法就是在方法名前面加上装饰器@staticmethod

class Worker:
    """..."""
    @staticmethod
    def fun():
        print("打工人,打工魂,打工都是人上人")
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值