python深刻

1. GIL(全局解释器锁)

  • GIL是CPython解释器中存在的,通常解释器都是CPython,同一时刻只有一个线程在运行,并且不能利用CPU多核的特性,因此没法实现并行。python

    1. 设置GIL锁算法

    2. 切换到一个线程执行数据库

    3. 执行如下指令:多线程

      • 执行指定数量的代码socket

      • 遇到延时(time.sleep、io操做、socket的recv、accept、content等)操做,线程让出控制权tcp

    4. 释放GIL锁函数

    5. 切换出线程工具

    6. 重复上述步骤 因此,多线程和多进程、协程的应用场景:spa

    • 计算(CPU)密集型:进程
    • IO密集型:线程、协程

2. 深拷贝与浅拷贝

2.1 浅拷贝

浅拷贝就是拷贝对象的引用地址,内存地址不变 通常常见的浅拷贝有:线程

  • 切片

  • list() 非数据类型转换

  • dict.copy() 字典拷贝

  • 导入模块copy

    import copy
      
      copy.copy()
    复制代码

浅拷贝不能拷贝不可变类型数据,不可变类型中存在可变数据也不进行拷贝

2.2 深拷贝

深拷贝就是拷贝对象的全部,拷贝引用地址,改变内存地址而且复制其中的数据

import copy
    
    copy.deepcopy()
复制代码

深拷贝不能拷贝不可变类型,但其中只要存在一个可变类型的数据,就可作深拷贝

3.私有化

  • _x:单前置下划线,表示私有属性或方法,from xxx import * 不能够导入此类属性或方法,但其类对象和子类能够访问
  • __xx:双前置下划线,私有化xx,通常避免与子类中的属性命名冲突,没法在外部直接访问
  • xx:双先后下划线,用户名、或系统魔法方法

4. Python mro

4.1 什么是mro

mro即method resolution order(方法解释顺序),解决Python多继承出现的二义性问题: 例:

class A():
    def f(self):
        pass
class B(A):
    def f(self):
        pass
class C(A, B):
    def f(self):
        pass
class D(B, C):
    def f(self):
        pass
class E(C, D):
    def f(self):
        pass
复制代码

Python中会产生这样的问题,利用C3算法能够肯定子类中继承方法的顺序,该序列保存在子类对象__mro__中

4.2 快速肯定mro顺序

  1. 肯定继承关系
  2. 画出继承关系图
class D(object):
    pass
 
class E(object):
    pass
 
class F(object):
    pass
 
class C(D, F):
    pass
 
class B(E, D):
    pass
 
class A(B, C):
    pass
 
if __name__ == '__main__':
    print(A.__mro__)
复制代码

  • 左边优先原则
  • 上下没法肯定谁在左边,下级优先

5. *args,**kwargs

5.1 函数声明:

def func(*args, **kwargs)
复制代码
  • *args能够接收不定长参数
  • **kwargs能够接受关键字参数

5.2 函数调用

def func(*args, **kwargs):
    pass

func(*args, **kwargs)
复制代码

此时表示拆包

6. Python中类方法、实例方法、静态方法有何区别?

例:

class Test(object):
    def __init__(name,age):
        self.name = name
        self.age = age

 @classmethod
    def test1(cls,name): # cls,类对象
        obj = cls(name,18) # 类对象能够建立实例对象

 @staticmethod
    def test2():
        return age<18 and len(name)>6

    def test3(self): # self,实例对象
        pass

test = Test("sss",19)
复制代码
  • 类方法:是类对象的方法,在定义时须要在上方使用"@classsmethod"进行装饰,形参为cls,表示类对象,类对象和实例对象均可调用; 能够利用实例方法中cls即类对象建立一份实例对象,扩充的初始化__init__方法的参数限制
  • 实例方法:是类实例化对象的方法,只有实例对象能够调用,形参为self,指代对象自己;
  • 静态方法:是一个任意函数,在其上方使用@staticmethod进行装饰,能够用对象直接调用,静态方法实际上跟该类没有太大关系,通常做为类提供的工具方法存在

7. property属性

经过property将类中的方法提高为一个属性,隐藏具体逻辑,对外只需像属性同样访问便可调用方法并得到返回值,简化调用者获取数据的流程

  1. 装饰器的方式建立
class Date(objecct):
    def __init__(self):
        self.__name = "sss"
        
 @property
    def name(self):
        return self.__name
        
 @name.setter
    def name(self, value):
        self.__name = value
复制代码
  1. 类属性来建立
class Foo(object):
    def get_bar(self):
        print("getter...")
        return "www"
        
    def set_bar(self, value):
        """必须两个参数"""
        print("setter...")
        return "set value" + value
        
    def del_bar(self):
        print("deleter...")
        return "www"
复制代码

若是代码考虑Python版本的兼容性,用类属性的方式建立,不然优先考虑装饰器的方式

8. 上下文管理器、with

系统资源如文件、数据库链接、socket而言,应用程序打开这些资源并执行完业务逻辑以后,必须作的一件事就是要关闭(断开)该资源。为了不每次都手动去关闭这些资源,可使用with关键字,好比:

with open("output.txt", "r") as f:
    f.write("python")
复制代码

with后面紧挨的语句返回的对象必须是一个上下文管理器,任何实现了__enter__()和__exit__()方法的对象均可称为上下文管理器。 例:

class SocketManager():
    def __init__(self, ip, port):
        self.addr = (ip, port)

    def __enter__(self):
        self.tcp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.tcp_socket.connect(self.addr)
        return self.tcp_socket

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.tcp_socket.close()


with SocketManager("127.0.0.1", 7890) as s:
    s.recv(1024)
    s.send(b"hello")
复制代码

若是中间遇到异常close方法也会被调用

  1. with会判断后面的语句返回值是否是一个上下文管理器
  2. 若是该对象是上下文管理器,调用该对象的__enter__()方法,并交给as后面的变量
  3. 使用该变量进行业务逻辑操做,完过后,会自动调用该对象的__exit__()方法去释放资源
相关文章
相关标签/搜索