[Python/魔法方法/装饰器]

来源:互联网 发布:阿里巴巴 淘宝 便宜 编辑:程序博客网 时间:2024/06/06 17:04

很多初学者遇到面向对象这块就会有点懵,尤其是魔法属性和装饰器,我们经常会遇到__str__双下划线开头,双下划线结尾的特殊方法,这个就是Python给我们内置的特殊方法,下面将对于常用的方法详解:

  1. @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.nameOut[9]: 123In [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)打印结果:self12124

@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#当我们调用方法的时候不需要加括号 我们可以认为他是一个变量,但他实际不是,我们还可以给他进行赋值,下面讲helloIn [14]: p.get()#报错hello---------------------------------------------------------------------------TypeError                                 Traceback (most recent call last)<ipython-input-14-b1f5e8758f96> in <module>()----> 1 p.get()TypeError: 'NoneType' object is not callableIn [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 = 9999Traceback (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')      9ValueError: value is not defiendIn [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@Loggerdef student(*args,**kwargs):    for i in args:        print('name:%d' % int(i))student(1,2,3)结果:name:1name:2name:3当我改成一个字符串:student(1,2,3,'e')name:1name:2name:3正常输出 错误值捕捉,我们看日志tail -f debug.log2017-12-25 14:36:24,239 - nobody - ERROR - value2017-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
阅读全文
'); })();
0 0
原创粉丝点击
热门IT博客
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 7个月孕妇得疱疹怎么办 受风脸上起疙瘩怎么办 受风了起疙瘩怎么办 7个月宝宝肠炎怎么办 出水痘发烧39度怎么办 腰肌拉伤怎么办恢复快 过敏起大水泡了怎么办 身上长疱疹怎么办冶疗 刚怀孕长了疱疹怎么办 吃完饭恶心想吐怎么办 减肥药吃了心慌怎么办 吃多了恶心想吐怎么办 想吐怎么办最快最有效 想吐又吐不出来怎么办 3岁宝宝反胃呕吐怎么办 2岁宝宝反胃呕吐怎么办 突然恶心想吐是怎么办 孕4个月反胃呕吐怎么办 怀孕2月反应大怎么办 狗吐拉稀不吃饭怎么办 狗狗咳喘怎么办最有效 半永久纹眉失败怎么办 纹的眉毛太细了怎么办 眉毛颜色做深了怎么办 半永久眼线不掉怎么办 移植9天来月经怎么办 月经迟迟不来该怎么办 lol晋级赛输了怎么办 激素正常的多囊怎么办 右侧输卵管通而不畅怎么办 小该咳嗽老不好怎么办 孩子吓着了怎么办最快 2个月宝宝吓到了怎么办 3个月宝宝吓到了怎么办 宝宝吓着了发烧怎么办 好几个月不遗精怎么办 孕妇吃了黑橄榄怎么办 内膜4mm来月经了怎么办 吃了伟哥没效果怎么办 维a酸乳膏副作用怎么办 颈椎病引起的头晕恶心怎么办