打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
Python基础学习(26)classmethod/staticmethod 装饰器 部分内置魔术方法

Python基础学习(26)classmethod/staticmethod 装饰器 部分内置魔术方法

一、今日内容大纲

  • classmethod staticmethod 装饰器
  • 部分内置魔术方法

二、classmethod staticmethod 装饰器

  1. classmethod 装饰器:对装饰的绑定方法会变成类方法

    为了了解 classmethod 装饰器到底有什么作用,我们继续使用之前举过的售卖苹果的例子:

    class Goods:    __discount = 0.8    def __init__(self):        self.__price = 5        self.price = self.__price * self.__discountapple = Goods()print(apple.price)  # 4.0

    这时我们如果想修改折扣为 6 折,可以进行下列修改:

    # 修改折扣 0.6class Goods:    __discount = 0.8    def __init__(self):        self.__price = 5        self.price = self.__price * self.__discount    def change_discount(self, new_discount):  # self参数没有利用        Goods.__discount = new_discount# 虽然成功修改了,但是好像有点儿不和逻辑apple = Goods()apple.change_discount(0.6)apple2 = Goods()print(apple2.price)  # 3.0

    可以看到,虽然我们能够成功实现修改购物商场的全场折扣,但是内置方法中的 self 参数是完全没有利用的,且修改全场折扣要利用到个别对象的绑定方法,也就是说我们如果想要修改整个全场折扣,还要首先实例化一个对象,再依靠对象来修改折扣。这样显然是不符合正常逻辑的,所以我们使用 classmethod 装饰器来将此方法定义为一个类方法:只可以被类调用(实际使用其实也可以被对象调用,但是一般不可以这么使用):

    # 定义了一个方法,默认传self,但这个self没被使用,# 这时我们使用classmethod装饰器class Goods:    __discount = 0.8    def __init__(self):        self.__price = 5        self.price = self.__price * self.__discount    @classmethod    def change_discount(cls, new_discount):  # 将self换成类名传入        cls.__discount = new_discountGoods.change_discount(0.6)  # 可以直接使用方法名修改,无需先实例化apple2 = Goods()print(apple2.price)  # 3.0

    所以一般什么情况下,才使用 classmethod 装饰器呢?

    • 定义了一个方法,默认传 self,但是这个 self 没有被使用;
    • 这个方法里用到了当前的类名,或者你准备使用这个类的内存空间中的名字的时候;

    我们来举一个实际应用中的例子:定义一个类Date,内部有年、月、日等实例变量,Date.today()可以返回一个存储当天年月日的对象。

    import timeclass Date:    def __init__(self, year, month, day):        self.year = year        self.month = month        self.day = day    @classmethod    def today(cls):        obj = cls(time.localtime().tm_year, time.localtime().tm_mon, time.localtime().tm_mday)        return objtime_obj = Date.today()print(time_obj.__dict__)
  2. staticmethod 装饰器:被装饰的绑定方法会变成一个静态方法

    class User:    pass    @staticmethod  # 本身是一个普通的函数,被挪到类的内部执行,那么直接给这个函数添加了@staticmethod装饰器就可以了    def login():        print('login')        # 在函数的内部不会用到self变量,也不会用到cls类User.login()  # 除了前面要加上类名,其他使用方式与普通函数一致
  3. 小结

    能定义到类的内容主要有:

    • 静态方法
    • 绑定方法
    • 类方法:利用 classmethod 装饰器装饰绑定方法实现
    • 静态方法:利用 staticmethod 装饰器装饰绑定方法实现
    • 属性/实例变量:可直接在__init__中定义或者利用 property 装饰器装饰绑定方法实现
    • 静态变量

三、部分内置魔术方法

  1. 总览

    魔术方法主要是指 Python 内置的__func__形式的方法,主要包括:

    • __new__
    • __call__
    • __len__
    • __eq__
    • __str__
    • __repr__
    • __del__
    • __enter__
    • __exit__
  2. __call__方法:object_name()调用此对象所属类的__call__方法。

    class A:    def __call__(self, *args, **kwargs):        print('----------')obj = A()print(callable(obj))  # Trueobj()  # 调用__call__方法 ----------
  3. __len__方法:len(object_name)调用此对象所属类的__call__方法。

    class Cls:    def __init__(self, name):        self.name = name        self.students = []    def __len__(self):        return len(self.students)py22 = Cls('py22')py22.students.append('duxiangxi')py22.students.append('taibai')py22.students.append('dazhuang')print(len(py22.students))  # 3# 这两者是等价的print(len(py22))  # 3print(py22.__len__())  # 3
  4. __new__方法:__new__方法就是在实例化之前所完成的操作,实例化的过程会先执行__new__方法,再执行__init__方法,实例化过程返回的对象也就是__new__返回的对象。

    # __new__class A:    def __new__(cls, *args, **kwargs):        o = super().__new__(cls)        # o = object.__new__(cls)  # 因为父类是object也可以这么写        print('new', o)        return o    def __init__(self):        print('init', self)A()# new <__main__.A object at 0x0000016947968B38># init <__main__.A object at 0x0000016947968B38># 实例化的时候# 先创建一块对象空间,有一个指针能指向类 -> 由__new__完成# 调用__init__# __new__是一个构造方法# 为什么要自己实现一个__new__呢?# 设计模式 --> 单例模式# 一个类 从头到尾 只会创建一次self的空间class Baby:    __instance = None    def __new__(cls, *args, **kwargs):        if cls.__instance is None:            cls.__instance = super().__new__(cls)        return cls.__instance    def __init__(self, cloth, pants):        self.cloth = cloth        self.pants = pantsb1 = Baby('红毛衣', '绿皮裤')b2 = Baby('白衬衫', '黑豹纹')print(b1)  # <__main__.Baby object at 0x0000022322CFDB00>print(b2)  # <__main__.Baby object at 0x0000022322CFDB00>print(b1.cloth)  # 白衬衫print(b2.cloth)  # 白衬衫# 利用模块的方式实现单例模式是最便捷的方法
  5. __str____repr__方法:在打印一个对象或者len(object_name)的时候,调用对象内部的__str__方法,如果对象内部不存在__str__方法则会调用备用的__repr__方法。

    # 2.__str__  __repr__class Course:    def __init__(self, name, price, period):        self.name = name        self.price = price        self.period = period    def __str__(self):  # 它只能返回str数据类型        return ','.join([self.name, str(self.price), self.period])python = Course('python', 21800, '6 months')linux = Course('linux', 19800, '3 months')mysql = Course('mysql', 12800, '4 months')go = Course('python', 21800, '4 months')print(go)  # python,21800,4 monthslst = [python, linux, mysql, go]for course in lst:    print(course)# for index, c in enumerate(lst, 1):#     print(index, c.name, c.price, c.period)# num = int(input('>>>'))# course = lst[num-1]# print(f'you choose {course.name} {course.price}.')# 在打印一个对象的时候,调用__str__方法# 在str一个对象的时候,调用__str__方法# 当我们打印一个对象的时候, 用%s进行字符串批结,或者str(对象) 总是调用这个对象的__str__方法# 如果找不到__str__就调用__repr__方法# __repr__不仅仅是__str__的替代品,还有自己的功能# 用%r进行字符串拼接 或者用repr(对象)的时候总是调用这个对象的__repr__方法
来源:https://www.icode9.com/content-1-723351.html
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
Python中classmethod和staticmethod的区别
[每日一题]2、Python中的类的定义和装饰器@classmethod与@staticmethod...
Python 的常用装饰器
玩转Python属性和方法,成为高手不再难!
python的cls,self,classmethod,staticmethod
Python中的静态方法和类成员方法简介
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服