[Python/魔法方法/装饰器]
2017-12-25 11:14
435 查看
很多初学者遇到面向对象这块就会有点懵,尤其是魔法属性和装饰器,我们经常会遇到__str__
双下划线开头,双下划线结尾的特殊方法,这个就是Python给我们内置的特殊方法,下面将对于常用的方法详解:
@staticmethod:该方法称之为静态方法
1:静态方法无需传入self参数;
2:静态方法不能访问实例变量,实例属性,类属性,独立的方法;
3:说白了就是一个普通的函数,可以用来做一些工具类的东西,独立的函数
In [7]: class Static(object): ...: def __init__(self): ...: self.name = 123 ...: @staticmethod ...: def static(): ...: print('静态方法') ...: try: ...: print(self.name) #报错 ...: except: ...: print('无法访问实例变量') In [8]: s = Static() In [9]: s.name Out[9]: 123 In [10]: s.static() 静态方法 无法访问实例变量
@classmethod:
类方法:
1:类方法传入的第一个参数是cls,代表类本身,他不能访问实例变量,实例属性,但可以访问类属性,我们知道,实例可以访问类属性,也可以修改类属性(实例属性),但是无论你怎么改,他的类属性也不会改变,改变的也就是所谓的实例属性,这时候我们可以通过类方法来进行修改
class CLASSMethod(object): Cls = 1 #类属性 def __init__(self,name): self.name = name @classmethod def SetCls(cls,value): cls.Cls = value if __name__ == '__main__': c = CLASSMethod('self') print(c.name) #实例变量 print(c.Cls) #类属性,这时也成了实例属性了,他可以访问 也可以修改,但是无论你怎么修改 类属性默认值就是1 c.Cls = 2 print(c.Cls) print(CLASSMethod('1').Cls) c.SetCls(4) print(c.Cls) print(CLASSMethod('1').Cls) 打印结果: self 1 2 1 2 4
@property
对于这个方法,我最开始接触的时候理解的就是 你实例调用方法的时候 不需要加()了~,后来研究了一下 原来并不是那么简单,他可以让你这个方法可读可写,还可以在进行赋值的时候,进行验证
#第一个用法 1: In [11]: class Pro(object): ...: def __init_(self): ...: pass ...: @property #使用 ...: def get(self): ...: print('hello') ...: In [12]: p = Pro()#实例化 In [13]: p.get#当我们调用方法的时候不需要加括号 我们可以认为他是一个变量,但他实际不是,我们还可以给他进行赋值,下面讲 hello In [14]: p.get()#报错 hello --------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-14-b1f5e8758f96> in <module>() ----> 1 p.get() TypeError: 'NoneType' object is not callable In [15]: 2: class Student(object): @property #只读 当我 实例化.score的时候他会执行这个方法, def score(self): return self._score @score.setter #可读可写 当我 实例化.Score = value的时候 他会到这里去做检查 def Score(self,value): if not isinstance(value,int): raise ValueError('score must be an integer') if value < 0 or value > 100: raise ValueError('score must between 0 ~ 100') self._score = value >>> s = Student() >>> s.Score = 60 >>> s.score OK, 60 >>> s.Score = 9999 Traceback (most recent call last): ... ValueError: score must between 0 ~ 100!
魔法方法
__new__
这个方法是在实例化的时候他会调用
In [1]: class init(object): ...: def __init__(self): ...: self.name = '1' ...: ...: def __new__(self): ...: print('实例化调用') ...: In [2]: response = init() 实例化调用
__getattr__
当我访问不存在的属性时,他会拦截做一些事情
In [18]: class GETArrr(object): ...: def __init_(self): ...: pass ...: def __getattr__(self,value): ...: if value == 'age': ...: print('该值不存在') ...: else: ...: raise ValueError('value is not defiend') ...: In [19]: g = GETArrr() In [20]: g.name --------------------------------------------------------------------------- ValueError Traceback (most recent call last) <ipython-input-20-7bc222e866f3> in <module>() ----> 1 g.name <ipython-input-18-b5c0f87787a9> in __getattr__(self, value) 6 print('该值不存在') 7 else: ----> 8 raise ValueError('value is not defiend' d7b7 ) 9 ValueError: value is not defiend In [21]: g.age 该值不存在
__setattr__
同理,当我给属赋值的时候拦截
def __setattr__(self, name. value): self.name = value # 因为每次属性幅值都要调用 __setattr__(),所以这里的实现会导致递归 # 这里的调用实际上是 self.__setattr('name', value)。因为这个方法一直 # 在调用自己,因此递归将持续进行,直到程序崩溃 def __setattr__(self, name, value): self.__dict__[name] = value # 使用 __dict__ 进行赋值 # 定义自定义行为
__call__
调用实例本身,这里不举例子 self()
__setitem___ && __getitem__
赋值与获取值 这里以dict 为例子
class SetAttr(object): def __init__(self): self.name = 'ayang' self.values = {} def __getitem__(self,key): try: print(self.values[key]) except Exception: raise ValueError('value is not found ') def __setitem__(self,key,value): self.values[key] = value s = SetAttr() s['name'] = 10 s['name'] s['age'] = 100 s['age']
装饰器
举个例子 我现在有一个需求,我每一次执行一个函数,如果这个函数崩溃了,那么我需要给这个崩溃的错误 记录到日志文件里面,我们的思路是这样的每一次做一个try except,如果程序崩溃了,那么我就给他写入文件里面,但是这并不是一个好的事情,这样的坏处是什么? 我代码重复,重复调用文件 重复写文件,很麻烦 消耗资源,这时候装饰器 就派上用场了:
import logging def Logger(func): logger = logging.getLogger('nobody') logger.setLevel(logging.INFO) debugfile = logging.FileHandler('debug.log') formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') debugfile.setFormatter(formatter) logger.addHandler(debugfile) def Try(*args,**kwargs): try: func(*args,**kwargs) except ValueError as e: logger.error('value') logger.error(e) logger.error('value') return Try @Logger def student(*args,**kwargs): for i in args: print('name:%d' % int(i)) student(1,2,3) 结果: name:1 name:2 name:3 当我改成一个字符串: student(1,2,3,'e') name:1 name:2 name:3 正常输出 错误值捕捉,我们看日志 tail -f debug.log 2017-12-25 14:36:24,239 - nobody - ERROR - value 2017-12-25 14:36:24,239 - nobody - ERROR - invalid literal for int() with base 10: 'e' 2017-12-25 14:36:24,239 - nobody - ERROR - value
相关文章推荐
- python 魔法方法
- Python 类内置魔法方法
- Python魔法方法--属性
- Python魔法方法指南
- python四个魔法方法__len__,__getitem__,__setitem__,__delitem__
- Python实现对一个函数应用多个装饰器的方法示例
- 【python】如何在类方法前添加装饰器
- Python基础教程——9魔法方法、属性及迭代器【总结】
- 《Python基础教程》读书笔记(4)之第9章魔法方法、属性和迭代器(关键词:Python/魔法方法/属性/迭代器)
- 第9章 Python笔记 魔法方法、属性和迭代器
- Python学习之路:一些BIF+魔法方法+模块
- python零碎知识(6)--魔法方法、属性和迭代器
- python的魔法方法
- python魔法方法-单目运算及一般算数运算
- python中魔法属性和魔法方法
- python魔法方法-自定义序列详解
- 魔法方法 Python从入门到放弃
- Python 魔法方法详解
- python魔法方法
- python学习之魔法方法的调用