Python学习程序员程序猿阵线联盟-汇总各类技术干货

Python学习笔记二十一(GIL/深拷贝/浅拷贝/多态)

2018-05-20  本文已影响31人  DragonFangQy

Python 多线程对CPU的使用率

单线程对CPU的一个核心使用率可以达到100%

# 多线程
import threading


# 子线程死循环
def test():
    while True:
        pass


# t1 = threading.Thread(target=test)
# t1.start()

# 主线程死循环
while True:
    pass

01单线程对CPU的使用情况.png

那么要让CPU的两个核心使用率都达到100%,应该怎么做?使用两个线程?
两个线程对CPU的两个核心使用情况

# 多线程
import threading


# 子线程死循环
def test():
    while True:
        pass


t1 = threading.Thread(target=test)
t1.start()

# 主线程死循环
while True:
    pass

02多线程对CPU的使用情况.png

两条线程对双核CPU的使用率大概是50%左右,远远达不到100%.这是为什么?说到这就绕不开一个概念GIL.

GIL(全局解释器锁)[1]

什么是GIL

GIL 的全程为 Global Interpreter Lock ,意即全局解释器锁,用来保护所有全局的解释器和环境状态变量的,线程执行必须拿到这把锁之后才能执行.

04单核多线程.png

GIL的来历, 单核怎么实现多任务? 为此GIL产生. 正是这个锁能保证同一时刻只有一个线程在运行, 也正是这个锁让单核也可以实现多任务.

那么怎么解决效率问题?
1.使用多进程+协程,完成任务
2.GIL 是CPython解释器的,换一个解释器JPython也可以解决
3.JPyhton解释器可以解决,调用Java写的多线程一样可以解决[2]

拷贝

什么是拷贝?

复制就是拷贝, 复制XXX文件, 粘贴之后得到 XXX副本, XXX副本 就是XXX 拷贝得到的. pyhon 中的拷贝分为浅拷贝 和深拷贝, 他们之间有什么区别呢?

引用和拷贝的区别

在讨论深浅拷贝的区别之前, 先讨论另一个问题, 引用 和 拷贝的区别.

# 引入copy 模块
import copy

a = [1, 2, 3]

# b引用 a
b = a

# c浅拷贝 a
c = copy.copy(a)
# d深拷贝 a
d = copy.deepcopy(a)

# 从值分析区别
print("从值分析区别")
print(a)
print(b)
print(c)
print(d)

print("--" * 10)

# 从地址分析区别
print("从地址分析区别")
print(id(a))
print(id(b))
print(id(c))
print(id(d))

# 运行结果
# 从值分析区别
# [1, 2, 3]
# [1, 2, 3]
# [1, 2, 3]
# [1, 2, 3]
# --------------------
# 从地址分析区别 
# 140060678261192
# 140060678261192
# 140060702258888
# 140060678259976

从值以及地址两方面入手分析引用 与拷贝的区别.

上面用的可变类型得出的结论,对于不可变类型是否依然成立?

# 引入copy 模块
import copy

a = 1

# b引用 a
b = a

# c浅拷贝 a
c = copy.copy(a)
d = copy.deepcopy(a)

# 从值分析区别
print("从值分析区别")
print(a)
print(b)
print(c)
print(d)

print("--" * 10)

# 从地址分析区别
print("从地址分析区别")
print(id(a))
print(id(b))
print(id(c))
print(id(d))

# 运行结果
# 从值分析区别
# 1
# 1
# 1
# 1
# --------------------
# 从地址分析区别
# 10919424
# 10919424
# 10919424
# 10919424

可以看出 对于不可变类型以上结论不成立.

深拷贝和浅拷贝的区别

引用和拷贝的区别分析完了, 那么深拷贝和 浅拷贝的区别是什么呢?

# 引入copy 模块
import copy

a = [[11, 22, 33], [33, 44, 55]]

# c浅拷贝 a
c = copy.copy(a)
d = copy.deepcopy(a)

# 从值分析区别
print("从值分析区别")
print(a)
print(c)
print(d)

print("--" * 10)

# 从地址分析区别
print("从地址分析区别")
print(id(a))
print(id(c))
print(id(d))


print("* *" * 10)
# 修改11 为100
a[0][0] = 100

# 从值分析区别
print("从值分析区别")
print(a)
print(c)
print(d)

print("--" * 10)

# 从地址分析区别
print("从地址分析区别")
print(id(a))
print(id(c))
print(id(d))

# 运行结果
# 从值分析区别
# [[11, 22, 33], [33, 44, 55]]
# [[11, 22, 33], [33, 44, 55]]
# [[11, 22, 33], [33, 44, 55]]
# --------------------
# 从地址分析区别
# 139975649195784
# 139975673194376
# 139975649196936
# * ** ** ** ** ** ** ** ** ** *
# 从值分析区别
# [[100, 22, 33], [33, 44, 55]]
# [[100, 22, 33], [33, 44, 55]]
# [[11, 22, 33], [33, 44, 55]]
# --------------------
# 从地址分析区别
# 139975649195784
# 139975673194376
# 139975649196936

分析深浅拷贝也是从值 和 地址两方面入手, 另改变了一次a[0][0]的值, 修改后地址以及值的变化.

如果a 存储的是不可变类型或者 a 本身就是不可变类型上述结论是否成立?

a存储不可变类型

# 引入copy 模块
import copy

a = [11,22,33]

# c浅拷贝 a
c = copy.copy(a)
d = copy.deepcopy(a)

# 从值分析区别
print("从值分析区别")
print(a)
print(c)
print(d)

print("--" * 10)

# 从地址分析区别
print("从地址分析区别")
print(id(a))
print(id(c))
print(id(d))


print("* *" * 10)
# 修改11 为100
a[0] = 100

# 从值分析区别
print("从值分析区别")
print(a)
print(c)
print(d)

print("--" * 10)

# 从地址分析区别
print("从地址分析区别")
print(id(a))
print(id(c))
print(id(d))

# 运行结果
# 从值分析区别
# [11, 22, 33]
# [11, 22, 33]
# [11, 22, 33]
# --------------------
# 从地址分析区别
# 140393288703176
# 140393312696072
# 140393288701192
# * ** ** ** ** ** ** ** ** ** *
# 从值分析区别
# [100, 22, 33]
# [11, 22, 33]
# [11, 22, 33]
# --------------------
# 从地址分析区别
# 140393288703176
# 140393312696072
# 140393288701192

从上面的结果可以看出, 当a 存储的是不可变类型, 修改之后 c值 != a值 ,d值 != a值, 既a 存储不可变类型,修改值之后 ,拷贝不会随着改变而改变.

a是不可变类型

# 引入copy 模块
import copy

a = 1

# c浅拷贝 a
c = copy.copy(a)
d = copy.deepcopy(a)

# 从值分析区别
print("从值分析区别")
print(a)
print(c)
print(d)

print("--" * 10)

# 从地址分析区别
print("从地址分析区别")
print(id(a))
print(id(c))
print(id(d))


print("* *" * 10)
# 修改11 为100
a = 100

# 从值分析区别
print("从值分析区别")
print(a)
print(c)
print(d)

print("--" * 10)

# 从地址分析区别
print("从地址分析区别")
print(id(a))
print(id(c))
print(id(d))

# 运行结果
# 从值分析区别
# [11, 22, 33]
# [11, 22, 33]
# [11, 22, 33]
# --------------------
# 从地址分析区别
# 140393288703176
# 140393312696072
# 140393288701192
# * ** ** ** ** ** ** ** ** ** *
# 从值分析区别
# [100, 22, 33]
# [11, 22, 33]
# [11, 22, 33]
# --------------------
# 从地址分析区别
# 140393288703176
# 140393312696072
# 140393288701192

从上面的结果可以看出, 当a 是不可变类型, 修改之后 c值 != a值 ,d值 != a值, 既a 存储不可变类型,修改值之后 ,拷贝不会随着改变而改变.

怎么理解上述变化?

深拷贝是完全克隆, 浅拷贝是整容. 也就是说 深拷贝是完全拷贝, 浅拷贝只是拷贝第一层

深拷贝

05深拷贝.png

浅拷贝

06浅拷贝.png

小结:

私有化

多态

class Animal(object):
    def run(self):
        print('Animal is running...')


class Dog(Animal):
    pass


class Cat(Animal):
    pass


def test(object):
    object.run()


class Demo(object):

    def run(self):
        print('我来打酱油')


dog = Dog()
cat = Cat()
demo = Demo()

test(dog)
test(cat)
test(demo)

# 运行结果
# Animal is running...
# Animal is running...
# 我来打酱油

因为多态的条件是

结合程序运行结果以及多态的条件得出 Python中的多态是一个不严谨的多态.


到此结 DragonFangQy 2018.5.20


  1. 详解python多线程无法增加cpu使用率

  2. java和python互相调用

上一篇下一篇

猜你喜欢

热点阅读