类的高级方法:
1.静态方法:在类方法前增加关键字@staticmethod,将普通方法变成静态方法,不能再次传值,不能访问实例变量或者类变量,与类的关系仅仅是通过类名进行调用
2.类方法:在类方法前增加关键字@classmethod,类方法只能访问类变量,不能访问实例变量
3.属性方法:(重点)在类方法前增加关键字@property,调用的时候通过属性一样的方式访问(去掉括号调用),可以通过类私有属性加@setter重新赋值,@deleter删除私有属性后方能删除属性方法
- 静态方法:
class Dog(object): def __init__(self,name): self.name=name def eat(self,food): print(‘%s is eating %s‘%(self.name,food)) obj1=Dog(‘hashiqi‘) obj1.eat(‘baozi‘)
正常输出:hashiqi is eating baozi
增加关键字staticmethod:
class Dog(object): def __init__(self,name): self.name=name @staticmethod def eat(self,food): print(‘%s is eating %s‘%(self.name,food)) obj1=Dog(‘hashiqi‘) obj1.eat(‘baozi‘)
报错:
Traceback (most recent call last): File "D:/001python/01course/day07/static_method.py", line 11, in <module> obj1.eat(‘baozi‘) TypeError: eat() missing 1 required positional argument: ‘food‘
eat的实参没有传给self
结论:增加关键字@staticmethod后,类的方法变成了单纯的函数,无法访问类或者实例中的任何属性,仅增加类名进行调用
如果非要给静态方法传类属性,可以直接将对象传进去---没有意义:
class Dog(object): def __init__(self,name): self.name=name @staticmethod def eat(self): print(‘%s is eating ‘%(self.name)) obj1=Dog(‘hashiqi‘) obj1.eat(obj1)
输出:hashiqi is eating
- 类方法 --关键字@classmethod
类方法无法访问实例属性
class Dog(object): #name=‘yzw‘ def __init__(self,name): self.name=name @classmethod def eat(self): print(‘%s is eating ‘%(self.name)) obj1=Dog(‘hashiqi‘) obj1.eat()
报错如下:
print(‘%s is eating ‘%(self.name)) AttributeError: type object ‘Dog‘ has no attribute ‘name‘
类方法只能访问类属性:
class Dog(object): name=‘yzw‘ def __init__(self,name): self.name=name @classmethod def eat(self): print(‘%s is eating ‘%(self.name)) obj1=Dog(‘hashiqi‘) obj1.eat()
输入:yzw is eating
- 属性方法--关键字@property
无法正常使用调用方法
class Dog(object): def __init__(self,name): self.name=name @property def eat(self): print(‘%s is eating ‘%(self.name)) obj1=Dog(‘hashiqi‘) obj1.eat()
报错如下:
obj1.eat() TypeError: ‘NoneType‘ object is not callable
改成调用属性的方法,也就是把括号去掉:
class Dog(object): def __init__(self,name): self.name=name @property def eat(self): print(‘%s is eating ‘%(self.name)) obj1=Dog(‘hashiqi‘) obj1.eat
正常输出:hashiqi is eating
结论:把一个方法变成一个静态属性,无法通过()进行调用,它可以通过"对象.属性"进行调用
属性普通赋值也会报错:
class Dog(object): def __init__(self,name): self.name=name @property def eat(self): print(‘%s is eating ‘%(self.name)) obj1=Dog(‘hashiqi‘) obj1.eat obj1.eat=‘value‘ error: obj1.eat=‘value‘ AttributeError: can‘t set attribute
结论:属性方法可以通过属性调用方式获取,但是不能直接给予赋值
通过特殊处理给属性方法传值:
再写一个同名的方法,使用@xxx.setter关键字进行赋值,但是怎么才能给属性里面的形参传值呢?
class Dog(object): def __init__(self,name): self.name=name @property def eat(self): print(‘%s is eating ‘%(self.name)) @eat.setter def eat(self,food): print(food) obj1=Dog(‘hashiqi‘) #正常实例化对象 obj1.eat # 调用属性方法 obj1.eat=‘value‘ #调用属性赋值方法 hashiqi is eating value
属性传值二:
通过在构造方法里增加私有属性,给属性方法其他形参传值
class Dog(object): def __init__(self,name): self.name=name self.__food=None @property def eat(self): print(‘%s is eating‘%self.name,self.__food) @eat.setter def eat(self,food): print(food) self.__food=food d=Dog(‘hashiqi‘) # 1.正常实例化对象 d.eat # 2.正常调用属性方法 输出:hashiqi is eating None,此时self.__food的值取构造方法的初始值 d.eat=‘包子‘ # 3.通过setter属性赋值方法给方法赋值 d.eat # 4.再次调用属性方法,输出属性方法的结果,此时属性方法调用setter里设置的值 hashiqi is eating None baozi hashiqi is eating baozi
删除属性方法--无法删除:
class Dog(object): def __init__(self,name): self.name=name self.__food=None @property def eat(self): print(‘%s is eating %s ‘%(self.name,self.__food)) @eat.setter def eat(self,food): print(food) self.__food=food obj1=Dog(‘hashiqi‘) obj1.eat obj1.eat=‘baozi‘ obj1.eat del obj1.eat error AttributeError: can‘t delete attribute
删除属性方法--先删除私有属性
class Dog(object): def __init__(self,name): self.name=name self.__food=None @property def eat(self): print(‘%s is eating %s ‘%(self.name,self.__food)) @eat.setter def eat(self,food): print(food) self.__food=food @eat.deleter def eat(self): del self.__food print(‘had been deleted‘) obj1=Dog(‘hashiqi‘) obj1.eat obj1.eat=‘baozi‘ obj1.eat del obj1.eat hashiqi is eating None baozi hashiqi is eating baozi had been deleted
删除再进行调用报错:
class Dog(object): def __init__(self,name): self.name=name self.__food=None @property def eat(self): print(‘%s is eating %s ‘%(self.name,self.__food)) @eat.setter def eat(self,food): print(food) self.__food=food @eat.deleter def eat(self): del self.__food print(‘had been deleted‘) obj1=Dog(‘hashiqi‘) obj1.eat obj1.eat=‘baozi‘ obj1.eat del obj1.eat obj1.eat # 依然是去调用静态方法,此时私有属性已被删除 error print(‘%s is eating %s ‘%(self.name,self.__food)) AttributeError: ‘Dog‘ object has no attribute ‘_Dog__food‘
属性方法用途:隐藏细节,暴露简单接口给用户
案例:查询航空班次状态
1.调用航空公司API查询
2.对查询结果进行分析
3.将分析后的结果返回页面,用户不关心过程/方法,只关心状态,也就是属性方法的结果
class Flight(object): def __init__(self,name): self.fly_name=name def checking_status(self): print(‘checking flight %s status...‘%self.fly_name) return 3 @property def Flight_status(self): status=self.checking_status() if status == 0: print(‘flight had got canceled‘) if status == 1: print(‘flight is arrived‘) if status == 2: print(‘flight has departured already...‘) if status == 3: print(‘cannot confirm the flight status ... check later pls‘) @Flight_status.setter def Flight_status(self,status): status_dict={0:‘canceled‘,1:‘arrived‘,2:"departured"} print(‘status has changed to %s‘%status_dict.get(status)) fly1=Flight(‘A380‘) fly1.Flight_status fly1.Flight_status = 1 output: checking flight A380 status... cannot confirm the flight status ... check later pls status has changed to arrived
类的特殊成员方法
1.__doc__ 打印类下面的注释信息
class Class_name(object): ‘‘‘class description‘‘‘ pass print(Class_name.__doc__) output:class description
2.__module__ 打印模块的名字 __class__ 打印类的名字
from fly import Flight t=Flight(‘A380‘) print(t.__module__) print(t.__class__) output: status has changed to arrived fly <class ‘fly.Flight‘>
3.__init__ 构造方法,实例化类的时候自动创建
4.__del__ 析构方法,一般不定义,系统会自动执行回收垃圾
5.__call__ 对象后面加括号,触发执行
class Dog(object): def __init__(self): pass def __call__(self, *args, **kwargs): print(*args,**kwargs) d1=Dog() d1(1,2,3) output: 1 2 3
6.__dict__ 打印字典形式的类属性方法或者实例属性
class Dog(object): address=‘earth‘ def __init__(self,name,age): self.name=name self.age=age def func1(self, *args, **kwargs): print(*args,**kwargs) print(Dog.__dict__) #以字典形式打印类的所有属性和方法 d1=Dog(‘hashiqi‘,19) print(d1.__dict__) #以字典形式打印实例的属性
7.__str__ 如果一个勒种定义了__str__方法,那么打印对象的时候,默认输出该方法的返回值
class Dog(object): address=‘earth‘ def __init__(self,name,age): self.name=name self.age=age def func1(self, *args, **kwargs): print(*args,**kwargs) def __str__(self): # 如果没有定义str方法,将打印对象的内存地址 return (‘return value‘) d1=Dog(‘hashiqi‘,19) print(d1) output:return value
8. item字典方法,使用起来像操纵字典,其实是类内置方法
class Dog(object): def __getitem__(self, item): print(‘getitem‘,item) def __setitem__(self, key, value): print(‘setitem‘,key,value) def __delitem__(self, key): print(‘delitem‘,key) d1=Dog() # 1.实例化对象 value1=d1[‘key1‘] # 2.调用getitem方法 d1[‘key2‘]=‘value2‘ # 3.调用setitem方法 del d1[‘key3‘] # 4.调用delitem方法 output: getitem key1 setitem key2 value2 delitem key3
类的本质
反射
- hasattr(obj,name_str) 判断一个对象里是否有对应的字符串方法
- getattr(obj,name_str)根据字符串去获取obj对象里对应的方法的内存地址
- setattr(obj,‘y‘,z) 相当于与obj.y=z
- delattr
class Dog(object): def __init__(self,name): self.name=name def eat(self): print(‘%s is eating...‘%self.name) d1=Dog(‘hashiqi‘) choice =input(‘input>>‘).strip() #判断有没有方法 print(hasattr(d1,choice)) #判断输入的字符串在内存地址中是否存在 print(getattr(d1,choice)) #获取内存地址,加括号直接调用 getattr(d1,choice)()
一般这么用:
class Dog(object): def __init__(self,name): self.name=name def eat(self,food): print(‘%s is eating %s‘%(self.name,food)) d1=Dog(‘hashiqi‘) choice =input(‘input>>‘).strip() #输入一个方法,如果方法在类中存在,则未true if hasattr(d1,choice): func=getattr(d1,choice) #增加一个变量,有助于传入参数 func(‘baozi‘) #将参数传给判断成功的方法 output: input>>eat hashiqi is eating baozi
动态装进取一个新方法:
class Dog(object): def __init__(self,name): self.name=name def eat(self,food): print(‘%s is eating %s‘%(self.name,food)) def bulk(self): print("%s is yelling"%self.name) d1=Dog(‘hashiqi‘) choice =input(‘input>>‘).strip() #输入一个方法,如果方法在类中存在,则未true if hasattr(d1,choice): func=getattr(d1,choice) #增加一个变量,有助于传入参数 func(‘baozi‘) #将参数传给判断成功的方法 else: setattr(d1,choice,bulk) d1.talk(d1) #相当于调用类里面的talk方法,talk实际上就是类外面的bulk函数 output: input>>talk hashiqi is yelling
动态装进去一个属性
class Dog(object): def __init__(self,name): self.name=name def eat(self,food): print(‘%s is eating %s‘%(self.name,food)) def bulk(self): print("%s is yelling"%self.name) d1=Dog(‘hashiqi‘) choice =input(‘input>>‘).strip() #输入一个方法,如果方法在类中存在,则未true if hasattr(d1,choice): func=getattr(d1,choice) #增加一个变量,有助于传入参数 func(‘baozi‘) #将参数传给判断成功的方法,如果输入一个已经存在的属性,则不能加括号调用 else: # setattr(d1,choice,bulk) # d1.talk(d1) #相当于调用类里面的talk方法,talk实际上就是类外面的bulk函数 setattr(d1,choice,2) print(getattr(d1,choice)) output: input>>asdf 2
删除一个属性
class Dog(object): def __init__(self,name): self.name=name def eat(self,food): print(‘%s is eating %s‘%(self.name,food)) def bulk(self): print("%s is yelling"%self.name) d1=Dog(‘hashiqi‘) choice =input(‘input>>‘).strip() #输入一个方法,如果方法在类中存在,则未true if hasattr(d1,choice): delattr(d1,choice) else: # setattr(d1,choice,bulk) # d1.talk(d1) #相当于调用类里面的talk方法,talk实际上就是类外面的bulk函数 setattr(d1,choice,2) print(getattr(d1,choice)) print(d1.name)
output:
print(d1.name)
AttributeError: ‘Dog‘ object has no attribute ‘name‘
再变化
class Dog(object): def __init__(self,name): self.name=name def eat(self,food): print(‘%s is eating %s‘%(self.name,food)) def bulk(self): print("%s is yelling"%self.name) d1=Dog(‘hashiqi‘) choice =input(‘input>>‘).strip() #输入一个方法,如果方法在类中存在,则未true if hasattr(d1,choice): getattr(d1,choice) else: setattr(d1,choice,bulk) func = getattr(d1,choice) # 这里不管choice输入任何东西,都只调用bulk 就是把字符串choice反射成内存中bulk的地址 func(d1)
异常处理
try: 可能出错的语句 except 错误关键字1 as 别名: 别名捕获了错误的详细信息 处理语句 except 错误关键子2 as 别名: 处理语句 或者 except (错误关键字1,错误关键字2,。。。) as 别名: 多个错误无法定位 except Exception: 不管什么错误都放到这里,不建议一开始用 else: 如果except都没有捕捉到异常 就在这里处理 finally: 不管有没有出现错误,都会执行
自定义异常
class CustomException(Exception): def __init__(self,msg): self.msg=msg try: raise CustomException(‘error‘) #这里实例化一个类了 except CustomException as e: # e保存的就是msg的值 print(e) output: error