python进阶点
1.列表生成式
range(1,100,5) #第一个参数表示开始位,第二个参数表示结束位(不含),第三个参数表示步长,就是每5个数返回一次。
a = [i for i in range(1,10)] #列表生成式表示返回i的值,并且返回9次,每次返回的是i的值。一到九
a = [2 for i in range(1,10)] #这里表示返回2,并且返回9次,但是每次的值都是2。
a = [i for i in range10 if i%2==0] #表示在生成式内部加入if判断,当i除以2的余数等于0的时候将数值返回。
a = [(i,j) for i in range(5) for j in range(5)] #表示将i和j的值以元组为元素的形式返回,当i循环一次的时候j循环5次,以此类推。
2.深拷贝与浅拷贝
- 深拷贝指的是复制内容,单独开辟一个内存。
- 浅拷贝指的是两个变量同时指向一个内存ID。
3.is 和 == 的区别
is 判断是否是一个ID, == 判断内容是否一致。
4.生成器
列表解析式,他的优点很多,比如运行速度快、编写简单,但是有一点我们不要忘了,他是一次性生成整个列表。如果整个列表非常大,这对内存也同样会造成很大压力,想要实现内存的节约,可以将列表解析式转换为生成器表达式。
python中有两种语言结构可以实现这种思路。
- 一个是生成器函数。没有用return语句一次性的返回整个结果对象列表,取而代之的是使用yield语句一次返回一个结果。
- 另一个是生成器表达式,类似于上一小节的列表解析,但是方括号换成了圆括号,他们返回按需产生的一个结果对象,而不是构建一个结果列表。
常规函数接受输入的参数然后立即送回单个结果,之后这个函数调用就结束了。生成器函数却不同,他通过yield关键字返回一个值后,还能从其退出的地方继续运行,因此可以随时间产生一系列的值。他们自动实现了迭代协议,并且可以出现在迭代环境中。
运行的过程是这样的:生成器函数返回一个迭代器,for循环等迭代环境对这个迭代器不断调用next函数,不断的运行到下一个yield语句,逐一取得每一个返回值,直到没有yield语句可以运行,最终引发StopIteration异常。
在每次循环的时候,生成器函数都会在yield处产生一个值,并将其返回给调用者,即for循环。然后在yield处保存内部状态,并挂起中断退出。在下一轮迭代调用时,从yield的地方继续执行,并且沿用上一轮的函数内部变量的状态,直到内部循环过程结束。
#生成器函数
def gen_squares(num):
for x in range(num):
yield x ** 2
for i in gen_squares(5):
print(i, end=' ')
#生成器表达式
g = (i ** 2 for i in range(5)) # 将使用生成器表达式得到的生成器对象赋给一个变量g
print(g)
5.迭代器
6.反射
一个对象能够在运行时,像照镜子一样,反射出其类型信息。在Python中,能够通过一个对象,找出其type、class、attribute或method的能力,称为反射或自省。
具有反射能力的函数有type(),isinstance(),callable().dir().getattr()等。
内建函数 | 意义 |
---|---|
getattr(object,name[,default]) | 通过name返回object的属性值,当属性不存在,将属性不存在,将使用default返回,如果没有default,则抛出AttributeError,name必须是字符串 |
setattr(object,name,value) | object的属性,则覆盖,不存在则新增 |
hasaattr(object,name) | 判断对象是否有这个名字的属性,name必须为字符串 |
反射相关的魔术方法
getattr()、setattr()、delattr()这三个魔术方法。
getattr():
实例属性会按照继承关系寻找,如果找不到,就会执行__getattr__()方法,如果没有这个方法,就会抛出AttributeError异常标识找不到属性
查找属性顺序为:
instance__dict__---->instance.class.dict---->继承的祖先类(直到object)的__dict__—>找不到—>调用setattr()
delattr():
可以阻止通过实例来删除属性的操作
7.多线程
使用多线程编程具有如下几个优点:
进程之间不能共享内存,但线程之间共享内存非常容易。
操作系统在创建进程时,需要为该进程重新分配系统资源,但创建线程的代价则小得多。因此使用多线程来实现多任务并发执行比使用多进程的效率高
python语言内置了多线程功能支持,而不是单纯地作为底层操作系统的调度方式,从而简化了python的多线程编程。
thread
Python通过两个标准库thread和threading提供对线程的支持。thread提供了低级别的、原始的线程以及一个简单的锁。
import thread
import time
# 一个用于在线程中执行的函数
def func():
for i in range(5):
print 'func'
time.sleep(1)
# 结束当前线程
# 这个方法与thread.exit_thread()等价
thread.exit() # 当func返回时,线程同样会结束
# 启动一个线程,线程立即开始运行
# 这个方法与thread.start_new_thread()等价
# 第一个参数是方法,第二个参数是方法的参数
thread.start_new(func, ()) # 方法没有参数时需要传入空tuple
# 创建一个锁(LockType,不能直接实例化)
# 这个方法与thread.allocate_lock()等价
lock = thread.allocate()
# 判断锁是锁定状态还是释放状态
print lock.locked()
# 锁通常用于控制对共享资源的访问
count = 0
# 获得锁,成功获得锁定后返回True
# 可选的timeout参数不填时将一直阻塞直到获得锁定
# 否则超时后将返回False
if lock.acquire():
count += 1
# 释放锁
lock.release()
# thread模块提供的线程都将在主线程结束后同时结束
time.sleep(6)
thread 模块提供的其他方法:
thread.interrupt_main(): 在其他线程中终止主线程。
thread.get_ident(): 获得一个代表当前线程的魔法数字,常用于从一个字典中获得线程相关的数据。这个数字本身没有任何含义,并且当线程结束后会被新线程复用。
thread还提供了一个ThreadLocal类用于管理线程相关的数据,名为 thread._local,threading中引用了这个类。
由于thread提供的线程功能不多,无法在主线程结束后继续运行,不提供条件变量等等原因,一般不使用thread模块,这里就不多介绍了。
threading
threading基于Java的线程模型设计。锁(Lock)和条件变量(Condition)在Java中是对象的基本行为(每一个对象都自带了锁和条件变量),而在Python中则是独立的对象。
threading 模块提供的常用方法:
threading.currentThread(): 返回当前的线程变量。
threading.enumerate(): 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。
threading.activeCount(): 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果。
threading模块提供的类:
Thread, Lock, Rlock, Condition, [Bounded]Semaphore, Event, Timer, local.
Thread
Thread是线程类,与Java类似,有两种使用方法,直接传入要运行的方法或从Thread继承并覆盖run():
import threading
# 方法1:将要执行的方法作为参数传给Thread的构造方法
def func():
print 'func() passed to Thread'
t = threading.Thread(target=func)
t.start()
# 方法2:从Thread继承,并重写run()
class MyThread(threading.Thread):
def run(self):
print 'MyThread extended from Thread'
t = MyThread()
t.start()
构造方法:
Thread(group=None, target=None, name=None, args=(), kwargs={})
group: 线程组,目前还没有实现,库引用中提示必须是None;
target: 要执行的方法;
name: 线程名;
args/kwargs: 要传入方法的参数。
实例方法:
isAlive(): 返回线程是否在运行。正在运行指启动后、终止前。
get/setName(name): 获取/设置线程名。
is/setDaemon(bool): 获取/设置是否守护线程。初始值从创建该线程的线程继承。当没有非守护线程仍在运行时,程序将终止。
start(): 启动线程。
join([timeout]): 阻塞当前上下文环境的线程,直到调用此方法的线程终止或到达指定的timeout(可选参数)。
Lock
Lock(指令锁)是可用的最低级的同步指令。Lock处于锁定状态时,不被特定的线程拥有。Lock包含两种状态——锁定和非锁定,以及两个基本的方法。
构造方法:
Lock()
实例方法:
acquire([timeout]): 使线程进入同步阻塞状态,尝试获得锁定。
release(): 释放锁。使用前线程必须已获得锁定,否则将抛出异常。