两个类的装饰器,内置的魔术方法
-
什么时候用?
-
定义了一个方法,默认传self,但这个self没被使用,而且你在这个方法里用到了当前的类名,或者你准备使用这个类的内存空间中的名字
-
-
怎么定义?
-
装饰器怎么加?
在被装饰的方法前写@classmethod
-
参数怎么改?
将self改成cls,并在方法里面需要用类名的地方一致写上cls
1 # classmethod 被装饰的方法会成为一个静态方法 2 # class Goods: 3 # __discount = 0.8 4 # def __init__(self): 5 # self.__price = 5 6 # self.price = self.__price * self.__discount 7 # @classmethod # 把一个对象绑定的方法 修改成一个 类方法 8 # def change_discount(cls,new_discount): 9 # cls.__discount = new_discount
-
-
怎么用?
类名或者对象名皆可调用
1 # Goods.change_discount(0.6) # 类方法可以通过类名调用 2 # apple = Goods() 3 # print(apple.price) 4 # apple.change_discount(0.5) # 类方法可以通过对象名调用 5 # apple2 = Goods() 6 # print(apple2.price)
-
为什么用?有什么好处?
在方法中仍然可以引用类中的静态变量;可以不用实例化对象,就直接用类名在外部调用这个方法
例子
1 # import time 2 # class Date: 3 # def __init__(self,year,month,day): 4 # self.year = year 5 # self.month = month 6 # self.day = day 7 # @classmethod 8 # def today(cls): 9 # struct_t = time.localtime() 10 # date = cls(struct_t.tm_year,struct_t.tm_mon,struct_t.tm_mday) 11 # return date 12 # 13 # date对象 = Date.today() 14 # print(date对象.year) 15 # print(date对象.month) 16 # print(date对象.day)
staticmethod
-
什么时候用
本身是一个普通的函数,被移到类的内部执行,在方法内部既不会用到self变量,也不会用到cls变量
-
怎么定义
在方法之前写上@staticmethod,别的不用改
1 # class User: 2 # pass 3 # @staticmethod 4 # def login(a,b): # 本身是一个普通的函数,被挪到类的内部执行,那么直接给这个函数添加@staticmethod装饰器就可以了 5 # print('登录的逻辑',a,b)
-
怎么用?由谁来调用
对象和类都可以调用
1 # obj = User() 2 # User.login(1,2) 3 # obj.login(3,4)
能定义在类中的内容
静态变量:是个所有的对象共享的变量 由对象\类调用
绑定方法:是个自带self参数的函数 由对象调用
类方法:是个自带cls参数的函数 由对象\类调用
静态方法:是个啥都不带的普通函数 由对象\类调用
property属性:是个伪装成属性的方法 由对象调用 但不加括号
1 class A: 2 country = '中国' 3 def func(self): 4 print(self.__dict__) 5 @classmethod 6 def clas_func(cls): 7 print(cls) 8 @staticmethod 9 def stat_func(): 10 print('普通函数') 11 @property 12 def name(self): 13 return 'wahaha'
一些内置的魔术方法
__call__
方法
类中有__call__
方法的话就可被调用
对象()能不能运行就是callable判断的事
1 class A: 2 def __call__(self, *args, **kwargs): 3 print('-------') 4 # obj = A() 5 # print(callable(obj)) 6 # obj() 7 # Flask框架的源码 8 # A()() # 实例化对象在调用方法
__len__
方法
len(对象)可不可用取决于这个类中有无__len__
方法
1 class Cls: 2 def __init__(self,name): 3 self.name = name 4 self.students = [] 5 def __len__(self): 6 return len(self.students) 7 py22 = Cls('py22') 8 py22.students.append('杜相玺') 9 py22.students.append('庄博') 10 py22.students.append('大壮') 11 print(py22.__len__()) 12 print(len(py22))
假如自己定义一个方法
1 # class Pow: 2 # def __init__(self,n): 3 # self.n = n 4 # def __pow2__(self): 5 # return self.n ** 2 6 7 # def pow2(obj): # 这一步为了实现类似于len(list_1)的功能 8 # return obj.__pow2__() 9 # obj = Pow(10) 10 # print(obj.__pow2__())
__str__
方法和__repr__
方法
-
__str__
方法:-
在打印一个对象的时候 调用
__str__
方法 -
在%s拼接一个对象的时候 调用
__str__
方法 -
在str一个对象的时候 调用
__str__
方法
1 # class clas: 2 # def __init__(self): 3 # self.student = [] 4 # def append(self,name): 5 # self.student.append(name) 6 # def __str__(self): 7 # return str(self.student) 8 # 9 # py22 = clas() 10 # py22.append('大壮') 11 # print(py22) 12 # print(str(py22)) 13 # print('我们py22班 %s'%py22) 14 # print(py22) 15 # py22.append('大壮') 16 # print(py22)
-
-
__repr__
方法-
如果找不到
__str__
,就调用__repr__
方法 -
用%r进行字符串拼接
-
用repr(对象)的时候
1 # class clas: 2 # def __init__(self): 3 # self.student = [] 4 # def append(self,name): 5 # self.student.append(name) 6 # def __repr__(self): 7 # return str(self.student) 8 # def __str__(self): 9 # return 'aaa' 10 # 11 # py22 = clas() 12 # py22.append('大壮') 13 # print(py22) 14 # print(str(py22)) 15 # print('我们py22班 %s'%py22) 16 # print('我们py22班 %r'%py22) 17 # print(repr(py22))
-
__new__
方法***
__new__
方法是一种构造方法,其作用是在实例化的时候创建一块对象的空间,有一个指针可以指向类。其顺序在__init__
之前
1 # class A: 2 # def __new__(cls, *args, **kwargs): # 构造方法 3 # # o = super().__new__(cls) #方法一 4 # o = object.__new__(cls) #方法二 两种方法皆可 5 # print('执行new',o) 6 # return o 7 # def __init__(self): 8 # print('执行init',self) 9 # A()
注意:在这个例子中self与o打印出来的结果一致,因为先调用__new__
实例化以后会自动把这个实例传给self
设计模式—单例
总共有五种实现方法
方法一***(面试用):
1 class Baby: 2 __instance = None 3 def __new__(cls, *args, **kwargs): 4 if cls.__instance is None: 5 cls.__instance = super().__new__(cls) 6 return cls.__instance 7 def __init__(self,cloth,pants): 8 self.cloth = cloth 9 self.pants = pants 10 b1 = Baby('红毛衣','绿皮裤') 11 print(b1.cloth) 12 b2 = Baby('白衬衫','黑豹纹') 13 print(b1.cloth) 14 print(b2.cloth)
方法二(平时用,简单方便):
1 # 在另一个模块中 单例.py 2 class Baby: 3 def __init__(self,cloth,pants): 4 self.cloth = cloth 5 self.pants = pants 6 7 baby = Baby('红上衣','绿裤子')
1 # 在当前运行脚本下 2 from 单例 import baby 3 print(baby) 4 # 一个模块不会被重复导入,所以导入一次每次都是同一个地址