• ~~面向对象进阶(四):双下划线方法~~


    进击のpython

    *****

    类的双下划线方法


    双下划线方法是类的特殊方法,是由双下划线加方法名加双下划线进行定义的

    而这样的写法就表示,它其实是有特殊意义的

    (没有特殊意义我提他干撒,不是神经病嘛)

    其实啊,双下划线方法更多是python的源码开发者使用的

    他们在写源码的时候,会采用这种双下划线方法

    但是我建议在开发的时候尽量少使用这种方法

    那尽量少使用,为什么还要说呢?

    这是因为,学一下这种方法,可以帮助我们更好地理解源码

    放心兄弟

    你要是没读过一两个源码,那算你口技好

    源码可是必须要翻过去的山┗|`O′|┛ 嗷~~

    来吧,既然是了解,就不会很细


    • 大概了解的方法

      len方法

      这个方法很熟悉吧

      其实我们在计算什么字典啊列表之类的长度的时候

      表面上写的是len()

      实际上是在调用--len--方法

      正常我们在执行这个函数的时候是这样的

      l = [1, 2, 3, 4, 5]
      
      print(l.__len__())
      print(len(l))
      

      结果喜闻乐见,两个5是吧,

      但是我要是将他的方法进行修改

      class Demo(object):
          def __len__(self, obj):
              print("我是len方法")
              return 1
      
      
      l = Demo()
      print(l.__len__([1, 2, 3, 4, 5]))
      

      (为什么要写return呢? 是因为要求的,不写就会报错)

      你打印的结果,还是5嘛?

      是不是就不是了

      所以说,这个len()在执行的时候,实际上是在调用双下划线len方法


      hash方法

      其实和楼上的len方法相同

      这个方法就是调用了内部的--hash--方法

      仿照上面的写一个!


      item系列

      这个系列,我想说一个大家都很熟悉的东西

      字典

      你有想过字典是怎么赋值调用的吗?

      其实用的都是双下划线方法

      话不多说直接上代码

      class Dic:
          # def __init__(self, name):
          #     self.name = name
      
          def __getitem__(self, item):
              print("获取KEY", item)
              print(self.__dict__[item])
      
          def __setitem__(self, key, value):
              print("设置一个key...", key)
              self.__dict__[key] = value
      
          def __delitem__(self, key):
              print('执行del时,我执行')
              self.__dict__.pop(key)
      
          def __delattr__(self, item):
              print('删除的时候我执行')
              self.__dict__.pop(item)
      
      
      b = Dic()
      b[1] = 1
      b[2] = 2
      del b[2]
      b[3] = 3
      b[3]
      print(b.__dict__)
      

      执行结果如下:

      设置一个key... 1
      设置一个key... 2
      执行del时,我执行
      设置一个key... 3
      获取KEY 3
      3
      {1: 1, 3: 3}
      

      所以说,字典的相关操作,实际上是在调用相应的双下划线方法


    • 重点掌握的方法

      str&repr

      这两个方法应该知道吧

      (要是不知道就回去看博客吧凑弟弟)

      那我们在使用它的时候实际上调用的就是对应的双下划线方法

      举个例子

      class R:
          def __init__(self, item):
              self.item = item
              pass
      
      s = R("ponny")
      
      print(str(s))
      print(repr(s))
      

      可以看到打印出来的其实都是相对应的内存地址

      <__main__.R object at 0x0548FF50>
      <__main__.R object at 0x0548FF50>
      

      现在我们自己这两个相对应的双下划线方法

      看看是不是对这两个函数有影响

      class R:
          def __init__(self, item):
              self.item = item
              pass
      
          def __str__(self):
              print(f"我是{self.item}的str方法!")
              return "A"
      
          def __repr__(self):
              print(f"我是{self.item}的repr方法!")
              return "B"
      
      
      s = R("ponny")
      
      print(str(s))
      print(repr(s))
      

      当我们执行上面的语句的时候

      应该得到的是这样的结果

      我是ponny的str方法!
      A
      我是ponny的repr方法!
      B
      

      说明什么?

      说明这两个方法的使用确实是调用python内部同名的双下划线方法

      而我们在局部空间自己定义了这个方法

      根据加载顺序,先加载的就是我们写好的

      所以说,也可以说明这两个方法其实是调用对应的双下划线方法

      其实还有一点想要说的

      当我把str方法注释掉再执行

      会发生什么现象呢?

      class R:
          def __init__(self, item):
              self.item = item
              pass
      
          # def __str__(self):
          #     print(f"我是{self.item}的str方法!")
          #     return "A"
      
          def __repr__(self):
              print(f"我是{self.item}的repr方法!")
              return "B"
      
      
      s = R("ponny")
      
      str(s)
      print(str(s))
      

      结果是这样的:

      我是ponny的repr方法!
      我是ponny的repr方法!
      B
      

      说明什么?

      当我们解释器中要是没有str双下划线方法的时候

      在使用str方法时,就会使用repr的双下划线方法

      然后其实还有一点就是

      其实你可能也注意到了

      这两个方法的返回值必须是字符串,否则会报错

      (要是感兴趣你可以自己去上网查一下相关资料)


      del 析构方法

      析构方法,当对象在内存中被释放时,自动触发执行

      怎么理解呢?

      我现在搞一个这样的代码

      class R:
          def __init__(self, item):
              self.item = item
              pass
      
          def __del__(self):
              print("我是del...")
              pass
      

      当我对这个类进行实例化会发生什么呢?

      s = R("ponny")
      

      执行结果如下:

      我是del...
      

      欸?

      我不是没有执行这个方法嘛?

      怎么还会执行啊??

      我们先把这个疑问放在这

      我们在这实例化的后面

      加上一个打印语句

      看看会打印什么??

      print("我是后面的语句")
      

      结果你可能大概想到(猜到)了

      我是后面的语句
      我是del...
      

      所以说为什么会是这个执行顺序呢?

      前面我们说了,del是个析构方法

      而析构方法就是对象在内存中被释放了就会自动执行

      当py文件的所有东西都执行完了的时候

      在内存中储存的对象就会自动释放

      (这是python的垃圾回收机制导致的)

      从而就会触发del方法

      而del方法的本质就是双下划线的del方法

      所以,就在最后执行了那个打印语句

      但是呢

      此方法一般无须定义,因为Python是一门高级语言

      程序员在使用时无需关心内存的分配和释放

      因为此工作都是交给Python解释器来执行

      所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的


    *有点东西*
    *继续深究*
  • 相关阅读:
    Java框架spring学习笔记(十七):事务操作
    Java框架spring 学习笔记(十六):c3p0连接池的配置以及dao使用jdbcTemplate
    Java框架spring 学习笔记(十五):操作MySQL数据库
    Java框架spring 学习笔记(十四):注解aop操作
    Java框架spring 学习笔记(十三):log4j介绍
    Java框架spring 学习笔记(十二):aop实例操作
    Java框架spring 学习笔记(十一):aop相关概念
    Java框架spring 学习笔记(十):bean管理(注解和配置文件混合使用)
    Java框架spring 学习笔记(九):Spring的bean管理(@Required、@Component、@Autowired、@Resource注解)
    Java框架spring 学习笔记(八):注入对象类型属性
  • 原文地址:https://www.cnblogs.com/jevious/p/11264615.html
Copyright © 2020-2023  润新知