python常见知识点
注意以下内容,⼤部分为 极客时间 Python核⼼技术与实战 整理得到
⽂章⽬录
装饰器与闭包
所谓的装饰器,其实就是通过装饰器函数,来修改原函数的⼀些功能,使得原函数不需要修改。
函数
1. 在 Python 中,函数是⼀等公民(first-class citizen),函数也是对象,
1. 即我们可以把函数赋予变量
2. 我们可以把函数当作参数,传⼊另⼀个函数中
3. 我们可以在函数⾥定义函数,也就是函数的嵌套。
4. 函数的返回值也可以是函数对象(即实现 闭包)
闭包
def func_closure():
def get_message(message):
print('Got a message: {}'.format(message))
return get_message
send_message = func_closure()
send_message('hello world')
##这⾥,函数 func_closure() 的返回值是函数对象 get_message 本⾝,之后,我们将其赋予变量 send_message,再调⽤ send_message(‘hello world’),最后输出了'Got a message: hello world'。
# 输出
Got a message: hello world
简单的装饰器
def my_decorator(func):
def wrapper():
print('wrapper of decorator')
func()
return wrapper
def greet():
print('hello world')
greet = my_decorator(greet)
greet()
## 这段代码中,变量 greet 指向了内部函数 wrapper(),⽽内部函数 wrapper() 中⼜会调⽤原函数 greet(),因此,最后调⽤ greet() 时,就会先打印'wrapper o f decorator',然后输出'hello world'
# 输出
wrapper of decorator
hello world
## 这⾥的函数 my_decorator() 就是⼀个装饰器,它把真正需要执⾏的函数 greet() 作为⾃⼰的输⼊,输出依然命名为greet, 此时输出的greet不仅仅会执⾏⾃⼰的代码 print('hello world'), 同时还会执⾏my_decorator()⾥的代码print('wrapper of decorator'),相当于在不改变原函数greet源码的前提下,修改了greet的功能。
def my_decorator(func):
def wrapper():
print('wrapper of decorator')
func()
return wrapper
@my_decorator
def greet():
print('hello world')
greet()
## 这⾥的@,我们称之为语法糖,@my_decorator就相当于前⾯的 greet=my_decorator(greet) 语句
装饰器中被修饰的函数带参数
def my_decorator(func):
def wrapper(message):
print('wrapper of decorator')
func(message)
return wrapper
大学python知识点汇总
# 常⽤形式
def my_decorator(func):
def wrapper(*args,**kwargs):
print('wrapper of decorator')
func(*args,**kwargs)
return wrapper
@my_decorator
def greet(message):
print(message)
greet('hello world')
# 输出
wrapper of decorator
hello world
装饰器中 装饰器⾃⼰ 要 带参数
def repeat(num):
def my_decorator(func):
def wrapper(*args,**kwargs):
for i in range(num):
print('wrapper of decorator')
func(*args,**kwargs)
return wrapper
return my_decorator
@repeat(4)
def greet(message):
print(message)
greet('hello world')
# 输出:
wrapper of decorator
hello world
wrapper of decorator
hello world
wrapper of decorator
hello world
wrapper of decorator
hello world
类装饰器
实际上,类也可以作为装饰器。类装饰器主要依赖于函数__call__(),每当你调⽤⼀个类的⽰例时,函数__call__()就会被执⾏⼀次。
def__init__(self, func):
self.func = func
self.num_calls =0
def__call__(self,*args,**kwargs):
self.num_calls +=1
print('num of calls is: {}'.format(self.num_calls)) return self.func(*args,**kwargs)
@Count
def example():
print("hello world")
example()
# 输出
num of calls is:1
hello world
example()
# 输出
num of calls is:2
hello world
多层装饰器
@decorator1
@decorator2
@decorator3
def func():
...
# 上⾯代码相当于
decorator1(decorator2(decorator3(func)))
则有:
def my_decorator1(func):
@functools.wraps(func)
def wrapper(*args,**kwargs):
print('execute decorator1')
func(*args,**kwargs)
return wrapper
def my_decorator2(func):
@functools.wraps(func)
def wrapper(*args,**kwargs):
print('execute decorator2')
func(*args,**kwargs)
return wrapper
@my_decorator1
@my_decorator2
def greet(message):
print(message)
greet('hello world')
# 输出
execute decorator1
execute decorator2
hello world
GIL
何为GIL
CPython 是⽤c语⾔实现的⼀个Python 解释器 ,(当然还有Jpython是⽤java实现的⼀个python解释器)
GIL 是 CPython中的⼀个概念,即 全局解释器锁。
GIL如何⼯作
GIL使得同⼀个时刻只有⼀个线程在⼀个cpu核上执⾏字节码。
每⼀个 Python 线程,在 CPython 解释器中执⾏时,都会先锁住⾃⼰的线程,阻⽌别的线程执⾏。当当前线程的时间⽚⽤完/ 因为io等原因阻塞时,当前线程退出cpu核,下⼀个线程才能⽤上这个cpu核。
所以,GIL使得并发很受限, ⽆法利⽤cpu多核的优势。
GIL会根据执⾏的字节码⾏数以及时间⽚释放,在遇到io操作的时候主动释放。
释放后会将当前cpu让给其他python线程执⾏。由于gil在遇到io操作时会主动释放,则gil在有频繁io处理的场景下很实⽤。
CPython引⼊GIL概念原因
我们到,CPython 使⽤引⽤计数来管理内存,所有 Python 脚本中创建的实例,都会有⼀个引⽤计数,来记录有多少个指针指向它。当引⽤计数只有 0 时,则会⾃动释放内存。
如果 不⽤GIL,那么如果有两个 Python 线程同时引⽤了 a,就会造成引⽤计数的 race condition,即
本来a的引⽤数变为2,但是两个变量同时引⽤a,则a的引⽤变为1。如果第⼀个线程结束,会把引⽤计数减少 1,则a的引⽤数为0,这时可能达到条件释放内存,当第⼆个线程再试图访问 a 时,就不到有效的内存了。
所以说,CPython 引进 GIL 其实主要就是这么两个原因:

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。