Python_提高

GIL全局解释器锁

  • 描述Python GIL的概念, 以及它对python多线程的影响?编写⼀个 多线程抓取⽹⻚的程序,并阐明多线程抓取程序是否可⽐单线程性 能有提升,并解释原因。

    1. Python语⾔和GIL没有半⽑钱关系。仅仅是由于历史原因在 Cpython虚拟机(解释器),难以移除GIL。

    2. GIL:全局解释器锁。每个线程在执⾏的过程都需要先获取 GIL,保证同⼀时刻只有⼀个线程可以执⾏代码。

    3. 线程释放GIL锁的情况: 在IO操作等可能会引起阻塞的system call之前,可以暂时释放GIL,但在执⾏完毕后,必须重新获取GIL Python 3.x使⽤计时器(执⾏时间达到阈值后,当前线程释放 GIL)或Python 2.x,tickets计数达到100

    4. Python使⽤多进程是可以利⽤多核的CPU资源的。

    5. 多线程爬取⽐单线程性能有提升,因为遇到IO阻塞会⾃动释放 GIL锁

  • 解决方法

    1. 换解释器

    2. 在一些部位换语言

浅拷贝、深拷贝

1.浅拷贝

  • 浅拷贝是对于一个对象的顶层拷贝(拷贝了引用,并没有拷贝内容)

2.深拷贝

  • 深拷贝是对于一个对象所有层次的拷贝(递归)

3.拷贝的其他方式

  • 切片表达式可以赋值一个序列(浅拷贝)

  • 字典的copy方法可以拷贝一个字典(浅拷贝)

4.注意点

  • 拷贝对不可变类型和可变类型的copy不同
    1.copy.copy对于可变类型,会进行浅拷贝
    2.copy.copy对于不可变类型,不会拷贝,仅仅是指向

私有化

  • xx:公有变量

  • _x:但前置下划线,私有化属性或方法,from somemodule import *禁止导入,类对象和子类可以访问

  • __xx:双前置下划线,避免与子类中的属性命名冲突,无法在外部直接访问(名字重整所以访问不到)

  • xx:双前后下划线,用户名字空间的魔法对象或属性。例如:init,__不要自己发明这样的名字

  • xx_:单后置下划线,用于避免与Python关键词的冲突

import导入模块

  • import搜素路径
improt sys
print(sys.path)
- 从上面列出的目录里依次查找导入的模块文件

-  "表示当前路径

-  列表中的路径的先后顺序代表了python解释器在搜索模块时的先后顺序
  • 重新导入模块
  • 模块被导入后, import module 不能重新导入模块,重新导入需要reload

from imp import reload
reload(模块名)

  • 多模块开发时注意点
  • 要修改某个引用模块内的属性值,必须使用 import

封装、继承、多态

  • 在使用面向过程编程时,当需要对数据处理时,需要考虑用哪个模板中哪个函数来进行操作,但是当用面向对象编程时,因为已经将数据存储到了这个独立的空间中,这个独立的空间(即对象)中通过一个特殊的变量(class)能够获取到类(模板),而且这个类中的方法是有一定数量的,与此类无关的将不会出现在本类中,因此需要对数据处理时,可以很快速的定位到需要的方法是谁 这样更方便
  • 全局变量是只能有1份的,多很多个函数需要多个备份时,往往需要利用其它的变量来进行储存;而通过封装 会将用来存储数据的这个变量 变为了对象中的一个“全局”变量,只要对象不一样那么这个变量就可以再有1份,所以这样更方便
  • 代码划分更清晰

多继承以及MRO顺序

1.单独调用父类的方法

2.多继承中super调用有所父类的被重写的方法
* 如果使用super().xxxx()那么会拿着当前类的名字到类名.mro获取到的元组中去找,只要找到,那么就调用它的下一个方法
* 如果使用super(类名,self).xxxx()那么会拿着类的名字到类名.mro获取到的元组中去找,只要找到,那么就调用它的下一个方法

3.单继承中super

总结

1.super().init相对于类名.init,在单继承上用法基本无差

2.但在多继承上有区别, super方法能保证每个父类的方法只会执行一次,而使用类名的方法会导致方法被执行多次,具体看前面的输出结果

3.多继承时,使用super方法,对父类的传参数,应该是由于python中super的算法导致的原因,必须把参数全部传递,否则会报错

4.单继承时,使用suoer方法, 则不能全部传递,只能传父类方法所需的参数,否则会报错

5.多继承时,相对与使用类名.init方法,要把每个父类全部写一遍,而使用super方法,只需写一句话便执行全部父类的方法, 这也是为何多继承需要全部传参的一个原因

静态方法和类方法

1.类属性、实例属性

  • 实例属性属于对象:实例属性在每个对象中都要保存一份
  • 类属性属于类:类属性内存中只保存一份
  • 应用场景:通过类创建实例对象时,如果每个对象需要具有相同名字的属性,那么就使用类属性,用一份即可

2.实例方法,静态方法和类 方法;三种方法在内存中都归属于类,区别在于调用方式不同

  • 实例方法:由对象调用;至少一个self参数;执行实例方法时,自动将调用该方法的对象赋值给self

  • 类方法:由类调用;至少一个cls参数;执行类方法时,自动将调用该方法的类赋值给cls

  • 静态方法:由类调用;无默认参数

  • 相同点:对于所有的方法而言,均属于类,所以在内存中也只保存一份

  • 不同点:方法调用者不同、调用方法时自动传入参数不同

property属性

  • 一种用起来像是使用的实例属性一样的特殊属性,可以对应于某个方法
  • 定义时,在实例方法的基础上添加@property装饰器;并且仅有一个self参数
  • 调用时,无需括号

方法:foo_obj.func()
property属性:foo_obj.prop

  • Python的property属性的功能是 :property属性内部进行一系列的逻辑计算,最终将计算结果返回
property属性的两种方式
  • 装饰器即:在方法上应用装饰器
  • 类属性即:在类中定义值为property对象的类属性
装饰器方式
  • 经典类中的属性只有一种访问方式,其对应被@property修饰的方法

  • 新式类中的属性有三种访问方式,并分别对应了三个被@property、@方法名.setter、@方法名.deleter修饰的方法,可以根据几个属性的访问特点分别将三个方法定义为对同一个属性:获取、修改、删除

  • 当使用类属性的方式创建property属性时,经典类和新式类无区别

property方法的四个参数
  • 第一个参数是方法名,调用对象.属性时自动触发执行方法
  • 第二个参数是方法名,调用对象.属性 = xxx时自动触发执行方法
  • 第三个参数是方法名,调用del对象.属性时自动触发执行方法
  • 第四个参数是字符串,调用对象.属性.doc,此参数是该属性的描述信息
总结
  • 定义property属性共有两种方式,分别是【装饰器】和【类属性】,而【装饰器】方式针对经典类和新式类又有所不同
  • 通过使用property属性,能够简化调用者在获取数据的流程

proeprty属性应用

  • 重新实现一个属性的设置和读取方法,可做边界判定

魔法属性

1.doc:表示类的描述信息

2.moduleclass

  • module表示当前操作的对象在那个模块
  • class表示当前操作的对象类是什么(当获取实例属性的时候,如果实例对象中没有这个属性,那么就会按照class指定的类对象中找到这个类属性)

3.init:初始化方法,通过类创建对象时,自动触发执行

4.del:当对象在内存中被释放,自动触发执行(对象计数为0或程序执行结束时触发)

5.call:对象后面加括号,触发执行

6.dict:类会对象中的所有属性

7.str:如果一个类中定义了str,那么在打印对象时,默认输出该方法的返回值(只要是获取这个对象的描述的情况,都会调用)

8.getitemsetitemdelitem

  • 用于索引操作,如字典,以上分别表示获取、设置、删除

9.getslicesetslicedelslice

  • 该三个方法用于分片操作,如:列表

面向对象设计

  • 继承-是基于Python中的属性查找(如X.name)
  • 多态-在X.medthod方法中,method的意义取决于X的类型
  • 封装-方法和运算符实现行为,数据隐藏默认是一种惯例

with与"上下文管理器"

  • 系统资源如文件、数据库连接、socket而言。应用程序打开这些资源并执行完业务逻辑之后,必须做的一件事就是要关闭(断开)该资源
  • 上下文管理器:任何实现了enter()和exit()方法的对象都可称之为上下文管理器
  • with语法用于简化资源操作的后续清除操作,是try/finally的替代方法,实现原理建立在上下文管理器之上

你可能感兴趣的:(Python_提高)