zoukankan      html  css  js  c++  java
  • python 模块会导入几次?猴子补丁为什么可以实现?

    一共三个文件

    a.py内容是

    print('被导入')

    x = 1

    b.py内容是

    import a

    a.x = 2

    c.py内容是

    import a

    import b

    print(a.x)

    现在运行c文件,这个结果出乎很多人的意料大部分python人员都猜不对,结果是

     在c文件里面不管是先导入a还是先导入b,

    1、可以发现a模块被两个地方导入了,但是只打印一次 “被导入”。

    2、打印x的结果都是2。

    不光是自己的文件如此,导入库文件也是一样。所以这就是猴子补丁能实现的原因。

    2、再多想一下,为什么要面向对象了,不面向对象,直接模块加全局变量,会造成多个地方全局变量互相干扰。有了类,类天然就是多实例,类的所有实例就像是无数个全局变量互不干扰的复制模块。

    2.1不用面向对象也可以实现多实例,原来是狗写成全局变量了,需要改成从函数return一只狗,然后有个吃翔的函数,把这个return出来的狗传给这个函数,所以形式是

    eat(dog,sheet)

    2.2用面向对象,那么就不是狗模块了,有个狗类,狗吃翔变成了

    dog = Dog()  

    dog.eat(sheeet)

    那么多个狗就实例化多次,每个狗 吃了多少翔  体重变化了多少,都是完全独立的。

    2.1的面向过程模拟多实例,需要在类外传入和保存很多狗的属性和状态,多个函数使用同一个类型的传参,很频繁,不是很容易看懂,例如a函数的第一个参数和b函数的第一个参数是代表同一个东西比如狗的名字,有的人在a函数写dog_name,在b

    函数写name,真的不容易看出来他们的关联。如果是面向对象,那是很直观的,a方法和b方法都是引用self.name。

    扯远了从模块导入机制  到了猴子补丁 面向过程 面向对象了。

    3、把b文件改成这样,name运行c会得到什么呢。

    import a
    from a import x
    x = 2


    由第三个例子可见,猴子补丁可不是乱打,地方打错了,就不会生效。主要是要找到你常用那个模块的什么函数或者类,patch与那个引用同一个模块的模块。打补丁时候一定要搞清楚from xx import yy和import xx.yy的区别,区别相当大。
  • 相关阅读:
    拦截导弹类问题 (Codevs4888零件分组POJ1065Wooden Sticks)(LIS及其覆盖问题)
    BZOJ1034[ZJOI2008]泡泡堂
    BZOJ1015[JSOI2008]星球大战starwar题解报告
    合唱队形(DP)
    美元和马克(dp)
    链式前向星
    hdu-6170(模拟)
    51nod-1117 聪明的木匠(优先队列)
    51nod-1095 Anigram单词(简单map)
    KingXMagicSpells 期望dp (记忆化搜索)
  • 原文地址:https://www.cnblogs.com/ydf0509/p/9366062.html
Copyright © 2011-2022 走看看