Chinaunix首页 | 论坛 | 博客
  • 博客访问: 287495
  • 博文数量: 73
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 452
  • 用 户 组: 普通用户
  • 注册时间: 2014-09-22 17:07
个人简介

心态决定命运

文章分类

全部博文(73)

文章存档

2017年(21)

2016年(27)

2015年(21)

2014年(4)

我的朋友

分类: 系统运维

2016-08-09 10:13:07


点击(此处)折叠或打开

  1. import sys
  2.  
  3.  '''
  4.  当使用实例对象访问属性时,都会调用__getattribute__内建函数
  5.  __getattribute__查找属性的优先级
  6.  1、类属性
  7.  2、数据描述符
  8.  3、实例属性
  9.  4、非数据描述符
  10.  5、__getattr__()
  11.  
  12.  #实例.属性
  13.  c.x ==>type(x).__dict__['x'].__get__(x,type(x))
  14.  #类.属性
  15.  C.x ==>X.__dict__['x'].__get__(None,C)
  16.  
  17.  __getattribute__伪代码:
  18.     __getattribute__(property) logic:
  19.    #先在类(包括父类、祖先类)的__dict__属性中查找描述符
  20.    descripter = find first descripter in class and bases's dict(property)
  21.    if descripter:#如果找到属性并且是数据描述符,就直接调用该数据描述符的__get__方法并将结果返回
  22.        return descripter.__get__(instance, instance.__class__)
  23.    else:#如果没有找到或者不是数据描述符,就去实例的__dict__属性中查找属性,如果找到了就直接返回这个属性
  24.        if value in instance.__dict__
  25.            return value
  26.        #程序执行到这里,说明没有数据描述符和实例属性,则在类(父类、祖先类)的__dict__属性中查找非数据描述符
  27.        value = find first value in class and bases's dict(property)
  28.        if value is a function:#如果找到了并且这个属性是一个函数,就返回绑定后的函数
  29.           return bounded function(value)
  30.        else:#否则就直接返回这个属性
  31.           return value
  32.   #程序执行到这里说明没有找到该属性,引发异常,__getattr__函数会被调用
  33.   raise AttributeNotFundedException
  34.  
  35.  __setattr__伪代码:
  36.   __setattr__(property, value)logic:
  37.   #先在类(包括父类、祖先类)的__dict__属性中查找描述符
  38.   descripter = find first descripter in class and bases's dict(property)
  39.   if descripter:#如果找到了且是数据描述符,就调用描述符的__set__方法
  40.       descripter.__set__(instance, value)
  41.   else:#否则就是给实例属性赋值
  42.       instance.__dict__[property] = value
  43.  '''
  44.  #带参数函数装饰器
  45.  def log(header,footer):#相当于在无参装饰器外套一层参数
  46.      def log_to_return(fun):#这里接受被装饰的函数
  47.          def return_fun(*args,**kargs):
  48.              print(header)
  49.              fun(*args,**kargs)
  50.              print(footer)
  51.          return return_fun
  52.      return log_to_return
  53.  
  54.  #带参数类型装饰器
  55.  def flyable(message):
  56.      def flyable_to_return(cls):
  57.          def fly(self):
  58.              print(message)
  59.          cls.fly = fly #类属性也可以动态修改
  60.          return cls
  61.      return flyable_to_return
  62.  
  63.  #say(meaasge) ==> log(parms)(say)(message)
  64.  @log('日志输出开始','结束日志输出')
  65.  def say(message):
  66.      print(message)
  67.  
  68.  #定义一个非数据描述符
  69.  class myStaticObject(object):
  70.      def __init__(self,fun):
  71.          self.fun = fun
  72.      def __get__(self,instance,owner):
  73.          print('call myStaticObject __get__')
  74.          return self.fun
  75.  #无参的函数装饰器,返回的是非数据描述符对象
  76.  def my_static_method(fun):
  77.      return myStaticObject(fun)
  78.  #定义一个非数据描述符
  79.  class myClassObject(object):
  80.      def __init__(self,fun):
  81.          self.fun = fun
  82.      def __get__(self,instance,owner):
  83.          print('call myClassObject __get__')
  84.          def class_method(*args,**kargs):
  85.              return self.fun(owner,*args,**kargs)
  86.          return class_method
  87.  #无参的函数装饰器,返回的是非数据描述符对象
  88.  def my_class_method(fun):
  89.      return myClassObject(fun)
  90.  
  91.  #非数据描述符
  92.  class des1(object):
  93.      def __init__(self,name=None):
  94.          self.__name = name
  95.      def __get__(self,obj,typ=None):
  96.          print('call des1.__get__')
  97.          return self.__name
  98.  #数据描述符
  99.  class des2(object):
  100.      def __init__(self,name=None):
  101.          self.__name = name
  102.      def __get__(self,obj,typ=None):
  103.          print('call des2.__get__')
  104.          return self.__name
  105.      def __set__(self,obj,val):
  106.          print('call des2.__set__,val is %s' % (val))
  107.          self.__name = val
  108.  #测试类
  109.  @flyable("这是一个测试类")
  110.  class test(object):
  111.      def __init__(self,name='test',age=0,sex='man'):
  112.          self.__name = name
  113.          self.__age = age
  114.          self.__sex = sex
  115.  #---------------------覆盖默认的内建方法
  116.      def __getattribute__(self, name):
  117.          print("start call __getattribute__")
  118.          return super(test, self).__getattribute__(name)
  119.      def __setattr__(self, name, value):
  120.          print("before __setattr__")
  121.          super(test, self).__setattr__(name, value)
  122.          print("after __setattr__")
  123.      def __getattr__(self,attr):
  124.          print("start call __getattr__")
  125.          return attr
  126.          #此处可以使用getattr()内建函数对包装对象进行授权
  127.      def __str__(self):
  128.          return str('name is %s,age is %d,sex is %s' % (self.__name,self.__age,self.__sex))
  129.      __repr__ = __str__
  130.  #-----------------------
  131.      d1 = des1('chenyang') #非数据描述符,可以被实例属性覆盖
  132.      d2 = des2('pengmingyao') #数据描述符,不能被实例属性覆盖
  133.      def d3(self): #普通函数,为了验证函数(包括函数、静态/类方法)都是非数据描述符,可悲实例属性覆盖
  134.          print('i am a function')
  135.  #------------------------
  136.      def get_name(self):
  137.          print('call test.get_name')
  138.          return self.__name
  139.      def set_name(self,val):
  140.          print('call test.set_name')
  141.          self.__name = val
  142.      name_proxy = property(get_name,set_name)#数据描述符,不能被实例属性覆盖,property本身就是一个描述符类
  143.  
  144.      def get_age(self):
  145.          print('call test.get_age')
  146.          return self.__age
  147.      age_proxy = property(get_age) #非数据描述符,但是也不能被实例属性覆盖
  148.  #----------------------
  149.      @property
  150.      def sex_proxy(self):
  151.          print("call get sex")
  152.          return self.__sex
  153.      @sex_proxy.setter #如果没有setter装饰,那么sex_proxy也是只读的,实例属性也无法覆盖,同property
  154.      def sex_proxy(self,val):
  155.          print("call set sex")
  156.          self.__sex = val
  157.  #---------------------
  158.      @my_static_method #相当于my_static_fun = my_static_method(my_static_fun) 就是非数据描述符
  159.      def my_static_fun():
  160.          print('my_static_fun')
  161.      @my_class_method
  162.      def my_class_fun(cls):
  163.          print('my_class_fun')
  164.  #end
  165.  
  166.  if __name__ == "__main__":
  167.      say("函数装饰器测试")
  168.      '''
  169.      日志输出开始
  170.      函数装饰器测试
  171.      结束日志输出
  172.      '''
  173.      t=test( ) #创建测试类的实例对象
  174.      '''
  175.      before __setattr__
  176.      after __setattr__
  177.      before __setattr__
  178.      after __setattr__
  179.      before __setattr__
  180.      after __setattr__
  181.      '''
  182.      print(str(t)) #验证__str__内建函数
  183.      '''
  184.      start call __getattribute__
  185.      start call __getattribute__
  186.      start call __getattribute__
  187.      name is test,age is 0,sex is man
  188.      '''
  189.      print(repr(t))#验证__repr__内建函数
  190.      '''
  191.      start call __getattribute__
  192.      start call __getattribute__
  193.      start call __getattribute__
  194.      name is test,age is 0,sex is man
  195.      '''
  196.      t.fly() #验证类装饰器
  197.      '''
  198.      start call __getattribute__
  199.      这是一个测试类
  200.      '''
  201.      t.my_static_fun()#验证自定义静态方法
  202.      '''
  203.      start call __getattribute__
  204.      call myStaticObject __get__
  205.      my_static_fun
  206.      '''
  207.      t.my_class_fun()#验证自定义类方法
  208.      '''
  209.      start call __getattribute__
  210.      call myClassObject __get__
  211.      my_class_fun
  212.      '''
  213.      #以下为属性获取
  214.      t.d1
  215.      '''
  216.      start call __getattribute__
  217.      call des1.__get__
  218.      '''
  219.      t.d2
  220.      '''
  221.      start call __getattribute__
  222.      call des2.__get__
  223.      '''
  224.      t.d3()
  225.      '''
  226.      start call __getattribute__
  227.      i am a function
  228.      '''
  229.      t.name_proxy
  230.      '''
  231.      start call __getattribute__
  232.      call test.get_name
  233.      start call __getattribute__
  234.      '''
  235.      t.age_proxy
  236.      '''
  237.      start call __getattribute__
  238.      call test.get_age
  239.      start call __getattribute__
  240.      '''
  241.      t.sex_proxy
  242.      '''
  243.      start call __getattribute__
  244.      call get sex
  245.      start call __getattribute__
  246.      '''
  247.      t.xyz #测试访问不存在的属性,会调用__getattr__
  248.      '''
  249.      start call __getattribute__
  250.      start call __getattr__
  251.      '''
  252.      #测试属性写
  253.      t.d1 = 3 #由于类属性d1是非数据描述符,因此这里将动态产生实例属性d1
  254.      '''
  255.      before __setattr__
  256.      after __setattr__
  257.      '''
  258.      t.d1 #由于实例属性的优先级比非数据描述符优先级高,因此此处访问的是实例属性
  259.      '''
  260.      start call __getattribute__
  261.      '''
  262.      t.d2 = 'modefied'
  263.      '''
  264.      before __setattr__
  265.      call des2.__set__,val is modefied
  266.      after __setattr__
  267.      '''
  268.      t.d2
  269.      '''
  270.      start call __getattribute__
  271.      call des2.__get__
  272.      '''
  273.      t.d3 = 'not a function'
  274.      '''
  275.      before __setattr__
  276.      after __setattr__
  277.      '''
  278.      t.d3
  279.      '''
  280.      start call __getattribute__
  281.      '''
  282.      t.name_proxy = 'modified'
  283.      '''
  284.      before __setattr__
  285.      call test.set_name
  286.      before __setattr__
  287.      after __setattr__
  288.      after __setattr__
  289.      '''
  290.      t.sex_proxy = 'women'
  291.      '''
  292.      before __setattr__
  293.      call set sex
  294.      before __setattr__
  295.      after __setattr__
  296.      after __setattr__
  297.      '''
  298.      t.age_proxy = 3
  299.      '''
  300.      before __setattr__
  301.      Traceback (most recent call last):
  302.        File "test.py", line 191, in <module>
  303.         t.age_proxy = 3
  304.        File "test.py", line 121, in __setattr__
  305.         super(test, self).__setattr__(name, value)
  306.      AttributeError: can't set attribute
  307.      '''

阅读(1014) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~