python
装饰器
- 针对的对象是一批不同的方法。
- 实现在已有的工程文件中,不修改这些方法的定义却能实现我们想要添加的功能。
- 你想给方法1加一个计时器功能,观察这个方法的运行时间,你可能想直接在函数定义处改一下完事了。现在的关注点在一个方法上。
- 但是你又想给方法2也加计时器,你又去改定义,然后你又想给方法3方法4方法5......方法n加计时器功能,难道你都要去改?现在的关注点在一堆方法上。
- 上面就是装饰器面对的问题。所以装饰器就是起这么一个功能,定义一个装饰器方法,你将需要加某一功能的方法从装饰器里过一下,之后再运行这些方法的时候,就会产生你想要的效果,而且这些方法不用你一个一个去改。就像一个人穿了衣服,但是这个人内在的一切都没变,衣服随便换,身体永远都这样。
import time
def timeit(func):
def test():
start = time.clock()
func()
end = time.clock()
print('time used :',end-start)
return test
@timeit#语法糖
def sum():
sum = 1+2
print(sum)
@timeit
def sub():
sub = 2-1
print(sub)
sub()
sum()
sum()
sum()
sub()
生成器迭代器
迭代器
- 迭代是Python最强大的功能之一,是访问集合元素的一种方式。
- 迭代器是一个可以记住遍历的位置的对象。
- 迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。
- 迭代器有两个基本的方法:iter() 和 next()。
字符串,列表,元组都是典型的迭代器,迭代器的类内部都有__iter__和__next__两个函数。
import sys
l = [1,2,3,4,3,46,457,235,73,45]
it = iter(l)
print(next(it))
print(next(it))
#常用的for遍历属于迭代器的语法糖
for i in l:
print(i)
一个典型的迭代器类如下,使用StopIteration异常标识迭代结束
class MyNumbers:
def __iter__(self):
self.a = 1
return self
def __next__(self):
if self.a <= 10:
x = self.a
self.a += 1
return x
else:
raise StopIteration
mynumber = MyNumbers()
myiter = iter(mynumber)
print(next(myiter))
print(next(myiter))
for i in myiter:
print(i)
生成器
在 Python 中,使用了 yield 的函数被称为生成器(generator)。
跟普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作,更简单点理解生成器就是一个迭代器。
在调用生成器运行的过程中,每次遇到 yield 时函数会暂停并保存当前所有的运行信息,返回 yield 的值, 并在下一次执行 next() 方法时从当前位置继续运行。
调用一个生成器函数,返回的是一个迭代器对象。以下实例使用 yield 实现斐波那契数列:
def fibonacci(n):
a, b, cnt = 0, 1, 0
while True:
if cnt > n:
return
yield a
a, b = b, a+b
cnt += 1
f = fibonacci(10)
while True:
try:
print(next(f), end='')
except StopIteration:
sys.exit()
推导式
又称解析式,python有三种推导式,列表,字典,集合。
列表是[],字典和集合是{}
逻辑运算符
匿名函数lambda表达式
只适用于代码量少,不想去def一个新的函数的时候(如果代码量多,直接去def多好),基本形式为关键字lambda 参数 : 程序语句。比如说列表排序时,key的指定可以使用lambda表达式。
function = lambda x,y: [x for i in range(y)]
print(function(2,5))
几个常用函数
map
map(函数f,可迭代对象1,可迭代对象2...可迭代对象n)
就是通过map函数对可迭代对象中的每个元素全部使用函数f,有种取代循环的感觉
def square(x):
return x**2
l = list(map(square,[1,2,3,6]))
print(l)
def add(x,y):
return x,y
l1 =[1,2,3,4]
l2 =[1,2,0]
l = list(map(add,l1,l2))
print(l)
l = list(map(lambda x,y:x*y,l1,l2))
print('*'*100,'\n',l)
zip
他是将可迭代对象组合成元组列表!!!使用*将元组列表解压成列表
l = list(zip(l1,l2))
print(l)
a,b = zip(*l)
print(a,'\t',b)
set
集合(set)是一个无序的不重复元素序列。他是python基本类型之一。
可以使用大括号 { } 或者 set() 函数创建集合,注意:创建一个空集合必须用 set() 而不是 { },因为 { } 是用来创建一个空字典。
sort
不说了,就是排序的,经常用
关于__init__和__new__和__del__
- init不是充当构造函数的角色,new才是类似于构造函数的工作,new是静态方法,返回一个实例对象给init,init只是给这个对象初始化。
- 没有init也可以,这样class相当于一个方法集,并没有这个类的属性(__dict__)
- 对象生命周期结束时__del__会被调用
打印
print('%d \t %.4f'%(4,3.1415))#百分号法
print('loss: {0} \t accuracy: {1:.4f}'.format(3.1415926,1.23456789))#format法
继承
class car():
def __init__(self,a):
self.a = a
class moto(car):
def __init__(self,a,b):
super(car,self).__init__(a)
self.b = b
m = moto(1,2)
print(m.__dict__)
class bwm(car):
def __init__(self,a,b):
Car.__init__(self,a)
self.b = b
def foo(self):
print('f1')
b = bwm(3,4)
print(b.__dict__)
闭包
- 在一个外函数中定义了一个内函数,内函数里运用了外函数的临时变量,并且外函数的返回值是内函数的引用。这样就构成了一个闭包。
- 一般情况下,在我们认知当中,如果一个函数结束,函数的内部所有东西都会释放掉,还给内存,局部变量都会消失。但是闭包是一种特殊情况,如果外函数在结束的时候发现有自己的临时变量将来会在内部函数中用到,就把这个临时变量绑定给了内部函数,然后自己再结束。
GIL全局解释锁
背景
- python为了数据安全考虑设置了全局解释锁机制
- 每个CPU在同一时间只能执行一个线程
在Python多线程下,每个线程的执行方式
- 获取GIL
- 执行代码直到sleep或者是python虚拟机将其挂起,(其他释放逻辑包括遇到IO操作或ticks记满次数)
- 释放GIL
可见,某个线程想要执行,必须先拿到GIL,我们可以把GIL看作是“通行证”,并且在一个python进程中,GIL只有一个。拿不到通行证的线程,就不允许进入CPU执行
所以要在python下提高效率,建议使用多进程(在多CPU前提下),因为每个进程用各自的GIL
Python是如何进行内存管理的?
一对象的引用计数机制
Python内部使用引用计数,来保持追踪内存中的对象,所有对象都有引用计数。
二垃圾回收机制
当一个对象的引用计数归零时,它将被垃圾收集机制处理掉
三内存池机制
Python提供了对内存的垃圾收集机制,但是它将不用的内存放到内存池而不是返回给操作系统。
异常捕捉
try:
#语句
except 错误类型:
#输出错误原因
else:
#如果语句没有错误,则执行else
finally:
#不管有没有错误,都要执行finally