Python 面向对象进阶

系统 1389 0

一、isinstance(obj,cls)和issubclass(sub, super)

1.1 isinstance

isinstance(obj,cls)检查obj是否是类cls的对象   包括继承关系

            
              1
            
            
              class
            
            
               Foo(object):

            
            
              2
            
            
              pass
            
            
              3
            
            
              4
            
             obj =
            
               Foo()

            
            
              5
            
            
              print
            
            (isinstance(obj, Foo)) 
            
              #
            
            
               True
            
          

1.2 issubclass

issubclass(sub, super)检查sub类是否是super类的派生类   判断类与类之间的继承关系

            
              1
            
            
              class
            
            
               Foo(object):

            
            
              2
            
            
              pass
            
            
              3
            
            
              4
            
            
              5
            
            
              class
            
            
               Bar(Foo):

            
            
              6
            
            
              pass
            
            
              7
            
            
              8
            
            
              9
            
            
              print
            
            (issubclass(Bar, Foo))     
            
              #
            
            
               True
            
          

 二、特殊方法

跟运算符无关的特殊方法:

类别 方法名
字符串 / 字节序列表示形式 __repr__、 __str__、 __format__、 __bytes__
数值转换 __abs__、 __bool__、 __complex__、 __int__、 __float__、 __hash__、 __index__
集合模拟 __len__、 __getitem__、 __setitem__、 __delitem__、__contains__
迭代枚举 __iter__、 __reversed__、 __next__
可调用模拟 __call__
上下文管理 __enter__、 __exit__
实例创建和销毁 __new__、 __init__、 __del__
属性管理 __getattr__、 __getattribute__、 __setattr__、 __delattr__、 __dir__
属性描述符 __get__、 __set__、 __delete__
跟类相关的服务 __prepare__、 __instancecheck__、 __subclasscheck__
 
 跟运算符相关的特殊方法:
类名 方法名和对应的运算符
一元运算符 __neg__ -、 __pos__ +、 __abs__ abs()
众多比较运算符 __lt__ <、 __le__ <=、 __eq__ ==、 __ne__ !=、 __gt__ >、 __ge__ >=
算术运算符 __add__ +、 __sub__ -、 __mul__ *、 __truediv__ /、 __floordiv__ //、 __mod__ %、 __divmod__
反向算术运算符 __radd__、 __rsub__、 __rmul__、 __rtruediv__、 __rfloordiv__、 __rmod__、 __rdivmod__、 __rpow__
增量赋值算术运算符 __iadd__、 __isub__、 __imul__、 __itruediv__、 __ifloordiv__、 __imod__、 __ipow__
位运算符 __invert__ ~、 __lshift__ <<、 __rshift__ >>、 __and__ &、 __or__ |、 __xor__ ^
反向位运算符 __rlshift__、 __rrshift__、 __rand__、 __rxor__、 __ror__
增量赋值位运算符 __ilshift__、 __irshift__、 __iand__、 __ixor__、 __ior__
 
 

2.1 __setattr__, __delattr__, __getattr__

  • __setattr__  添加/修改属性会触发它的执行
  • __delattr__  删除属性的时候会触发
  • __getattr__  只有在调用属性且属性不存在的时候才会触发
            
               1
            
            
              #
            
            
               三者的用法演示
            
            
               2
            
            
              class
            
            
               Foo:

            
            
               3
            
                 x = 1

            
               4
            
            
              def
            
            
              __init__
            
            
              (self, y):

            
            
               5
            
                     self.y =
            
               y

            
            
               6
            
            
               7
            
            
              def
            
            
              __getattr__
            
            
              (self, item):

            
            
               8
            
            
              print
            
            (
            
              '
            
            
              ----> from getattr:你找的属性不存在
            
            
              '
            
            
              )

            
            
               9
            
            
              10
            
            
              def
            
            
              __setattr__
            
            
              (self, key, value):

            
            
              11
            
            
              print
            
            (
            
              '
            
            
              ----> from setattr
            
            
              '
            
            
              )

            
            
              12
            
            
              #
            
            
               self.key=value # 这就无限递归了,你好好想想
            
            
              13
            
                     self.
            
              __dict__
            
            [key] = value  
            
              #
            
            
               应该使用它
            
            
              14
            
            
              15
            
            
              def
            
            
              __delattr__
            
            
              (self, item):

            
            
              16
            
            
              print
            
            (
            
              '
            
            
              ----> from delattr
            
            
              '
            
            
              )

            
            
              17
            
            
              #
            
            
               del self.item #无限递归了
            
            
              18
            
                     self.
            
              __dict__
            
            
              .pop(item)

            
            
              19
            
            
              20
            
            
              #
            
            
               __setattr__  添加/修改属性会触发它的执行
            
            
              21
            
             f1=Foo(10
            
              )

            
            
              22
            
            
              print
            
            (f1.
            
              __dict__
            
            ) 
            
              #
            
            
               因为你重写了__setattr__,凡是赋值操作都会触发它的运行,你啥都没写,就是根本没赋值,除非你直接操作属性字典,否则永远无法赋值
            
            
              23
            
             f1.z=3

            
              24
            
            
              print
            
            (f1.
            
              __dict__
            
            
              )

            
            
              25
            
            
              26
            
            
              #
            
            
               __delattr__    删除属性的时候会触发
            
            
              27
            
             f1.
            
              __dict__
            
            [
            
              '
            
            
              a
            
            
              '
            
            ]=3    
            
              #
            
            
               我们可以直接修改属性字典,来完成添加/修改属性的操作
            
            
              28
            
            
              del
            
            
               f1.a

            
            
              29
            
            
              print
            
            (f1.
            
              __dict__
            
            
              )

            
            
              30
            
            
              31
            
            
              #
            
            
               __getattr__    只有在使用点调用属性且属性不存在的时候才会触发
            
            
              32
            
             f1.xxxxxx
          

2.2 __getattribute__

__getattribute__ : 不管有没有属性都会执行到,当__getattribute__和__getattr__同时存在时,只有当__getattribute__抛出AttributeError的异常时,才会执行到__getattr__,否则会一直执行__getattribute__

            
               1
            
            
              class
            
            
               Foo(object):

            
            
               2
            
            
               3
            
            
              def
            
            
              __init__
            
            
              (self, x):

            
            
               4
            
                     self.x =
            
               x

            
            
               5
            
            
               6
            
            
              def
            
            
              __getattr__
            
            
              (self, item):

            
            
               7
            
            
              print
            
            (
            
              "
            
            
              执行的是__getattr__
            
            
              "
            
            
              )

            
            
               8
            
            
               9
            
            
              def
            
            
              __getattribute__
            
            
              (self, item):

            
            
              10
            
            
              print
            
            (
            
              "
            
            
              执行的是getattribute
            
            
              "
            
            
              )

            
            
              11
            
            
              raise
            
             AttributeError(
            
              "
            
            
              抛出异常了
            
            
              "
            
            )    
            
              #
            
            
               只有抛出AttributeError的异常时,找不到属性才会执行__getattr__方法
            
            
              12
            
            
              13
            
            
              14
            
             f1 = Foo(10
            
              )

            
            
              15
            
            
              f1.x

            
            
              16
            
             f1.xxx
          

2.3 __getitem__、__setitem__、__delitem__

  • __getitem__ 以字典形式获取属性时,触发__getitem__
  • __setitem__ 以字典形式设置属性时,触发__setitem__
  • __delitem__ 删除字典的key值时,会触发__delitem__
            
               1
            
            
              class
            
            
               Foo(object):

            
            
               2
            
            
               3
            
            
              def
            
            
              __getitem__
            
            
              (self, item):

            
            
               4
            
            
              print
            
            (
            
              "
            
            
              getitem----->%s
            
            
              "
            
             %
            
               item)

            
            
               5
            
            
              return
            
             self.
            
              __dict__
            
            
              .get(item)

            
            
               6
            
            
               7
            
            
              def
            
            
              __setitem__
            
            
              (self, key, value):

            
            
               8
            
            
              print
            
            (
            
              "
            
            
              setitem---->%s %s
            
            
              "
            
             %
            
               (key, value))

            
            
               9
            
                     self.
            
              __dict__
            
            [key] =
            
               value

            
            
              10
            
            
              11
            
            
              def
            
            
              __delitem__
            
            
              (self, key):

            
            
              12
            
            
              print
            
            (
            
              "
            
            
              delitem----->%s
            
            
              "
            
             %
            
               key)

            
            
              13
            
                     self.
            
              __dict__
            
            
              .pop(key)

            
            
              14
            
            
              15
            
            
              16
            
             f1 =
            
               Foo()

            
            
              17
            
            
              print
            
            (f1.
            
              __dict__
            
            
              )

            
            
              18
            
            
              19
            
             f1[
            
              '
            
            
              name
            
            
              '
            
            ] = 
            
              '
            
            
              zhangsan
            
            
              '
            
            
              20
            
            
              print
            
            (f1.
            
              __dict__
            
            
              )

            
            
              21
            
            
              22
            
            
              print
            
            (f1[
            
              '
            
            
              name
            
            
              '
            
            
              ])

            
            
              23
            
            
              24
            
            
              del
            
             f1[
            
              '
            
            
              name
            
            
              '
            
            
              ]

            
            
              25
            
            
              26
            
            
              print
            
            (f1.
            
              __dict__
            
            )
          

2.4 __str__、__repr__、__format__

    __str__与__repr__都能改变对象的字符串显示,需要注意的是:
    str函数或者print函数--->obj.__str__()
    repr或者交互式解释器--->obj.__repr__()
    如果__str__没有被定义,那么就会使用__repr__来代替输出
    注意:这俩方法的返回值必须是字符串,否则抛出异常
              
                 1
              
              
                class
              
              
                 School(object):

              
              
                 2
              
              
                 3
              
              
                def
              
              
                __init__
              
              
                (self, name, age):

              
              
                 4
              
                       self.name =
              
                 name

              
              
                 5
              
                       self.age =
              
                 age

              
              
                 6
              
              
                 7
              
              
                def
              
              
                __str__
              
              
                (self):

              
              
                 8
              
              
                return
              
              
                '
              
              
                名字是%s,年龄是%s
              
              
                '
              
               %
              
                 (self.name, self.age)

              
              
                 9
              
              
                10
              
              
                def
              
              
                __repr__
              
              (self):     
              
                #
              
              
                 只有当__str__没有定义时,才会执行
              
              
                11
              
              
                return
              
              
                '
              
              
                aaa
              
              
                '
              
              
                12
              
              
                13
              
              
                14
              
               f1 = School(
              
                '
              
              
                alex
              
              
                '
              
              , 
              
                '
              
              
                23
              
              
                '
              
              
                )

              
              
                15
              
              
                print
              
              
                (f1)

              
              
                16
              
              
                17
              
              
                #
              
              
                 在子类中使用__str__,先找子类的__str__,没有的话向上找,只要父类不是object,就执行父类的__str__
              
              
                18
              
              
                #
              
              
                 但是如果除了object之外的父类都没有__str__方法,就执行子类的__repr__方法,如果子类也没有,还要向上找父类的__repr__方法
              
              
                19
              
              
                #
              
              
                 一直找不到,再执行object类中的__str__方法
              
            

__format__    格式化对象的字符串格式:

              
                 1
              
               date_dic =
              
                 {

              
              
                 2
              
              
                '
              
              
                ymd
              
              
                '
              
              : 
              
                '
              
              
                {0.year}:{0.month}:{0.day}
              
              
                '
              
              
                ,

              
              
                 3
              
              
                '
              
              
                dmy
              
              
                '
              
              : 
              
                '
              
              
                {0.day}/{0.month}/{0.year}
              
              
                '
              
              
                ,

              
              
                 4
              
              
                '
              
              
                mdy
              
              
                '
              
              : 
              
                '
              
              
                {0.month}-{0.day}-{0.year}
              
              
                '
              
              
                ,

              
              
                 5
              
              
                }

              
              
                 6
              
              
                 7
              
              
                 8
              
              
                class
              
              
                 Date(object):

              
              
                 9
              
              
                def
              
              
                __init__
              
              
                (self, year, month, day):

              
              
                10
              
                       self.year =
              
                 year

              
              
                11
              
                       self.month =
              
                 month

              
              
                12
              
                       self.day =
              
                 day

              
              
                13
              
              
                14
              
              
                def
              
              
                __format__
              
              
                (self, format_spec):

              
              
                15
              
              
                if
              
              
                not
              
               format_spec 
              
                or
              
               format_spec 
              
                not
              
              
                in
              
              
                 date_dic:

              
              
                16
              
                           format_spec = 
              
                '
              
              
                ymd
              
              
                '
              
              
                17
              
                       fmt =
              
                 date_dic[format_spec]

              
              
                18
              
              
                return
              
              
                 fmt.format(self)

              
              
                19
              
              
                20
              
              
                21
              
               d1 = Date(2016, 12, 29
              
                )

              
              
                22
              
              
                print
              
              
                (format(d1))

              
              
                23
              
              
                print
              
              (
              
                '
              
              
                {:mdy}
              
              
                '
              
              
                .format(d1))

              
              
                24
              
              
                print
              
              (format(d1, 
              
                '
              
              
                ymd
              
              
                '
              
              ))
            

2.5 __slots__

1.__slots__是什么:是一个类变量,变量值可以是列表,元祖,或者可迭代对象,也可以是一个字符串(意味着所有实例只有一个数据属性)
2.引子:使用点来访问属性本质就是在访问类或者对象的__dict__属性字典(类的字典是共享的,而每个实例的是独立的)
3.为何使用__slots__:字典会占用大量内存,如果你有一个属性很少的类,但是有很多实例,为了节省内存可以使用__slots__取代实例的__dict__,当你定义__slots__后,__slots__就会为实例使用一种更加紧凑的内部表示。实例通过一个很小的固定大小的数组来构建,而不是为每个实例定义一个字典,这跟元组或列表很类似。在__slots__中列出的属性名在内部被映射到这个数组的指定小标上。使用__slots__一个不好的地方就是我们不能再给实例添加新的属性了,只能使用在__slots__中定义的那些属性名。
4.注意事项:__slots__的很多特性都依赖于普通的基于字典的实现。另外,定义了__slots__后的类不再 支持一些普通类特性了,比如多继承。大多数情况下,你应该只在那些经常被使用到 的用作数据结构的类上定义__slots__比如在程序中需要创建某个类的几百万个实例对象 。
关于__slots__的一个常见误区是它可以作为一个封装工具来防止用户给实例增加新的属性。尽管使用__slots__可以达到这样的目的,但是这个并不是它的初衷。更多的是用来作为一个内存优化工具。
                
                   1
                
                
                  class
                
                
                   Foo(object):

                
                
                   2
                
                
                  #
                
                
                   创建完后,该类就不具有__dict__属性
                
                
                   3
                
                
                  __slots__
                
                 = [
                
                  '
                
                
                  name
                
                
                  '
                
                , 
                
                  '
                
                
                  age
                
                
                  '
                
                
                  ]

                
                
                   4
                
                
                   5
                
                
                   6
                
                 f1 =
                
                   Foo()

                
                
                   7
                
                 f1.name = 
                
                  '
                
                
                  alex
                
                
                  '
                
                
                   8
                
                 f1.age = 18

                
                   9
                
                
                  print
                
                
                  (f1.name)

                
                
                  10
                
                
                  11
                
                 f1.gender = 
                
                  '
                
                
                  male
                
                
                  '
                
                
                  #
                
                
                   会报错 'Foo' object has no attribute 'gender'
                
              

2.6 __doc__

该属性的无法被继承

                
                   1
                
                
                  class
                
                
                   Foo:

                
                
                   2
                
                
                  """
                
                
                   3
                
                
                      我是描述信息

                
                
                   4
                
                
                  """
                
                
                   5
                
                
                  pass
                
                
                   6
                
                
                   7
                
                
                   8
                
                
                  class
                
                
                   Bar(Foo):

                
                
                   9
                
                
                  pass
                
                
                  10
                
                
                  11
                
                
                  12
                
                
                  print
                
                (Foo.
                
                  __doc__
                
                )  
                
                  #
                
                
                   我是描述信息
                
                
                  13
                
                
                  print
                
                (Bar.
                
                  __doc__
                
                )  
                
                  #
                
                
                   None
                
              

2.7 __module__和__class__

__module__ 表示当前操作的对象在那个模块
__class__     表示当前操作的对象的类是什么
                  
                    1
                  
                  
                    #
                  
                  
                    !/usr/bin/env python
                  
                  
                    2
                  
                  
                    #
                  
                  
                     -*- coding:utf-8 -*-
                  
                  
                    3
                  
                  
                    4
                  
                  
                    class
                  
                  
                     C:

                  
                  
                    5
                  
                  
                    6
                  
                  
                    def
                  
                  
                    __init__
                  
                  
                    (self):

                  
                  
                    7
                  
                           self.name = ‘SB
                  
                    '

                  
                  
                    8
                  
                  
                    9
                  
                  
                    #
                  
                  
                     lib/aa.py
                  
                
                  
                    1
                  
                  
                    from
                  
                   lib.aa 
                  
                    import
                  
                  
                     C

                  
                  
                    2
                  
                  
                    3
                  
                   obj =
                  
                     C()

                  
                  
                    4
                  
                  
                    print
                  
                  (obj.
                  
                    __module__
                  
                  )  
                  
                    #
                  
                  
                     输出 lib.aa,即:输出模块
                  
                  
                    5
                  
                  
                    print
                  
                  (obj.
                  
                    __class__
                  
                  )      
                  
                    #
                  
                  
                      输出 lib.aa.C,即:输出类
                  
                

2.8 __del__

析构方法,当对象在内存中被释放时,自动触发执行。
 
注:如果产生的对象仅仅只是python程序级别的(用户级),那么无需定义__del__,如果产生的对象的同时还会向操作系统发起系统调用,即一个对象有用户级与内核级两种资源,比如(打开一个文件,创建一个数据库链接),则必须在清除对象的同时回收系统资源,这就用到__del__
                    
                       1
                    
                    
                      class
                    
                    
                       Foo(object):

                    
                    
                       2
                    
                    
                       3
                    
                    
                      def
                    
                    
                      __init__
                    
                    
                      (self, name):

                    
                    
                       4
                    
                             self.name =
                    
                       name

                    
                    
                       5
                    
                    
                       6
                    
                    
                      def
                    
                    
                      __del__
                    
                    
                      (self):

                    
                    
                       7
                    
                    
                      print
                    
                    (
                    
                      "
                    
                    
                      我被删除了
                    
                    
                      "
                    
                    
                      )

                    
                    
                       8
                    
                    
                       9
                    
                    
                      10
                    
                     f1 = Foo(
                    
                      '
                    
                    
                      alex
                    
                    
                      '
                    
                    
                      )

                    
                    
                      11
                    
                    
                      del
                    
                     f1
                  

2.9 __call__

对象后面加括号,触发执行。
注:构造方法的执行是由创建对象触发的,即:对象 = 类名() ;而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()
                      
                        class
                      
                      
                         Foo(object):

    
                      
                      
                        def
                      
                      
                        __call__
                      
                      (self, *args, **
                      
                        kwargs):
        
                      
                      
                        print
                      
                      (
                      
                        "
                      
                      
                        hello world
                      
                      
                        "
                      
                      
                        )


f1 
                      
                      =
                      
                         Foo()

f1()

Foo()()
                      
                    

2.10 描述符(__get__、__set__、__delete__)

1.描述符是什么:描述符本质就是一个新式类,在这个新式类中,至少实现了__get__(),__set__(),__delete__()中的一个,这也被称为描述符协议。
  __get__():调用一个属性时,触发
  __set__():为一个属性赋值时,触发
  __delete__():采用del删除属性时,触发
 
定义描述符:
                        
                          class
                        
                         Foo(object):     
                        
                          #
                        
                        
                              在python3中Foo是新式类,它实现了三种方法,这个类就被称作一个描述符
                        
                        
                          def
                        
                        
                          __get__
                        
                        
                          (self, instance, owner):
        
                        
                        
                          pass
                        
                        
                          def
                        
                        
                          __set__
                        
                        
                          (self, instance, value):
        
                        
                        
                          pass
                        
                        
                          def
                        
                        
                          __delete__
                        
                        
                          (self, instance):
        
                        
                        
                          pass
                        
                      

2.描述符是干什么的:描述符的作用是用来代理另外一个类的属性的(必须把描述符定义成这个类的类属性,不能定义到构造函数中

                        
                           1
                        
                        
                          class
                        
                        
                           Foo(object):

                        
                        
                           2
                        
                        
                           3
                        
                        
                          def
                        
                        
                          __get__
                        
                        
                          (self, instance, owner):

                        
                        
                           4
                        
                        
                          print
                        
                        (
                        
                          "
                        
                        
                          get方法
                        
                        
                          "
                        
                        
                          )

                        
                        
                           5
                        
                        
                           6
                        
                        
                          def
                        
                        
                          __set__
                        
                        
                          (self, instance, value):

                        
                        
                           7
                        
                        
                          print
                        
                        (
                        
                          "
                        
                        
                          set方法
                        
                        
                          "
                        
                        
                          )

                        
                        
                           8
                        
                        
                          #
                        
                        
                           instance.__dict__['x'] = value
                        
                        
                           9
                        
                        
                          10
                        
                        
                          def
                        
                        
                          __delete__
                        
                        
                          (self, instance):

                        
                        
                          11
                        
                        
                          print
                        
                        (
                        
                          "
                        
                        
                          delete方法
                        
                        
                          "
                        
                        
                          )

                        
                        
                          12
                        
                        
                          13
                        
                        
                          14
                        
                        
                          class
                        
                        
                           Bar(object):

                        
                        
                          15
                        
                        
                          16
                        
                             x =
                        
                           Foo()

                        
                        
                          17
                        
                        
                          18
                        
                        
                          19
                        
                         b1 =
                        
                           Bar()

                        
                        
                          20
                        
                         b1.x = 1    
                        
                          #
                        
                        
                           触发__set__方法的执行
                        
                        
                          21
                        
                        
                          print
                        
                        (b1.
                        
                          __dict__
                        
                        )  
                        
                          #
                        
                        
                           dict中为空
                        
                        
                          22
                        
                         b1.x   
                        
                          #
                        
                        
                           触发__get__方法的执行
                        
                        
                          23
                        
                        
                          del
                        
                         b1.x    
                        
                          #
                        
                        
                           触发__delete__方法的执行
                        
                      
3.描述符分为两种:
  • 数据描述符:至少实现了__get__()和__set__()
  • 非数据描述符:没有实现__set__()
4.注意事项:
  • 描述符本身应该定义成新式类,被代理的类也应该是新式类
  • 必须把描述符定义成这个类的类属性,不能为定义到构造函数中
  • 要严格遵循该优先级,优先级由高到底分别是
    • 类属性
    • 数据描述符
    • 实例属性
    • 非数据描述符
    • 找不到的属性触发__getattr__()

类属性>数据描述符

                        
                           1
                        
                        
                          #
                        
                        
                           描述符Str
                        
                        
                           2
                        
                        
                          class
                        
                        
                           Str:

                        
                        
                           3
                        
                        
                          def
                        
                        
                          __get__
                        
                        
                          (self, instance, owner):

                        
                        
                           4
                        
                        
                          print
                        
                        (
                        
                          '
                        
                        
                          Str调用
                        
                        
                          '
                        
                        
                          )

                        
                        
                           5
                        
                        
                          def
                        
                        
                          __set__
                        
                        
                          (self, instance, value):

                        
                        
                           6
                        
                        
                          print
                        
                        (
                        
                          '
                        
                        
                          Str设置...
                        
                        
                          '
                        
                        
                          )

                        
                        
                           7
                        
                        
                          def
                        
                        
                          __delete__
                        
                        
                          (self, instance):

                        
                        
                           8
                        
                        
                          print
                        
                        (
                        
                          '
                        
                        
                          Str删除...
                        
                        
                          '
                        
                        
                          )

                        
                        
                           9
                        
                        
                          10
                        
                        
                          11
                        
                        
                          class
                        
                        
                           People:

                        
                        
                          12
                        
                             name=
                        
                          Str()

                        
                        
                          13
                        
                        
                          def
                        
                        
                          __init__
                        
                        (self,name,age): 
                        
                          #
                        
                        
                          name被Str类代理,age被Int类代理,
                        
                        
                          14
                        
                                 self.name=
                        
                          name

                        
                        
                          15
                        
                                 self.age=
                        
                          age

                        
                        
                          16
                        
                        
                          17
                        
                        
                          18
                        
                        
                          #
                        
                        
                           基于上面的演示,我们已经知道,在一个类中定义描述符它就是一个类属性,存在于类的属性字典中,而不是实例的属性字典
                        
                        
                          19
                        
                        
                          20
                        
                        
                          #
                        
                        
                           那既然描述符被定义成了一个类属性,直接通过类名也一定可以调用吧,没错
                        
                        
                          21
                        
                         People.name 
                        
                          #
                        
                        
                           恩,调用类属性name,本质就是在调用描述符Str,触发了__get__()
                        
                        
                          22
                        
                        
                          23
                        
                         People.name=
                        
                          '
                        
                        
                          egon
                        
                        
                          '
                        
                        
                          #
                        
                        
                           那赋值呢,我去,并没有触发__set__()
                        
                        
                          24
                        
                        
                          del
                        
                         People.name  
                        
                          #
                        
                        
                           赶紧试试del,我去,也没有触发__delete__()
                        
                        
                          25
                        
                        
                          #
                        
                        
                          结论:描述符对类没有作用-------->傻逼到家的结论
                        
                        
                          26
                        
                        
                          27
                        
                        
                          '''
                        
                        
                          28
                        
                        
                          原因:描述符在使用时被定义成另外一个类的类属性,因而类属性比二次加工的描述符伪装而来的类属性有更高的优先级

                        
                        
                          29
                        
                        
                          People.name #恩,调用类属性name,找不到就去找描述符伪装的类属性name,触发了__get__()

                        
                        
                          30
                        
                        
                          31
                        
                        
                          People.name='egon' # 那赋值呢,直接赋值了一个类属性,它拥有更高的优先级,相当于覆盖了描述符,肯定不会触发描述符的__set__()

                        
                        
                          32
                        
                        
                          del People.name #同上

                        
                        
                          33
                        
                        
                          '''
                        
                      

数据描述符>实例属性

                        
                           1
                        
                        
                          #
                        
                        
                          描述符Str
                        
                        
                           2
                        
                        
                          class
                        
                        
                           Str:

                        
                        
                           3
                        
                        
                          def
                        
                        
                          __get__
                        
                        
                          (self, instance, owner):

                        
                        
                           4
                        
                        
                          print
                        
                        (
                        
                          '
                        
                        
                          Str调用
                        
                        
                          '
                        
                        
                          )

                        
                        
                           5
                        
                        
                          def
                        
                        
                          __set__
                        
                        
                          (self, instance, value):

                        
                        
                           6
                        
                        
                          print
                        
                        (
                        
                          '
                        
                        
                          Str设置...
                        
                        
                          '
                        
                        
                          )

                        
                        
                           7
                        
                        
                          def
                        
                        
                          __delete__
                        
                        
                          (self, instance):

                        
                        
                           8
                        
                        
                          print
                        
                        (
                        
                          '
                        
                        
                          Str删除...
                        
                        
                          '
                        
                        
                          )

                        
                        
                           9
                        
                        
                          10
                        
                        
                          11
                        
                        
                          class
                        
                        
                           People:

                        
                        
                          12
                        
                             name=
                        
                          Str()

                        
                        
                          13
                        
                        
                          def
                        
                        
                          __init__
                        
                        (self,name,age): 
                        
                          #
                        
                        
                          name被Str类代理,age被Int类代理,
                        
                        
                          14
                        
                                 self.name=
                        
                          name

                        
                        
                          15
                        
                                 self.age=
                        
                          age

                        
                        
                          16
                        
                        
                          17
                        
                        
                          18
                        
                         p1=People(
                        
                          '
                        
                        
                          egon
                        
                        
                          '
                        
                        ,18
                        
                          )

                        
                        
                          19
                        
                        
                          20
                        
                        
                          21
                        
                        
                          #
                        
                        
                           如果描述符是一个数据描述符(即有__get__又有__set__),那么p1.name的调用与赋值都是触发描述符的操作,于p1本身无关了,相当于覆盖了实例的属性
                        
                        
                          22
                        
                         p1.name=
                        
                          '
                        
                        
                          egonnnnnn
                        
                        
                          '
                        
                        
                          23
                        
                        
                          p1.name

                        
                        
                          24
                        
                        
                          print
                        
                        (p1.
                        
                          __dict__
                        
                        )
                        
                          #
                        
                        
                          实例的属性字典中没有name,因为name是一个数据描述符,优先级高于实例属性,查看/赋值/删除都是跟描述符有关,与实例无关了
                        
                        
                          25
                        
                        
                          del
                        
                         p1.name
                      

实例属性 > 非数据描述符

                        
                           1
                        
                        
                          class
                        
                        
                           Foo:

                        
                        
                           2
                        
                        
                          def
                        
                        
                           func(self):

                        
                        
                           3
                        
                        
                          print
                        
                        (
                        
                          '
                        
                        
                          我胡汉三又回来了
                        
                        
                          '
                        
                        
                          )

                        
                        
                           4
                        
                        
                           5
                        
                         f1 =
                        
                           Foo()

                        
                        
                           6
                        
                         f1.func() 
                        
                          #
                        
                        
                           调用类的方法,也可以说是调用非数据描述符
                        
                        
                           7
                        
                        
                          #
                        
                        
                           函数是一个非数据描述符对象(一切皆对象么)
                        
                        
                           8
                        
                        
                          print
                        
                        
                          (dir(Foo.func))

                        
                        
                           9
                        
                        
                          print
                        
                        (hasattr(Foo.func,
                        
                          '
                        
                        
                          __set__
                        
                        
                          '
                        
                        
                          ))

                        
                        
                          10
                        
                        
                          print
                        
                        (hasattr(Foo.func,
                        
                          '
                        
                        
                          __get__
                        
                        
                          '
                        
                        
                          ))

                        
                        
                          11
                        
                        
                          print
                        
                        (hasattr(Foo.func,
                        
                          '
                        
                        
                          __delete__
                        
                        
                          '
                        
                        
                          ))

                        
                        
                          12
                        
                        
                          #
                        
                        
                           有人可能会问,描述符不都是类么,函数怎么算也应该是一个对象啊,怎么就是描述符了
                        
                        
                          13
                        
                        
                          #
                        
                        
                           笨蛋哥,描述符是类没问题,描述符在应用的时候不都是实例化成一个类属性么
                        
                        
                          14
                        
                        
                          #
                        
                        
                           函数就是一个由非描述符类实例化得到的对象
                        
                        
                          15
                        
                        
                          #
                        
                        
                           没错,字符串也一样
                        
                        
                          16
                        
                        
                          17
                        
                         f1.func=
                        
                          '
                        
                        
                          这是实例属性啊
                        
                        
                          '
                        
                        
                          18
                        
                        
                          print
                        
                        
                          (f1.func)

                        
                        
                          19
                        
                        
                          20
                        
                        
                          21
                        
                        
                          del
                        
                         f1.func 
                        
                          #
                        
                        
                           删掉了非数据
                        
                        
                          22
                        
                         f1.func()
                      

再次验证:实例属性>非数据描述符

                        
                           1
                        
                        
                          class
                        
                        
                           Foo:

                        
                        
                           2
                        
                        
                          def
                        
                        
                          __set__
                        
                        
                          (self, instance, value):

                        
                        
                           3
                        
                        
                          print
                        
                        (
                        
                          '
                        
                        
                          set
                        
                        
                          '
                        
                        
                          )

                        
                        
                           4
                        
                        
                          def
                        
                        
                          __get__
                        
                        
                          (self, instance, owner):

                        
                        
                           5
                        
                        
                          print
                        
                        (
                        
                          '
                        
                        
                          get
                        
                        
                          '
                        
                        
                          )

                        
                        
                           6
                        
                        
                          class
                        
                        
                           Room:

                        
                        
                           7
                        
                             name=
                        
                          Foo()

                        
                        
                           8
                        
                        
                          def
                        
                        
                          __init__
                        
                        
                          (self,name,width,length):

                        
                        
                           9
                        
                                 self.name=
                        
                          name

                        
                        
                          10
                        
                                 self.width=
                        
                          width

                        
                        
                          11
                        
                                 self.length=
                        
                          length

                        
                        
                          12
                        
                        
                          13
                        
                        
                          14
                        
                        
                          15
                        
                        
                          16
                        
                        
                          #
                        
                        
                           name是一个数据描述符,因为name=Foo()而Foo实现了get和set方法,因而比实例属性有更高的优先级
                        
                        
                          17
                        
                        
                          #
                        
                        
                          对实例的属性操作,触发的都是描述符的
                        
                        
                          18
                        
                         r1=Room(
                        
                          '
                        
                        
                          厕所
                        
                        
                          '
                        
                        ,1,1
                        
                          )

                        
                        
                          19
                        
                        
                          r1.name

                        
                        
                          20
                        
                         r1.name=
                        
                          '
                        
                        
                          厨房
                        
                        
                          '
                        
                        
                          21
                        
                        
                          22
                        
                        
                          23
                        
                        
                          24
                        
                        
                          class
                        
                        
                           Foo:

                        
                        
                          25
                        
                        
                          def
                        
                        
                          __get__
                        
                        
                          (self, instance, owner):

                        
                        
                          26
                        
                        
                          print
                        
                        (
                        
                          '
                        
                        
                          get
                        
                        
                          '
                        
                        
                          )

                        
                        
                          27
                        
                        
                          28
                        
                        
                          class
                        
                        
                           Room:

                        
                        
                          29
                        
                             name=
                        
                          Foo()

                        
                        
                          30
                        
                        
                          def
                        
                        
                          __init__
                        
                        
                          (self,name,width,length):

                        
                        
                          31
                        
                                 self.name=
                        
                          name

                        
                        
                          32
                        
                                 self.width=
                        
                          width

                        
                        
                          33
                        
                                 self.length=
                        
                          length

                        
                        
                          34
                        
                        
                          35
                        
                        
                          36
                        
                        
                          37
                        
                        
                          #
                        
                        
                           name是一个非数据描述符,因为name=Foo()而Foo没有实现set方法,因而比实例属性有更低的优先级
                        
                        
                          38
                        
                        
                          #
                        
                        
                           对实例的属性操作,触发的都是实例自己的
                        
                        
                          39
                        
                         r1=Room(
                        
                          '
                        
                        
                          厕所
                        
                        
                          '
                        
                        ,1,1
                        
                          )

                        
                        
                          40
                        
                        
                          r1.name

                        
                        
                          41
                        
                         r1.name=
                        
                          '
                        
                        
                          厨房
                        
                        
                          '
                        
                      

非数据描述符>找不到

                        
                           1
                        
                        
                          class
                        
                        
                           Foo:

                        
                        
                           2
                        
                        
                          def
                        
                        
                           func(self):

                        
                        
                           3
                        
                        
                          print
                        
                        (
                        
                          '
                        
                        
                          我胡汉三又回来了
                        
                        
                          '
                        
                        
                          )

                        
                        
                           4
                        
                        
                           5
                        
                        
                           6
                        
                        
                          def
                        
                        
                          __getattr__
                        
                        
                          (self, item):

                        
                        
                           7
                        
                        
                          print
                        
                        (
                        
                          '
                        
                        
                          找不到了当然是来找我啦
                        
                        
                          '
                        
                        
                          ,item)

                        
                        
                           8
                        
                        
                           9
                        
                        
                          10
                        
                         f1=
                        
                          Foo()

                        
                        
                          11
                        
                         f1.xxxxxxxxxxx    
                        
                          #
                        
                        
                           找不到,调用__getattr__方法
                        
                      
 
5.描述符的使用
    众所周知,python是弱类型语言,即参数的赋值没有类型限制,下面我们通过描述符机制来实现类型限制功能
                          
                             1
                          
                          
                            class
                          
                          
                             Typed(object):

                          
                          
                             2
                          
                          
                            def
                          
                          
                            __init__
                          
                          
                            (self,name,expected_type):

                          
                          
                             3
                          
                                   self.name=
                          
                            name

                          
                          
                             4
                          
                                   self.expected_type=
                          
                            expected_type

                          
                          
                             5
                          
                          
                             6
                          
                          
                            def
                          
                          
                            __get__
                          
                          
                            (self, instance, owner):

                          
                          
                             7
                          
                          
                            print
                          
                          (
                          
                            '
                          
                          
                            get--->
                          
                          
                            '
                          
                          
                            ,instance,owner)

                          
                          
                             8
                          
                          
                            if
                          
                           instance 
                          
                            is
                          
                          
                             None:

                          
                          
                             9
                          
                          
                            return
                          
                          
                             self

                          
                          
                            10
                          
                          
                            return
                          
                           instance.
                          
                            __dict__
                          
                          
                            [self.name]

                          
                          
                            11
                          
                          
                            12
                          
                          
                            def
                          
                          
                            __set__
                          
                          
                            (self, instance, value):

                          
                          
                            13
                          
                          
                            print
                          
                          (
                          
                            '
                          
                          
                            set--->
                          
                          
                            '
                          
                          
                            ,instance,value)

                          
                          
                            14
                          
                          
                            if
                          
                          
                            not
                          
                          
                             isinstance(value,self.expected_type):

                          
                          
                            15
                          
                          
                            raise
                          
                           TypeError(
                          
                            '
                          
                          
                            Expected %s
                          
                          
                            '
                          
                           %
                          
                            str(self.expected_type))

                          
                          
                            16
                          
                                   instance.
                          
                            __dict__
                          
                          [self.name]=
                          
                            value

                          
                          
                            17
                          
                          
                            18
                          
                          
                            def
                          
                          
                            __delete__
                          
                          
                            (self, instance):

                          
                          
                            19
                          
                          
                            print
                          
                          (
                          
                            '
                          
                          
                            delete--->
                          
                          
                            '
                          
                          
                            ,instance)

                          
                          
                            20
                          
                                   instance.
                          
                            __dict__
                          
                          
                            .pop(self.name)

                          
                          
                            21
                          
                          
                            22
                          
                          
                            23
                          
                          
                            class
                          
                          
                             People(object):

                          
                          
                            24
                          
                               name=Typed(
                          
                            '
                          
                          
                            name
                          
                          
                            '
                          
                          
                            ,str)

                          
                          
                            25
                          
                               age=Typed(
                          
                            '
                          
                          
                            name
                          
                          
                            '
                          
                          
                            ,int)

                          
                          
                            26
                          
                               salary=Typed(
                          
                            '
                          
                          
                            name
                          
                          
                            '
                          
                          
                            ,float)

                          
                          
                            27
                          
                          
                            def
                          
                          
                            __init__
                          
                          
                            (self,name,age,salary):

                          
                          
                            28
                          
                                   self.name=
                          
                            name

                          
                          
                            29
                          
                                   self.age=
                          
                            age

                          
                          
                            30
                          
                                   self.salary=
                          
                            salary

                          
                          
                            31
                          
                          
                            32
                          
                           p1=People(123,18,3333.3
                          
                            )

                          
                          
                            33
                          
                           p1=People(
                          
                            '
                          
                          
                            egon
                          
                          
                            '
                          
                          ,
                          
                            '
                          
                          
                            18
                          
                          
                            '
                          
                          ,3333.3
                          
                            )

                          
                          
                            34
                          
                           p1=People(
                          
                            '
                          
                          
                            egon
                          
                          
                            '
                          
                          ,18,3333)
                        

6.类装饰器

                          
                             1
                          
                          
                            #
                          
                          
                             检查对象属性的类型
                          
                          
                             2
                          
                          
                            class
                          
                          
                             Typed(object):

                          
                          
                             3
                          
                          
                            def
                          
                          
                            __init__
                          
                          
                            (self, name, expected_type):

                          
                          
                             4
                          
                                   self.name =
                          
                             name

                          
                          
                             5
                          
                                   self.expected_type =
                          
                             expected_type

                          
                          
                             6
                          
                          
                             7
                          
                          
                            def
                          
                          
                            __get__
                          
                          
                            (self, instance, owner):

                          
                          
                             8
                          
                          
                            print
                          
                          (
                          
                            '
                          
                          
                            get--->
                          
                          
                            '
                          
                          
                            , instance, owner)

                          
                          
                             9
                          
                          
                            if
                          
                           instance 
                          
                            is
                          
                          
                             None:

                          
                          
                            10
                          
                          
                            return
                          
                          
                             self

                          
                          
                            11
                          
                          
                            return
                          
                           instance.
                          
                            __dict__
                          
                          
                            [self.name]

                          
                          
                            12
                          
                          
                            13
                          
                          
                            def
                          
                          
                            __set__
                          
                          
                            (self, instance, value):

                          
                          
                            14
                          
                          
                            print
                          
                          (
                          
                            '
                          
                          
                            set--->
                          
                          
                            '
                          
                          
                            , instance, value)

                          
                          
                            15
                          
                          
                            if
                          
                          
                            not
                          
                          
                             isinstance(value,self.expected_type):

                          
                          
                            16
                          
                          
                            raise
                          
                           TypeError(
                          
                            '
                          
                          
                            Expected %s
                          
                          
                            '
                          
                           %
                          
                             str(self.expected_type))

                          
                          
                            17
                          
                                   instance.
                          
                            __dict__
                          
                          [self.name] =
                          
                             value

                          
                          
                            18
                          
                          
                            19
                          
                          
                            def
                          
                          
                            __delete__
                          
                          
                            (self, instance):

                          
                          
                            20
                          
                          
                            print
                          
                          (
                          
                            '
                          
                          
                            delete--->
                          
                          
                            '
                          
                          
                            , instance)

                          
                          
                            21
                          
                                   instance.
                          
                            __dict__
                          
                          
                            .pop(self.name)

                          
                          
                            22
                          
                          
                            23
                          
                          
                            24
                          
                          
                            def
                          
                           typeassert(**
                          
                            kwargs):

                          
                          
                            25
                          
                          
                            def
                          
                          
                             decorate(cls):

                          
                          
                            26
                          
                          
                            print
                          
                          (
                          
                            '
                          
                          
                            类的装饰器开始运行啦------>
                          
                          
                            '
                          
                          
                            ,kwargs)

                          
                          
                            27
                          
                          
                            for
                          
                           name,expected_type 
                          
                            in
                          
                          
                             kwargs.items():

                          
                          
                            28
                          
                          
                                        setattr(cls,name,Typed(name,expected_type))

                          
                          
                            29
                          
                          
                            return
                          
                          
                             cls

                          
                          
                            30
                          
                          
                            return
                          
                          
                             decorate

                          
                          
                            31
                          
                          
                            32
                          
                          
                            #
                          
                          
                             有参:1.运行typeassert(...)返回结果是decorate,此时参数都传给kwargs 2.People=decorate(People)
                          
                          
                            33
                          
                           @typeassert(name=str,age=int,salary=
                          
                            float)  

                          
                          
                            34
                          
                          
                            class
                          
                          
                             People:

                          
                          
                            35
                          
                          
                            def
                          
                          
                            __init__
                          
                          
                            (self,name,age,salary):

                          
                          
                            36
                          
                                   self.name=
                          
                            name

                          
                          
                            37
                          
                                   self.age=
                          
                            age

                          
                          
                            38
                          
                                   self.salary=
                          
                            salary

                          
                          
                            39
                          
                          
                            40
                          
                          
                            41
                          
                          
                            print
                          
                          (People.
                          
                            __dict__
                          
                          
                            )

                          
                          
                            42
                          
                           p1 = People(
                          
                            '
                          
                          
                            egon
                          
                          
                            '
                          
                          , 18, 3333.3)
                        
7.描述符总结
    描述符是可以实现大部分python类特性中的底层魔法,包括@classmethod,@staticmethd,@property甚至是__slots__属性.
    描述符是很多高级库和框架的重要工具之一,描述符通常是使用到装饰器或者元类的大型框架中的一个组件.
8.描述符的案例
    利用描述符,实现自定制的property,计算房屋面积
                              
                                 1
                              
                              
                                class
                              
                              
                                 LazyProperty(object):

                              
                              
                                 2
                              
                              
                                 3
                              
                              
                                def
                              
                              
                                __init__
                              
                              
                                (self, func):

                              
                              
                                 4
                              
                                       self.func =
                              
                                 func

                              
                              
                                 5
                              
                              
                                 6
                              
                              
                                def
                              
                              
                                __get__
                              
                              
                                (self, instance, owner):

                              
                              
                                 7
                              
                              
                                #
                              
                              
                                 print(self.func)
                              
                              
                                 8
                              
                              
                                #
                              
                              
                                 print(instance)
                              
                              
                                 9
                              
                              
                                #
                              
                              
                                 print(owner)
                              
                              
                                10
                              
                              
                                #
                              
                              
                                 print("haha")
                              
                              
                                11
                              
                              
                                return
                              
                              
                                 self.func(instance)

                              
                              
                                12
                              
                              
                                13
                              
                              
                                14
                              
                              
                                class
                              
                              
                                 Room(object):

                              
                              
                                15
                              
                              
                                16
                              
                              
                                def
                              
                              
                                __init__
                              
                              
                                (self, name, width, length):

                              
                              
                                17
                              
                                       self.name =
                              
                                 name

                              
                              
                                18
                              
                                       self.width =
                              
                                 width

                              
                              
                                19
                              
                                       self.length =
                              
                                 length

                              
                              
                                20
                              
                              
                                21
                              
                                   @LazyProperty        
                              
                                #
                              
                              
                                 相当于 area = LazyProperty(area)
                              
                              
                                22
                              
                              
                                def
                              
                              
                                 area(self):

                              
                              
                                23
                              
                              
                                return
                              
                               self.width *
                              
                                 self.length

                              
                              
                                24
                              
                              
                                25
                              
                              
                                26
                              
                               r1 = Room(
                              
                                "
                              
                              
                                卧室
                              
                              
                                "
                              
                              , 2, 3
                              
                                )

                              
                              
                                27
                              
                              
                                print
                              
                              (r1.area)
                            

实现缓存计算的功能

                              
                                 1
                              
                              
                                class
                              
                              
                                 Lazyproperty:

                              
                              
                                 2
                              
                              
                                def
                              
                              
                                __init__
                              
                              
                                (self,func):

                              
                              
                                 3
                              
                                       self.func=
                              
                                func

                              
                              
                                 4
                              
                              
                                 5
                              
                              
                                def
                              
                              
                                __get__
                              
                              
                                (self, instance, owner):

                              
                              
                                 6
                              
                              
                                print
                              
                              (
                              
                                '
                              
                              
                                这是我们自己定制的静态属性,r1.area实际是要执行r1.area()
                              
                              
                                '
                              
                              
                                )

                              
                              
                                 7
                              
                              
                                if
                              
                               instance 
                              
                                is
                              
                              
                                 None:

                              
                              
                                 8
                              
                              
                                return
                              
                              
                                 self

                              
                              
                                 9
                              
                              
                                else
                              
                              
                                :

                              
                              
                                10
                              
                              
                                print
                              
                              (
                              
                                '
                              
                              
                                --->
                              
                              
                                '
                              
                              
                                )

                              
                              
                                11
                              
                                           value =
                              
                                 self.func(instance)

                              
                              
                                12
                              
                                           setattr(instance, self.func.
                              
                                __name__
                              
                              ,value) 
                              
                                #
                              
                              
                                计算一次就缓存到实例的属性字典中
                              
                              
                                13
                              
                              
                                return
                              
                              
                                 value

                              
                              
                                14
                              
                              
                                15
                              
                              
                                class
                              
                              
                                 Room:

                              
                              
                                16
                              
                              
                                def
                              
                              
                                __init__
                              
                              
                                (self,name,width,length):

                              
                              
                                17
                              
                                       self.name=
                              
                                name

                              
                              
                                18
                              
                                       self.width=
                              
                                width

                              
                              
                                19
                              
                                       self.length=
                              
                                length

                              
                              
                                20
                              
                              
                                21
                              
                                   @Lazyproperty 
                              
                                #
                              
                              
                                area=Lazyproperty(area) 相当于'定义了一个类属性,即描述符'
                              
                              
                                22
                              
                              
                                def
                              
                              
                                 area(self):

                              
                              
                                23
                              
                              
                                return
                              
                               self.width *
                              
                                 self.length

                              
                              
                                24
                              
                              
                                25
                              
                               r1=Room(
                              
                                '
                              
                              
                                alex
                              
                              
                                '
                              
                              ,1,1
                              
                                )

                              
                              
                                26
                              
                              
                                print
                              
                              (r1.area) 
                              
                                #
                              
                              
                                先从自己的属性字典找,没有再去类的中找,然后出发了area的__get__方法
                              
                              
                                27
                              
                              
                                print
                              
                              (r1.area) 
                              
                                #
                              
                              
                                先从自己的属性字典找,找到了,是上次计算的结果,这样就不用每执行一次都去计算
                              
                            

做了一点小改动,缓存计算的功能就失效了

                              
                                 1
                              
                              
                                #
                              
                              
                                 缓存不起来了
                              
                              
                                 2
                              
                              
                                 3
                              
                              
                                class
                              
                              
                                 Lazyproperty:

                              
                              
                                 4
                              
                              
                                def
                              
                              
                                __init__
                              
                              
                                (self,func):

                              
                              
                                 5
                              
                                       self.func=
                              
                                func

                              
                              
                                 6
                              
                              
                                 7
                              
                              
                                def
                              
                              
                                __get__
                              
                              
                                (self, instance, owner):

                              
                              
                                 8
                              
                              
                                print
                              
                              (
                              
                                '
                              
                              
                                这是我们自己定制的静态属性,r1.area实际是要执行r1.area()
                              
                              
                                '
                              
                              
                                )

                              
                              
                                 9
                              
                              
                                if
                              
                               instance 
                              
                                is
                              
                              
                                 None:

                              
                              
                                10
                              
                              
                                return
                              
                              
                                 self

                              
                              
                                11
                              
                              
                                else
                              
                              
                                :

                              
                              
                                12
                              
                                           value=
                              
                                self.func(instance)

                              
                              
                                13
                              
                                           instance.
                              
                                __dict__
                              
                              [self.func.
                              
                                __name__
                              
                              ]=
                              
                                value

                              
                              
                                14
                              
                              
                                return
                              
                              
                                 value

                              
                              
                                15
                              
                              
                                #
                              
                              
                                 return self.func(instance) #此时你应该明白,到底是谁在为你做自动传递self的事情
                              
                              
                                16
                              
                              
                                17
                              
                              
                                def
                              
                              
                                __set__
                              
                              
                                (self, instance, value):

                              
                              
                                18
                              
                              
                                print
                              
                              (
                              
                                '
                              
                              
                                hahahahahah
                              
                              
                                '
                              
                              
                                )

                              
                              
                                19
                              
                              
                                20
                              
                              
                                class
                              
                              
                                 Room:

                              
                              
                                21
                              
                              
                                def
                              
                              
                                __init__
                              
                              
                                (self,name,width,length):

                              
                              
                                22
                              
                                       self.name=
                              
                                name

                              
                              
                                23
                              
                                       self.width=
                              
                                width

                              
                              
                                24
                              
                                       self.length=
                              
                                length

                              
                              
                                25
                              
                              
                                26
                              
                                   @Lazyproperty 
                              
                                #
                              
                              
                                area=Lazyproperty(area) 相当于定义了一个类属性,即描述符
                              
                              
                                27
                              
                              
                                def
                              
                              
                                 area(self):

                              
                              
                                28
                              
                              
                                return
                              
                               self.width *
                              
                                 self.length

                              
                              
                                29
                              
                              
                                30
                              
                              
                                print
                              
                              (Room.
                              
                                __dict__
                              
                              
                                )

                              
                              
                                31
                              
                               r1=Room(
                              
                                '
                              
                              
                                alex
                              
                              
                                '
                              
                              ,1,1
                              
                                )

                              
                              
                                32
                              
                              
                                print
                              
                              
                                (r1.area)

                              
                              
                                33
                              
                              
                                print
                              
                              
                                (r1.area)

                              
                              
                                34
                              
                              
                                print
                              
                              
                                (r1.area)

                              
                              
                                35
                              
                              
                                print
                              
                              (r1.area) 
                              
                                #
                              
                              
                                 缓存功能失效,每次都去找描述符了,为何,因为描述符实现了set方法,它由非数据描述符变成了数据描述符,数据描述符比实例属性有更高的优先级,因而所有的属性操作都去找描述符了
                              
                            

2.11 上下文管理协议(__enter__和__exit__)

上下文管理协议: 即with语句,为了让一个对象兼容with语句,必须在这个对象的类中声明__enter__和__exit__方法

                              
                                 1
                              
                              
                                #
                              
                              
                                 上下文管理协议
                              
                              
                                 2
                              
                              
                                class
                              
                              
                                 Open:

                              
                              
                                 3
                              
                              
                                def
                              
                              
                                __init__
                              
                              
                                (self,name):

                              
                              
                                 4
                              
                                       self.name=
                              
                                name

                              
                              
                                 5
                              
                              
                                 6
                              
                              
                                def
                              
                              
                                __enter__
                              
                              
                                (self):

                              
                              
                                 7
                              
                              
                                print
                              
                              (
                              
                                '
                              
                              
                                出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量
                              
                              
                                '
                              
                              
                                )

                              
                              
                                 8
                              
                              
                                #
                              
                              
                                 return self
                              
                              
                                 9
                              
                              
                                10
                              
                              
                                def
                              
                              
                                __exit__
                              
                              
                                (self, exc_type, exc_val, exc_tb):

                              
                              
                                11
                              
                              
                                print
                              
                              (
                              
                                '
                              
                              
                                with中代码块执行完毕时执行我啊
                              
                              
                                '
                              
                              
                                )

                              
                              
                                12
                              
                              
                                13
                              
                              
                                14
                              
                              
                                #
                              
                              
                                 with Open--》触发Open.__enter__,拿到返回值
                              
                              
                                15
                              
                              
                                #
                              
                              
                                 as f ---> f = __enter__的返回值
                              
                              
                                16
                              
                              
                                #
                              
                              
                                 with Open('a.txt') as f =======> f = Open('a.txt')
                              
                              
                                17
                              
                               with Open(
                              
                                '
                              
                              
                                a.txt
                              
                              
                                '
                              
                              
                                ) as f:

                              
                              
                                18
                              
                              
                                print
                              
                              (
                              
                                '
                              
                              
                                =====>执行代码块
                              
                              
                                '
                              
                              
                                )

                              
                              
                                19
                              
                              
                                #
                              
                              
                                 print(f,f.name)
                              
                            

__exit__()中的三个参数分别代表异常类型,异常值和追溯信息,with语句中代码块出现异常,则with后的代码都无法执行

                              
                                 1
                              
                              
                                class
                              
                              
                                 Open:

                              
                              
                                 2
                              
                              
                                def
                              
                              
                                __init__
                              
                              
                                (self,name):

                              
                              
                                 3
                              
                                       self.name=
                              
                                name

                              
                              
                                 4
                              
                              
                                 5
                              
                              
                                def
                              
                              
                                __enter__
                              
                              
                                (self):

                              
                              
                                 6
                              
                              
                                print
                              
                              (
                              
                                '
                              
                              
                                出现with语句,对象的__enter__被触发,有返回值则赋值给as声明的变量
                              
                              
                                '
                              
                              
                                )

                              
                              
                                 7
                              
                              
                                 8
                              
                              
                                def
                              
                              
                                __exit__
                              
                              
                                (self, exc_type, exc_val, exc_tb):

                              
                              
                                 9
                              
                              
                                print
                              
                              (
                              
                                '
                              
                              
                                with中代码块执行完毕时执行我啊
                              
                              
                                '
                              
                              
                                )

                              
                              
                                10
                              
                              
                                print
                              
                              
                                (exc_type)

                              
                              
                                11
                              
                              
                                print
                              
                              
                                (exc_val)

                              
                              
                                12
                              
                              
                                print
                              
                              
                                (exc_tb)

                              
                              
                                13
                              
                              
                                14
                              
                              
                                15
                              
                              
                                16
                              
                               with Open(
                              
                                '
                              
                              
                                a.txt
                              
                              
                                '
                              
                              
                                ) as f:

                              
                              
                                17
                              
                              
                                print
                              
                              (
                              
                                '
                              
                              
                                =====>执行代码块
                              
                              
                                '
                              
                              
                                )

                              
                              
                                18
                              
                              
                                raise
                              
                               AttributeError(
                              
                                '
                              
                              
                                ***着火啦,救火啊***
                              
                              
                                '
                              
                              
                                )

                              
                              
                                19
                              
                              
                                print
                              
                              (
                              
                                '
                              
                              
                                0
                              
                              
                                '
                              
                              *100) 
                              
                                #
                              
                              
                                ------------------------------->不会执行
                              
                            

如果__exit__()返回值为True,那么异常会被清空,就好像啥都没发生一样,with后的语句正常执行

                              
                                 1
                              
                              
                                class
                              
                              
                                 Open(object):

                              
                              
                                 2
                              
                              
                                 3
                              
                              
                                def
                              
                              
                                __init__
                              
                              
                                (self, name):

                              
                              
                                 4
                              
                                       self.name =
                              
                                 name

                              
                              
                                 5
                              
                              
                                 6
                              
                              
                                def
                              
                              
                                __enter__
                              
                              
                                (self):

                              
                              
                                 7
                              
                              
                                print
                              
                              (
                              
                                "
                              
                              
                                执行enter
                              
                              
                                "
                              
                              
                                )

                              
                              
                                 8
                              
                              
                                return
                              
                              
                                 self

                              
                              
                                 9
                              
                              
                                10
                              
                              
                                def
                              
                              
                                __exit__
                              
                              
                                (self, exc_type, exc_val, exc_tb):

                              
                              
                                11
                              
                              
                                print
                              
                              (
                              
                                "
                              
                              
                                执行exit
                              
                              
                                "
                              
                              
                                )

                              
                              
                                12
                              
                              
                                print
                              
                              
                                (exc_type)

                              
                              
                                13
                              
                              
                                print
                              
                              
                                (exc_val)

                              
                              
                                14
                              
                              
                                print
                              
                              
                                (exc_tb)

                              
                              
                                15
                              
                              
                                return
                              
                               True     
                              
                                #
                              
                              
                                 包容了with中的异常,返回true,会正常结束with语句,会继续执行with后的语句;如果不包容异常,则出现异常就会停止
                              
                              
                                16
                              
                              
                                17
                              
                              
                                18
                              
                               with Open(
                              
                                '
                              
                              
                                aa
                              
                              
                                '
                              
                              
                                ) as f:

                              
                              
                                19
                              
                              
                                print
                              
                              
                                (f)

                              
                              
                                20
                              
                              
                                raise
                              
                               Exception(
                              
                                "
                              
                              
                                aa
                              
                              
                                "
                              
                              
                                )

                              
                              
                                21
                              
                              
                                22
                              
                              
                                print
                              
                              (
                              
                                "
                              
                              
                                bbb
                              
                              
                                "
                              
                              )
                            
__exit__语句的执行结束,表示with语句的执行结束
 
使用上下文管理协议的好处:
1. 使用with语句的目的就是把代码块放入with中执行,with结束后,自动完成清理工作,无须手动干预
2. 在需要管理一些资源比如文件,网络连接和锁的编程环境中,可以在__exit__中定制自动释放资源的机制,你无须再去关系这个问题,这将大有用处

2.12 __dict__

类或对象中的所有成员
我们知道:类的普通字段属于对象;类中的静态字段和方法等属于类,即:
                                
                                   1
                                
                                
                                  class
                                
                                
                                   Province:

                                
                                
                                   2
                                
                                
                                   3
                                
                                     country = 
                                
                                  '
                                
                                
                                  China
                                
                                
                                  '
                                
                                
                                   4
                                
                                
                                   5
                                
                                
                                  def
                                
                                
                                  __init__
                                
                                
                                  (self, name, count):

                                
                                
                                   6
                                
                                         self.name =
                                
                                   name

                                
                                
                                   7
                                
                                         self.count =
                                
                                   count

                                
                                
                                   8
                                
                                
                                   9
                                
                                
                                  def
                                
                                 func(self, *args, **
                                
                                  kwargs):

                                
                                
                                  10
                                
                                
                                  print
                                
                                
                                  '
                                
                                
                                  func
                                
                                
                                  '
                                
                                
                                  11
                                
                                
                                  12
                                
                                
                                  13
                                
                                
                                  #
                                
                                
                                   获取类的成员,即:静态字段、方法、
                                
                                
                                  14
                                
                                
                                  print
                                
                                 Province.
                                
                                  __dict__
                                
                                
                                  15
                                
                                
                                  #
                                
                                
                                   输出:{'country': 'China', '__module__': '__main__', 'func': 
                                  
                                    , '__init__': 
                                    
                                      , '__doc__': None}
                                    
                                  
                                
                                
                                  16
                                
                                
                                  17
                                
                                
                                  18
                                
                                 obj1 = Province(
                                
                                  '
                                
                                
                                  HeBei
                                
                                
                                  '
                                
                                ,10000
                                
                                  )

                                
                                
                                  19
                                
                                
                                  print
                                
                                 obj1.
                                
                                  __dict__
                                
                                
                                  20
                                
                                
                                  #
                                
                                
                                   获取 对象obj1 的成员
                                
                                
                                  21
                                
                                
                                  #
                                
                                
                                   输出:{'count': 10000, 'name': 'HeBei'}
                                
                                
                                  22
                                
                                
                                  23
                                
                                
                                  24
                                
                                 obj2 = Province(
                                
                                  '
                                
                                
                                  HeNan
                                
                                
                                  '
                                
                                , 3888
                                
                                  )

                                
                                
                                  25
                                
                                
                                  print
                                
                                 obj2.
                                
                                  __dict__
                                
                                
                                  26
                                
                                
                                  #
                                
                                
                                   获取 对象obj1 的成员
                                
                                
                                  27
                                
                                
                                  #
                                
                                
                                   输出:{'count': 3888, 'name': 'HeNan'}
                                
                              

2.13 __new__ 构造方法

 __init__ 初始化方法

                                
                                   1
                                
                                
                                  class
                                
                                
                                   Single(object):

                                
                                
                                   2
                                
                                
                                   3
                                
                                
                                  __instance
                                
                                 =
                                
                                   None

                                
                                
                                   4
                                
                                
                                   5
                                
                                
                                  def
                                
                                
                                  __new__
                                
                                (cls, *args, **
                                
                                  kwargs):

                                
                                
                                   6
                                
                                
                                  if
                                
                                 cls.
                                
                                  __instance
                                
                                
                                  is
                                
                                
                                   None:

                                
                                
                                   7
                                
                                             cls.
                                
                                  __instance
                                
                                 = object.
                                
                                  __new__
                                
                                
                                  (cls)

                                
                                
                                   8
                                
                                
                                  return
                                
                                 cls.
                                
                                  __instance
                                
                                
                                   9
                                
                                
                                  10
                                
                                
                                  11
                                
                                
                                  def
                                
                                
                                  __init__
                                
                                
                                  (self):

                                
                                
                                  12
                                
                                
                                  print
                                
                                (
                                
                                  "
                                
                                
                                  init
                                
                                
                                  "
                                
                                
                                  )

                                
                                
                                  13
                                
                                
                                  14
                                
                                
                                  15
                                
                                
                                  #
                                
                                
                                   开辟一个空间,属于对象的
                                
                                
                                  16
                                
                                
                                  #
                                
                                
                                   把对象的空间传给self,执行init
                                
                                
                                  17
                                
                                
                                  #
                                
                                
                                   将这个对象的空间返回给调用者
                                
                                
                                  18
                                
                                 obj =
                                
                                   Single()

                                
                                
                                  19
                                
                                 obj2 =
                                
                                   Single()

                                
                                
                                  20
                                
                                
                                  print
                                
                                
                                  (id(obj), id(obj2))

                                
                                
                                  21
                                
                                
                                  22
                                
                                
                                  23
                                
                                
                                  #
                                
                                
                                   单例:如果一个类,从头到尾只能有一个实例,那么这个类就是一个单例类
                                
                              

2.14 __len__

                                
                                   1
                                
                                
                                  class
                                
                                
                                   A:

                                
                                
                                   2
                                
                                
                                  def
                                
                                
                                  __init__
                                
                                
                                  (self):

                                
                                
                                   3
                                
                                         self.a = 1

                                
                                   4
                                
                                         self.b = 2

                                
                                   5
                                
                                
                                   6
                                
                                
                                   7
                                
                                
                                  def
                                
                                
                                  __len__
                                
                                
                                  (self):

                                
                                
                                   8
                                
                                
                                  return
                                
                                 len(self.
                                
                                  __dict__
                                
                                
                                  )

                                
                                
                                   9
                                
                                 a =
                                
                                   A()

                                
                                
                                  10
                                
                                
                                  print
                                
                                (len(a))
                              

2.15 __hash__

                                
                                   1
                                
                                
                                  class
                                
                                
                                   A:

                                
                                
                                   2
                                
                                
                                  def
                                
                                
                                  __init__
                                
                                
                                  (self):

                                
                                
                                   3
                                
                                         self.a = 1

                                
                                   4
                                
                                         self.b = 2

                                
                                   5
                                
                                
                                   6
                                
                                
                                   7
                                
                                
                                  def
                                
                                
                                  __hash__
                                
                                
                                  (self):

                                
                                
                                   8
                                
                                
                                  return
                                
                                 hash(str(self.a)+
                                
                                  str(self.b))

                                
                                
                                   9
                                
                                 a =
                                
                                   A()

                                
                                
                                  10
                                
                                
                                  print
                                
                                (hash(a))
                              

2.16 __eq__

                                
                                   1
                                
                                
                                  class
                                
                                
                                   A:

                                
                                
                                   2
                                
                                
                                  def
                                
                                
                                  __init__
                                
                                
                                  (self):

                                
                                
                                   3
                                
                                         self.a = 1

                                
                                   4
                                
                                         self.b = 2

                                
                                   5
                                
                                
                                   6
                                
                                
                                   7
                                
                                
                                  def
                                
                                
                                  __eq__
                                
                                
                                  (self,obj):

                                
                                
                                   8
                                
                                
                                  if
                                
                                  self.a == obj.a 
                                
                                  and
                                
                                 self.b ==
                                
                                   obj.b:

                                
                                
                                   9
                                
                                
                                  return
                                
                                
                                   True

                                
                                
                                  10
                                
                                 a =
                                
                                   A()

                                
                                
                                  11
                                
                                 b =
                                
                                   A()

                                
                                
                                  12
                                
                                
                                  print
                                
                                (a == b)
                              

2.17 __bool__

bool(x)  的背后,调用的就是__bool__()方法. 如果不存在 __bool__ 方法, 那么 bool(x) 会尝试调用 x.__len__()。 若返回 0, 则 bool 会返回False; 否则返回 True。

                                
                                  from
                                
                                 math 
                                
                                  import
                                
                                
                                   hypot





                                
                                
                                  class
                                
                                
                                   Vector:
    
                                
                                
                                  """
                                
                                
                                  
    二维向量
    
                                
                                
                                  """
                                
                                
                                  def
                                
                                
                                  __init__
                                
                                
                                  (self, x, y):
        self.x 
                                
                                =
                                
                                   x
        self.y 
                                
                                =
                                
                                   y


    
                                
                                
                                  def
                                
                                
                                  __repr__
                                
                                
                                  (self):
        
                                
                                
                                  return
                                
                                
                                  '
                                
                                
                                  Vector(%s, %s)
                                
                                
                                  '
                                
                                 %
                                
                                   (self.x, self.y)


    
                                
                                
                                  def
                                
                                
                                  __abs__
                                
                                
                                  (self):
        
                                
                                
                                  return
                                
                                
                                   hypot(self.x, self.y)


    
                                
                                
                                  def
                                
                                
                                  __bool__
                                
                                
                                  (self):
        
                                
                                
                                  return
                                
                                
                                   bool(abs(self))


    
                                
                                
                                  def
                                
                                
                                  __add__
                                
                                
                                  (self, other):
        x 
                                
                                = self.x +
                                
                                   other.x
        y 
                                
                                = self.y +
                                
                                   other.y
        
                                
                                
                                  return
                                
                                
                                   Vector(x, y)


    
                                
                                
                                  def
                                
                                
                                  __mul__
                                
                                
                                  (self, other):
        
                                
                                
                                  return
                                
                                 Vector(self.x * other, self.y * other)
                              

三、加工数据类型

包装:python为大家提供了标准数据类型,以及丰富的内置方法,其实在很多场景下我们都需要基于标准数据类型来定制我们自己的数据类型,新增/改写方法,这就用到了我们刚学的继承/派生知识(其他的标准类型均可以通过下面的方式进行二次加工)

                                
                                   1
                                
                                
                                  class
                                
                                
                                   List(list):

                                
                                
                                   2
                                
                                
                                   3
                                
                                
                                  def
                                
                                
                                   show_middle(self):

                                
                                
                                   4
                                
                                         mid_index = int(len(self) / 2
                                
                                  )

                                
                                
                                   5
                                
                                
                                  return
                                
                                
                                   self[mid_index]

                                
                                
                                   6
                                
                                
                                   7
                                
                                
                                  #
                                
                                
                                   对append方法进行重写,只允许添加字符串类型
                                
                                
                                   8
                                
                                
                                  def
                                
                                
                                   append(self, p_object):

                                
                                
                                   9
                                
                                
                                  if
                                
                                 type(p_object) 
                                
                                  is
                                
                                
                                   str:

                                
                                
                                  10
                                
                                
                                              super(List, self).append(p_object)

                                
                                
                                  11
                                
                                
                                  else
                                
                                
                                  :

                                
                                
                                  12
                                
                                
                                  print
                                
                                (
                                
                                  '
                                
                                
                                  只能添加字符串类型
                                
                                
                                  '
                                
                                
                                  )

                                
                                
                                  13
                                
                                
                                  14
                                
                                
                                  15
                                
                                 l1 = List(
                                
                                  "
                                
                                
                                  hello world
                                
                                
                                  "
                                
                                
                                  )

                                
                                
                                  16
                                
                                
                                  print
                                
                                
                                  (type(l1))

                                
                                
                                  17
                                
                                
                                  print
                                
                                
                                  (l1.show_middle())

                                
                                
                                  18
                                
                                
                                  19
                                
                                 l1.append(
                                
                                  "
                                
                                
                                  aa
                                
                                
                                  "
                                
                                
                                  )

                                
                                
                                  20
                                
                                
                                  print
                                
                                (l1)
                              
授权:授权是包装的一个特性, 包装一个类型通常是对已存在的类型的一些定制,这种做法可以新建,修改或删除原有产品的功能。其它的则保持原样。授权的过程,即是所有更新的功能都是由新类的某部分来处理,但已存在的功能就授权给对象的默认属性。
 
实现授权的关键点就是覆盖__getattr__方法
 
文件读写实现授权:
                                  
                                     1
                                  
                                  
                                    class
                                  
                                  
                                     FileHandle(object):

                                  
                                  
                                     2
                                  
                                  
                                     3
                                  
                                  
                                    def
                                  
                                  
                                    __init__
                                  
                                  (self, filename, mode=
                                  
                                    '
                                  
                                  
                                    r
                                  
                                  
                                    '
                                  
                                  , encoding=
                                  
                                    '
                                  
                                  
                                    utf-8
                                  
                                  
                                    '
                                  
                                  
                                    ):

                                  
                                  
                                     4
                                  
                                  
                                    #
                                  
                                  
                                     self.filename = filename
                                  
                                  
                                     5
                                  
                                           self.file = open(filename, mode, encoding=
                                  
                                    encoding)

                                  
                                  
                                     6
                                  
                                           self.mode =
                                  
                                     mode

                                  
                                  
                                     7
                                  
                                           self.encoding =
                                  
                                     encoding

                                  
                                  
                                     8
                                  
                                  
                                     9
                                  
                                  
                                    def
                                  
                                  
                                     write(self, data):

                                  
                                  
                                    10
                                  
                                           t = time.strftime(
                                  
                                    '
                                  
                                  
                                    %Y-%m-%d %X
                                  
                                  
                                    '
                                  
                                  
                                    )

                                  
                                  
                                    11
                                  
                                           self.file.write(
                                  
                                    '
                                  
                                  
                                    %s %s
                                  
                                  
                                    '
                                  
                                   %
                                  
                                     (t, data))

                                  
                                  
                                    12
                                  
                                  
                                    13
                                  
                                  
                                    def
                                  
                                  
                                    __getattr__
                                  
                                  
                                    (self, item):

                                  
                                  
                                    14
                                  
                                  
                                    return
                                  
                                  
                                     getattr(self.file, item)

                                  
                                  
                                    15
                                  
                                  
                                    16
                                  
                                  
                                    17
                                  
                                   f1 = FileHandle(
                                  
                                    '
                                  
                                  
                                    a.txt
                                  
                                  
                                    '
                                  
                                  , 
                                  
                                    '
                                  
                                  
                                    w
                                  
                                  
                                    '
                                  
                                  
                                    )

                                  
                                  
                                    18
                                  
                                  
                                    print
                                  
                                  
                                    (f1.file)

                                  
                                  
                                    19
                                  
                                  
                                    #
                                  
                                  
                                     print(f1.read)
                                  
                                  
                                    20
                                  
                                   f1.write(
                                  
                                    "
                                  
                                  
                                    aabbcc
                                  
                                  
                                    "
                                  
                                  
                                    )

                                  
                                  
                                    21
                                  
                                   f1.close()
                                
文件读写加上b模式:
                                    
                                       1
                                    
                                    
                                      #
                                    
                                    
                                      _*_coding:utf-8_*_
                                    
                                    
                                       2
                                    
                                    
                                       3
                                    
                                    
                                      #
                                    
                                    
                                      我们来加上b模式支持
                                    
                                    
                                       4
                                    
                                    
                                      import
                                    
                                    
                                       time

                                    
                                    
                                       5
                                    
                                    
                                      class
                                    
                                    
                                       FileHandle:

                                    
                                    
                                       6
                                    
                                    
                                      def
                                    
                                    
                                      __init__
                                    
                                    (self,filename,mode=
                                    
                                      '
                                    
                                    
                                      r
                                    
                                    
                                      '
                                    
                                    ,encoding=
                                    
                                      '
                                    
                                    
                                      utf-8
                                    
                                    
                                      '
                                    
                                    
                                      ):

                                    
                                    
                                       7
                                    
                                    
                                      if
                                    
                                    
                                      '
                                    
                                    
                                      b
                                    
                                    
                                      '
                                    
                                    
                                      in
                                    
                                    
                                       mode:

                                    
                                    
                                       8
                                    
                                                 self.file=
                                    
                                      open(filename,mode)

                                    
                                    
                                       9
                                    
                                    
                                      else
                                    
                                    
                                      :

                                    
                                    
                                      10
                                    
                                                 self.file=open(filename,mode,encoding=
                                    
                                      encoding)

                                    
                                    
                                      11
                                    
                                             self.filename=
                                    
                                      filename

                                    
                                    
                                      12
                                    
                                             self.mode=
                                    
                                      mode

                                    
                                    
                                      13
                                    
                                             self.encoding=
                                    
                                      encoding

                                    
                                    
                                      14
                                    
                                    
                                      15
                                    
                                    
                                      def
                                    
                                    
                                       write(self,line):

                                    
                                    
                                      16
                                    
                                    
                                      if
                                    
                                    
                                      '
                                    
                                    
                                      b
                                    
                                    
                                      '
                                    
                                    
                                      in
                                    
                                    
                                       self.mode:

                                    
                                    
                                      17
                                    
                                    
                                      if
                                    
                                    
                                      not
                                    
                                    
                                       isinstance(line,bytes):

                                    
                                    
                                      18
                                    
                                    
                                      raise
                                    
                                     TypeError(
                                    
                                      '
                                    
                                    
                                      must be bytes
                                    
                                    
                                      '
                                    
                                    
                                      )

                                    
                                    
                                      19
                                    
                                    
                                              self.file.write(line)

                                    
                                    
                                      20
                                    
                                    
                                      21
                                    
                                    
                                      def
                                    
                                    
                                      __getattr__
                                    
                                    
                                      (self, item):

                                    
                                    
                                      22
                                    
                                    
                                      return
                                    
                                    
                                       getattr(self.file,item)

                                    
                                    
                                      23
                                    
                                    
                                      24
                                    
                                    
                                      def
                                    
                                    
                                      __str__
                                    
                                    
                                      (self):

                                    
                                    
                                      25
                                    
                                    
                                      if
                                    
                                    
                                      '
                                    
                                    
                                      b
                                    
                                    
                                      '
                                    
                                    
                                      in
                                    
                                    
                                       self.mode:

                                    
                                    
                                      26
                                    
                                                 res=
                                    
                                      "
                                    
                                    
                                      <_io.BufferedReader name='%s'>
                                    
                                    
                                      "
                                    
                                     %
                                    
                                      self.filename

                                    
                                    
                                      27
                                    
                                    
                                      else
                                    
                                    
                                      :

                                    
                                    
                                      28
                                    
                                                 res=
                                    
                                      "
                                    
                                    
                                      <_io.TextIOWrapper name='%s' mode='%s' encoding='%s'>
                                    
                                    
                                      "
                                    
                                     %
                                    
                                      (self.filename,self.mode,self.encoding)

                                    
                                    
                                      29
                                    
                                    
                                      return
                                    
                                    
                                       res

                                    
                                    
                                      30
                                    
                                    
                                      31
                                    
                                    
                                      32
                                    
                                     f1=FileHandle(
                                    
                                      '
                                    
                                    
                                      b.txt
                                    
                                    
                                      '
                                    
                                    ,
                                    
                                      '
                                    
                                    
                                      wb
                                    
                                    
                                      '
                                    
                                    
                                      )

                                    
                                    
                                      33
                                    
                                    
                                      #
                                    
                                    
                                       f1.write('你好啊啊啊啊啊') #自定制的write,不用在进行encode转成二进制去写了,简单,大气
                                    
                                    
                                      34
                                    
                                     f1.write(
                                    
                                      '
                                    
                                    
                                      你好啊
                                    
                                    
                                      '
                                    
                                    .encode(
                                    
                                      '
                                    
                                    
                                      utf-8
                                    
                                    
                                      '
                                    
                                    
                                      ))

                                    
                                    
                                      35
                                    
                                    
                                      print
                                    
                                    
                                      (f1)

                                    
                                    
                                      36
                                    
                                     f1.close()
                                  

 

 


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论