python高级--知识点提高

GIL(全局解释锁)

简介

顾名思义这是一个锁,它的作用保证了同一个时刻只能一个线程可以运行代码,也就是说不管你是几线程的cpu但在这一刻只能一个线程运行,其他线程没法运行,只有当遇到堵塞时才会切换进程。GIL与python语言没有任何关系,这是python解释器的问题,cpython解释器有这个问题,jpython解决了这个问题。只对线程有效。

GIL面试题

描述python GIL的概念,以及它对python多线程的影响,如果编写一个爬虫程序,并阐述多线程程序是否比单线程性能提升,并解释原因。


1、Python语言与GIL没有任何关系,只是由于历史原因在Cpython解释器。难以移除GIL
2、GIL全局解释器锁每个线程在执行的过程中都需要先获取GIL,保证同一时刻只能有一个线程执行代码
3、线程释放GIL锁的情况当线程遇到堵塞(IO)操作之前,在执行完毕后会重新获取GIL锁
4、多线程程序是比单线程性能高的,因为单线程只能在当这个任务完成后才可以执行下一个,多线程在执行时会遇到堵塞所以在堵塞的时候可以执行另一个线程。

解决方法

1、使用Jpython解释器
2、使用其他语言

深拷贝、浅拷贝

简单的深拷贝、浅拷贝

浅拷贝
例如Python中
a = 5;
b = a;
此时的拷贝是一个引用,就是首先定义一个变量a它指向一个int类型的数据,
然后将变量a赋给变量b,此时是b也指向a指向的那一个地址。
在这里插入图片描述深拷贝
例如在c语言中
int a = 5;
定义一个变量是在为该变量在内存中开辟一块int的空间,
int b = a;
赋值时;
是将该空间复制了一份赋给b存储在另一块空间中,相互之间没有关联
在这里插入图片描述## 复杂的深拷贝、浅拷贝

python中的copy模块
copy.copy(变量)方法
copy.deepcopy(变量)方法

拷贝变量

在拷贝变量时两个都是简单的浅拷贝。

拷贝列表

copy.copy();
只对第一层进行深拷贝,如果列表中还有其他元素,则其他的进行浅拷贝。
在这里插入图片描述
deep.copy()
全部进行深拷贝
在这里插入图片描述注意列表的切片list[:]和copy一样属于浅拷贝。

拷贝不可变类型

例如元组
在拷贝主元素和子元素都是不可变类型时,
copy.copy()
copy.deepcopy()
都是拷不动的,拷贝的都是引用。

如果其中子元素有一个是可变类型,即使不可变类型数据为第一层,那么deepcopy就可以对该数据进行深拷贝,而copy还是指向

类的属性

  • xx:公有变量

  • _xx:单前置下划线开头的属性或方法,表示在禁止在模块中导入,
    禁止 from yyy import xxx 导入

  • __xx:双前置下划线开头,表示该属性/方法为私有的,使用对象实例化无法直接访问和操作,只能利用特殊方法来操作该属性或方法。
    设个私有化的原理是:自动将该变量名改变了,规则是:_类名变量名

  • _xxx_:双前后置下划线,为魔法属性或方法

  • xxx_:单后置下划线,表示避免与关键字相同

import导入模块

import 模块
from yyy import xxx
from yyy import *
import xxx as XXX :起别名避免一个程序中变量和模块名相同

导入模块的顺序

import sys
sys.path
用于查看导入模块时的查找文件的顺序
sys.path.insert(下标,模块路径)
该表导入模块时的搜索路径

导入模块的注意事项

重新加载模块

当一个程序导入了一个模快,但在该模块导入后,这个模块被修改了,这就需要将该模块重新导入。
import xxxx
这样都是不行的,因为在python重复导入模块时只有第一次导入有效
要想重新再导入模块一次要使用
imp模块中reload函数
reload(模块名);

多模块导入事项

导入模块只是定义了一个变量然后指向了那一个导入的地方,并不是实际的
**from yyy import xxx **导入
使用该方式导入模块,只是在该文件中定义了一个全局变量xxx该变量的指向为yyy模块中xxx,如果在该文件中改变了xxx的值并不会改变yyy中的xxx,而是在该文件中将xxx的指向改变了而已。
不过如果xxx是一个列表,对列表进行append和remove操作是可以的,因为该操作不是改变指向
import yyy
该导入方式是导入了该模块的引用,使用yyy.xxx则可以改变值,当其他模块在使用时就会发生改变

再谈继承、多态

多继承中调用调用父类方法

super()调用父类方法,使用该方法保证了每个父类方法只会调用一次。
原理
类的__mro__方法:返回一个元组,该元组中保存的是从本类继承的一直到object类的类名,
该方法调用后会在__mro__生成的元组中查找,本类的类名然后跳转到本类后面的哪一个类去执行相应的方法。
super(类名):该表示直接在元组中查找填写的类名,然后执行该类名后面的哪一个类去。

多态

如果一个类继承了另一个类,在使用实例对象调用方法时,如果本类中没有,则会去继承类中去找,如果本类中有则会使用本类的该方法,不使用继承类的。
也就是说,本类中的方法可以和继承类中的方法相同,这就是多态的一个体现。
不过python中的是方法重写。
重写
如果有一个类方法,然后又有一个拥有相同方法名的类方法,则只会调用后面的那个类方法,前面那个不会调用,表示后面那个方法重写了前面的那个方法。
重载
同样两个拥有相同方法名的方法,但里面传递的参数不同,则这两个方法互相不影响,在使用时通过传递不同的参数会使用不同的方法。

聊聊类对象

创建对象的过程:
当用户通过类名创建一个对象时;
首先调用__new__方法申请一块空间用于存储对象,然后调用__init__方法初始化该空间。

类属性、实例属性

类属性属于对象
实例属性属于实例对象
类属性实例对象不能直接访问,只能通过类访问
类属性只要是通过该类创建的对象都可以使用。
类属性只在内存中保存一份。
实例属性通过实例对象来访问,只能本对象来使用,
实例对象在每个对象中都保存一份。

实例方法、类方法、静态方法

  • 实例方法:由对象调用,至少一个self参数,执行实例方法时自动将该对象赋给self,用于对该对象进行操作。
  • 类方法:由类调用,至少一个cls参数,用于表示该类,用于操作类属性
  • 静态方法:由类调用,默认无参数,创建在方法前加一个@classmethod装饰器,表示该方法是一个静态方法。

property属性

一种将方法用起来像实例属性一样的方法。

class poo(object):

   @property 
	def fool()
		rerurn 10;

pool = poo();
p = pool.fool;
\# p = 10;
  • 定义时只需在方法前加入@property即可,并且只有一个self参数,
  • 调用时无需加括号

配合property的另外两种

@方法名.setter装饰器
允许赋值,该方法有两个参数,一个self另一个为要传递的值
@方法名.deletr装饰器:
删除,允许使用del删除

class poo(object):
	
	@property 
 	def fool(self):
 		self.a = 10;
 		rerurn self.a;
 	@fool.setter
 	def fool(self,value):
 		self.a = value;

pool = poo();
pool.fool = 20;
p = pool.fool;
#p = 20;

调用pool.fool = 20;时自动执行@fool.setter装饰的方法。

创建property的属性的另外一种方法

类属性:通过property()方法创建
该方法有四个参数:

  • 第一个参数为方法名,调用对象.属性时自动触发,用于获取属性值
  • 第二个参数为方法名,调用对象.属性 = 值 时自动触发,用于设置该值
  • 第三个参数为方法名,调用 del 对象.属性 时自动触发,用于删除该值
  • 第四个参数是字符串,调用对象.属性.__doc__时吃法,该参数用于设置该属性的描述信息

魔法方法

以双下划线开头和结尾的称为魔法方法,该方法是在python自留的,

  • _doc_:类的描述信息,通过类名来调用,也就是在定义类时三双引号之间的描述。
  • _module_:用于查看当前操作的对象在那个模块中
  • _class_:用来查看当前操作对象在那个类
  • _init_:初始化方法,通过类创建对象时自动调用。
  • _del_:当对象被释放时自动执行。
  • _call_:当创建一个对象后,使用对象名加括号执行该方法
  • _dict_:获取类或对象的所有属性。返回的是一个字典
  • _str_:当类中定义了该方法,在使用print打印对象时执行该方法。

with与“上下文管理器”

用于打开文件使用,使用它能够保证不管是否有异常无异常最后都会关闭文件。

with结构

with 上下文管理器 as 标识符(自定义用于接受上下文管理器返回的值):
pass;

上下文管理器

当在一个类中实现了__enter__方法和__exit__方法,那么该类就可以称为是一个上下文管理器。

with原理

  • with首先会判断该对象是否为一个上下文管理器,如果是调用__enter__方法,然后将返回值赋给标识符,否则直接调用__exit__方法。
  • 如果在下面的语句中发生了异常会直接调用__exit__方法
  • 当程序执行完以后,最后也会调用__exit__方法

with案例–实现我的文件打开对象

class my_open(onject):
	def __init__(self,file_name,mode):
		self.file_name = file_name;
		self.mode = mode;
		
	def __enter__(self):
		self.f = open(self.file_name,self.mode);
		return self.f;
	def __exit__(self):
		self.f.colse();

with my_open("out.txt","w") as f:
	f.write("hello with!!!");

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值