python线程安全类型_4.1 python类的特殊成员,偏函数,线程安全,栈,flask上下文

一. Python 类的特殊成员(部分)

class MyClass(object):

def __call__(self, *args, **kwargs):

print(f'__call__ -- args:{args}')

def __setattr__(self, key, value):

print(f'__setattr__ -- key:{key} value:{value}')

def __getattr__(self, item):

print(f'__getattr__ -- item:{item}')

def __setitem__(self, key, value):

print(f'__setitem__ -- key:{key} value:{value}')

def __getitem__(self, item):

print(f'__getitem__ -- item:{item}')

my_class = MyClass()

my_class(1, 2, 3) # 执行__call__

my_class.age = 41 # 执行__setattr__

res1 = my_class.age # 执行__getattr__

my_class['王力宏'] = '王二哥'# 执行__setitem__

res2 = my_class['王力宏'] # 执行__getitem__

# 以上代码执行结果:

__call__ -- args:(1, 2, 3)

__setattr__ -- key:age value:41

__getattr__ -- item:age

__setitem__ -- key:王力宏 value:王二哥

__getitem__ -- item:王力宏

二. Python偏函数

Python 偏函数是通过 functools 模块被用户调用。

1. 描述

函数在执行时,要带上所有必要的参数进行调用。但是,有时参数可以在函数被调用之前提前获知。这种情况下,一个函数有一个或多个参数预先就能用上,以便函数能用更少的参数进行调用。

偏函数是将所要承载的函数作为partial()函数的第一个参数,原函数的各个参数依次作为partial()函数后续的参数,除非使用关键字参数。

通过语言描述可能无法理解偏函数是怎么使用的,那么就举几个常见的例子来说明。

2. 实例一: 取余函数

取余函数,对于整数 100,取得对于不同数 m 的 100%m 的余数。

from functools import partial

def mod(n, m):

return n % m

mod_by_100 = partial(mod, 100)

print(mod(100, 7))# 2

print(mod_by_100(7))# 2

3. 实例二: 求三个数的和

from functools import partial

def add(a, b, c):

print(a, b, c)

return a + b + c

par_add = partial(add, 1, 2)

print(par_add(3))

par_add2 = partial(add, 1)

print(par_add2(5, 7))

# 执行结果:

1 2 3

6

1 5 7

13

三. 线程安全

1. 实例一: 无线程,消耗时间过长

import time

class Foo(object):

pass

foo = Foo()

def add(i):

foo.num = i

time.sleep(1)

print(foo.num)

for i in range(10):

add(i)

# 执行结果: 每秒打印出一个数字,总共耗时10秒

0

1

2

3

4

5

6

7

8

9

2. 实例二: 开启线程,节省了时间,但数据不安全

import time

import threading

class Foo(object):

pass

foo = Foo()

def add(i):

foo.num = i

time.sleep(1)

print(foo.num, i)

for i in range(20):

th = threading.Thread(target=add, args=(i,))

th.start()

# 执行结果: 几乎在1秒的时间打印出了全部结果

19 4

19 2

19 1

19 3

19 0

19 14

19 13

19 11

19 10

19 9

19 7

19 5

19 16

19 8

19 15

19 19

19 18

19 17

19 6

19 12

3. 实例三: 使用local, 以空间换时间, 保证了数据安全

import time

import threading

from threading import local

class Foo(local): # 继承local

pass

foo = Foo()

def add(i):

foo.num = i

time.sleep(1)

print(foo.num, i, threading.current_thread().ident)

for i in range(20):

th = threading.Thread(target=add, args=(i,))

th.start()

# 执行结果: 以空间换时间,浪费了部分资源,保证了执行效率和数据安全

8 8 7760

11 11 1856

9 9 836

7 7 10612

5 5 1148

4 4 12124

2 2 6040

19 19 12652

6 6 8288

3 3 6552

18 18 10232

17 17 12668

15 15 9348

13 13 13132

10 10 7948

1 1 7404

16 16 13200

12 12 9440

0 0 7880

14 14 7616

4. Flask上下文机制

# 总结: threading.local

Flask上下文机制就是使用的 threading.local,这个技术不算很牛逼,但是概念很重要:

线程进来,开辟一个空间给这个线程,线程操作的所有任务,都会复制一份到该空间中.

四. 栈Stack

栈遵循 后进先出(Last In First Out) 原则.

# 栈Stack: 遵循 后进先出(Last In First Out) 的原则

class Stack(object):

data = []

def __setattr__(self, key, value):

self.push(key, value)

def push(self, key, value):

self.data.append({key: value})

def pop(self):

return self.data.pop()

stack = Stack()

stack.name = '666'

stack.name = '777'

stack.name = '888'

print(stack.data)

print(stack.pop(), stack.data)

print(stack.pop(), stack.data)

print(stack.pop(), stack.data)

# 执行结果:

[{'name': '666'}, {'name': '777'}, {'name': '888'}]

{'name': '888'} [{'name': '666'}, {'name': '777'}]

{'name': '777'} [{'name': '666'}]

{'name': '666'} []

五. LocalStack

from threading import get_ident # get_ident()可以获取到当前线程id

import threading

import time

class MyLocalStack(object):

storage = {} # 结构: {key1: [el1], key2: [el2]}

def push(self, item):

try:

self.storage[get_ident()].append(item)

except:

self.storage[get_ident()] = [item]

def pop(self):

return self.storage[get_ident()].pop()

my_local_stack = MyLocalStack()

def run(i):

my_local_stack.push(i)

time.sleep(1)

for i in range(5):

th = threading.Thread(target=run, args=(i,))

th.start()

print(my_local_stack.storage)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值