摘要
@classmethod和@staticmethod是类的两个装饰器,可以让方法变成类方法或静态方法。@classmethod可以让方法中引用类中的静态变量,而不用实例化对象。@staticmethod则更加灵活,可以独立于类而存在。
正文
类的两个装饰器classmethod、staticethod和内置魔术方法
@classmethod:把类中的绑定方法变成一个类方法,cls 就等于类名
有什么用?
1、在方法中任然可以引用类中的静态变量
2、可以不用实例化对象,就直接用类名在外部调用这个方法
什么时候用?
1、定义了一个方法,默认传 self ,但这个 self 没有被使用。
2、并且你在这个方法里用到了当前类名,或者你准备使用这个类的内存空间中的名字的时候
# 商品打折: class Goods: __discount = 0.8 def __init__(self, original_price): self.original_price = original_price self.price = self.original_price * self.__discount @classmethod # 把一个对象的绑定方法改成一个类方法 def change_discount(cls, count): cls.__discount = count # 相当于Goods.__discount = count Goods.change_discount(0.6) # 类方法可以通过类名调用 # 实例化一个华为手机对象 huawei = Goods(20) print(int(huawei.price)) huawei.change_discount(0.4) # 类方法可以通过对象调用 # 实例化一个苹果手机对象 apple = Goods(20) print(int(apple.price)) # 输出 12 8
扩展:
在掉用类的函数的时候就实例化了一个对象
import time class Date: def __init__(self, year, month, day): self.year = year self.month = month self.day = day @classmethod def today(cls): structure = time.localtime() # 在方法中创建一个对象 obj = cls(structure.tm_year, structure.tm_mon, structure.tm_mday) return obj # 当调用类中的today方法就会返回一个对象(对象属性不用自己填,today方法已经填好了) data对象 = Date.today() print(data对象.year) print(data对象.month) print(data对象.day) # 输出 2021 5 4
@staticmethod:被装饰的方法会成为一个静态方法
本身是一个普通函数,被挪到类的内部执行,那么直接给这个函数添加 @staticmethod 装饰器就可以了
在函数的内部即用不到 self 变量,也用不到 cls 类
class User: pass @staticmethod def login(user): print(f'{user},登录成功') User.login('Alen') # 类可以调佣 Bob = User() Bob.login('Bob') # 对象可以调佣 # 输出 Alen,登录成功 Bob,登录成功
总结:能定义到类中的内容。
1、静态变量:是个所有的对象共享的变量 ——由对象、类调用
2、实例变量:是对象的属性变量 ——由对象调用
3、绑定方法:是个自带self参数的函数 ——由对象调用
4、类方法:是个自带cls参数的函数 ——由对象、类调用
5、property属性:是个伪装属性的方法 ——由对象调用,但不加括号
二、内置魔术方法
__call__
方法:对象 + ( ) 调用这个类中的__call__
方法
class User: pass @staticmethod def login(user): print(f'{user},登录成功') User.login('Alen') # 类可以调佣 Bob = User() Bob.login('Bob') # 对象可以调佣 # 输出 Alen,登录成功 Bob,登录成功
__len__
方法:len (对象) 需要实现这个类中的__len__
方法
class A: def __init__(self): self.lis = [1, 2, 3, 4, 5] def len(self): return len(self.lis) def __len__(self): return len(self.lis) a = A() print(len(a)) # 可以直接len(a)就可以查看lis里面值的个数 print(a.len()) # 不然就要使用类中的len方法才可以查看 # 输出 5 5 # ------------------------------------------------------------------------------------- # 扩展:也可以使用自定义的函数 class A: def __init__(self, count): self.count = count def __square__(self): value = self.count ** 2 return value def square(count): return A.__square__(count) a = A(5) print(square(a)) # 输出 25
__new__
方法:实例化的时候会先执行__new__
方法用来创建一个对象需要的空间
class A: def __new__(cls, *args, **kwargs): o = super().__new__(cls) print(o) # 内存地址和 self 的内存地址一样 print('执行了__new__方法') return o def __init__(self): print(self) print('执行了__init__方法') A() # 实例化对象 # 输出 <__main__.A object at 0x014E0970> 执行了__new__方法 <__main__.A object at 0x014E0970> 执行了__init__方法
__new__
方法的设计模式:————>单例模式
一个类,从头到尾,只会创建一次 self 的空间
class Car: __attribute = None def __new__(cls, *args, **kwargs): if cls.__attribute is None: # 当第一次开空间的时候__attribute肯定是空的 # 所以就会开一个新的空间。并把__attribute给赋值,那么以后的都不是第一次了。 cls.__attribute = super().__new__(cls) return cls.__attribute # 把新空间返回给self def __init__(self, car_paint, cartwheel_colour): self.car_paint = car_paint self.cartwheel_colour = cartwheel_colour xiao_hong = Car('红色的车漆', '蓝色的车轮') print('小红的内存地址:', xiao_hong) # 他们的内存地址都是一样的 print(xiao_hong.car_paint) # 红色的车漆————>小红刚拿到的时候还是红色的 xiao_ming = Car('白色的车漆', '黑色的车轮') print('小名的内存地址:', xiao_ming) print(xiao_hong.car_paint) # 白色的车漆————>小明在拿过来,把颜色给改成白的了 print(xiao_ming.car_paint) # 白色的车漆————>小红的也变了,应为他们都是同一个车 # 输出 小红的内存地址: <__main__.Car object at 0x01A70A60> 红色的车漆 小名的内存地址: <__main__.Car object at 0x01A70A60> 白色的车漆 白色的车漆
__str__
和__repr__
方法:
str方法:帮助我们在打印或展示对象的时候更加直观的显示对象内容
1、在打印一个对象的时候,调用__str__
方法
2、在 %s 拼接一个对象的时候,调用__str__
方法
3、在str一个对象的时候,调用__str__
方法
当打印一个对象的时候,希望这个对象显示的值是什么,那么你就必须在这个对象内部实现一个__str__
,这样的话你就能做到,你在打印这个对象的时候你就能查看到他的内容是多少(查看的内容由你自己在 str 中定义),不然就只能答应一堆内存地址。
repr方法:是 str 的备胎(有str的时候打印str,没有就打印rper),同时 %r 和 repr 有合作关系
class User: def __init__(self, name, age): self.name = name self.age = age def __str__(self): return self.name def __repr__(self): return self.age Bob = User('鲍勃', '18') print(Bob) # 现在就可以直接打印对象了,——不设置str方法,打印的就是是一堆内存地址,优先打印 str 方法 print('我的名字是%s' % Bob) # 在 %s 拼接一个对象的时候,调用__str__方法 print('我的年龄是%r' % Bob) # 在 %r 拼接一个对象的时候,调用__repr__方法 # 输出 鲍勃 我的名字是鲍勃 我的年龄是18
关注不迷路
扫码下方二维码,关注宇凡盒子公众号,免费获取最新技术内幕!
评论0