python学习总结(函数进阶)
-------------------程序运行原理-------------------
1、模块的内建__name__属性,主模块其值为__main__,导入模块其值为模块名
1、创建时间,py文件比pyc文件新,则从新生成pyc。
2、magic num,做运行前版本测试,版本不同重新生成pyc。
3、PyCodeObject对象,源代码中的字符串,常量值,字节码指令,原始代码行号的对应关系。
2、LEGB规则
1、Local :本地
当前所在命名空间(如函数,模块),函数的参数也属于命名空间内的变量。
2、Ecolsing function :外部嵌套函数的命名空间
外部嵌套函数的命名空间(闭包中常见)。
3、Global :全局
全局变量,函数定义所在模块的命名空间。
4、Builtins :内建模块命名空间
1、Python 在启动的时候会自动为我们载入很多内建的函数、类, 比如 dict,list,type,print,这些都位于 __builtins__ 模块中,可以使用 dir(__builtins__) 来查看。
2、在Python中,有一个内建模块,该模块中有一些常用函数;在Python启动后,且没有执行程序员所写的任何代码前,Python会首先加载该内建函数到内存。另外,该内建模块中的功能可以直接使用,不用在其前添加内建模块前缀,其原因是对函数、变量、类等标识符的查找是按LEGB法则,其中B即代表内建模块。
3、dir函数
Python 的内置函数 dir 可以用来查看一个命名空间下的所有名字符号。一个用处是查看一个命名空间的所有属性和方法(这里的命名空间就是指类、函数、module)。
4、垃圾回收
1、小整数对象池:
1、整数在程序中的使用非常广泛,Python为了优化速度,使用了小整数对象池, 避免为整数频繁申请和销毁内存空间。
2、Python 对小整数的定义是 [-5, 257) 这些整数对象是提前建立好的,不会被垃圾回收。在一个 Python 的程序中,所有位于这个范围内的整数使用的都是同一个对象。
2、大整数对象池:每一个大整数,均创建一个新的对象。
3、intern机制:
python中有这样一个机制——intern机制,让他只占用一个”HelloWorld”所占的内存空间。靠引用计数去维护何时释放。
5、小结
1、小整数[-5,257)共用对象,常驻内存。
2、单个字符共用对象,常驻内存。
3、单个单词,不可修改,默认开启intern机制,共用对象,引用计数为0,则销毁。
4、字符串(含有空格),不可修改,没开启intern机制,不共用对象,引用计数为0,销毁 。
5、大整数不共用内存,引用计数为0,销毁 。
6、注:数值类型和字符串类型在 Python 中都是不可变的,这意味着你无法修改这个对象的值,每次对变量的修改,实际上是创建一个新的对象。
6、def指令
1、def func(),在字节码指令中就是 MAKE_FUNCTION。 Python 是动态语言,def 实际上是执行一条指令,用来创建函数 (class 则是创建类的指令),而不仅仅是个语法关键字。 函数并不是事先创建好的,而是执行到的时候才创建的。
2、def func() 将会创建一个名称为 func 的函数对象。 实际上是先创建一个函数对象,然后将 func 这个名称符号绑定到这个函数上。
7、import导入包时进行搜索路径:
1、路径搜索:
import sys
sys.path :查看导入包路径
2、程序执行时导入模块路径
sys.path.append('/home/usr/local/images')
sys.path.insert(0,'/home/usr/local/image')
3、设置linux下导入模块路径
echo $pythonpath
export pythonpath=$pythonpath:'/home/usr/local/image'
4、如果程序已经引用了模块,但是模块被修改。需要重新导入模块:
可使用reload(module)进行,类似于情况缓存后进行import操作
7、pyc文件
1、概念
pyc 文件是 PyCodeObject 对象在硬盘上的表现形式。生成pyc文件:
2、pyc文件三大作用
1、创建时间,py文件比pyc文件新,则从新生成pyc文件
2、magic num做运行前版本检测,版本不同从新生产pyc
3、PyCodeObject对象
4、在运行期间,编译结果也就是 PyCodeObject 对象,只会存在于内存中,而当这个模块的 Python 代码执行完后,就会将编译结果保存到了 pyc 文件中,这样下次就不用编译,直接加载到内存中。
5、这个 PyCodeObject 对象包含了 Python 源代码中的字符串,常量值,以及通过语法解析后编译生成的字节码指令。PyCodeObject 对象还会存储这些字节码指令与原始代码行号的对应关系,这样当出现异常时,就能指明位于哪一行的代码。
8、import指令
1、import 指令是用来载入 module 的,如果需要,也会顺道做编译的事。但 import 指令,还会做一件重要的事情就是把 import 的那个 module 的代码执行一遍,这件事情很重要。 Python 是解释执行的,连函数都是执行的时候才创建的。如果不把那个 module 的代码执行一遍,那么 module 里面的函数都没法创建,更别提去调用这些函数了。
2、执行代码的另外一个重要作用,就是在这个 module 的命名空间中,创建模块内定义的函数和各种对象的符号名称(也就是变量名),并将其绑定到对象上,这样其他 module 才能通过变量名来引用这些对象。
3、Python 虚拟机还会将已经 import 过的 module 缓存起来,放到一个全局 module 集合 sys.modules 中。 这样做有一个好处,即如果程序的在另一个地方再次 import 这个模块,Python 虚拟机只需要将全局 module 集合中缓存的那个 module 对象返回即可。
-------------------闭包-------------------
1、概念:
内部函数对外部函数作用域里变量的引用(非全局变量),则称内部函数为闭包。
2、案例:
#外部函数
def counter(start=0):
#自由变量:定义一个列表
count = [start]
#内部函数
def incr():
count[0] += 1
return count[0]#返回列表结果
#返回函数
return incr
#变量接受一个函数
con = counter(5)
#运行接收到的函数
print con()
print con()
-------------------装饰器-------------------
1、引用通用功能处理
1、常用处理功能:
1、引入日志
2、函数执行时间统计
3、执行函数前预备处理
4、执行函数后清洗功能
5、权限校验等场景
6、缓存
2、案例:无参函数
#引用对应的包
from time import ctime
#修饰器
def timefun(func):
def wrappedfunc():
print("%s called at %s"%(func.__name__,ctime()))
return func()
return wrappedfunc
@timefun
def foo():
print("I am foo")
foo()
3、案例:装饰器和闭包混用
#coding=utf-8
from time import time
def logged(when):
def log(f, *args, **kargs):
print("fun:%s args:%r kargs:%r" %(f, args, kargs))
#%r字符串的同时,显示原有对象类型
def pre_logged(f):
def wrapper(*args, **kargs):
log(f, *args, **kargs)
return f(*args, **kargs)
return wrapper
def post_logged(f):
def wrapper(*args, **kargs):
now=time()
try:
return f(*args, **kargs)
finally:
log(f, *args, **kargs)
print("time delta: %s"%(time()-now))
return wrapper
try:
return {"pre":pre_logged, "post":post_logged}[when]
except KeyError, e:
raise ValueError(e), 'must be "pre" or "post"'
@logged("post")
def fun(name):
print("%s"%(name))
fun("hello word!")
-------------------内建函数-------------------
1、概念:
1、Build-in Function,启动python解释器,输入dir(builtins), 可以看到很多python解释器启动后默认加载的属性和函数,这些函数称之为内建函数, 这些函数因为在编程时使用较多,cpython解释器用c语言实现了这些函数,启动解释器 时默认加载。
2、这些函数数量众多,不宜记忆,开发时不是都用到的,待用到时再help(function), 查看如何使用,或结合百度查询即可,在这里介绍些常用的内建函数。
2、range
1、help(range):
range(stop) -> list of integers
range(start, stop[, step]) -> list of integers
2、参数分析:
1、start:计数从start开始。默认是从0开始。例如range(5)等价于range(0, 5)。
2、stop:到stop结束,但不包括stop.例如:range(0, 5) 是[0, 1, 2, 3, 4]没有5。
3、step:每次跳跃的间距,默认为1。例如:range(0, 5) 等价于 range(0, 5, 1)。
3、示例:
a = range(5)
list(a)
3、map
1、help(map):
map(...)
map(function, sequence[, sequence, ...]) -> list
2、参数分析:
1、function:是一个函数
2、sequence:是一个或多个序列,取决于function需要几个参数
3、返回值是一个list
3、语法:
参数序列中的每一个元素分别调用function函数,返回包含每次function函数返回值的list。
4、示例
#函数需要一个参数
map(lambda x: x*x, [1, 2, 3])
[1, 4, 9]
#函数需要两个参数
map(lambda x, y: x+y, [1, 2, 3], [4, 5, 6])
[5, 7, 9]
#函数为None,相当于合并参数为元祖
map(None, [1, 3, 5, 7, 9], [2, 4, 6, 8, 10])
[(1, 2), (3, 4), (5, 6), (7, 8), (9, 10)]
#两个序列参数个数不一致时,个数少的补None
map(None, [1, 3, 5, 7, 9], [2, 4, 6])
[(1, 2), (3, 4), (5, 6), (7, None), (9, None)]
4、filter
1、help(filter):
filter(...)
filter(function or None, sequence) -> list, tuple, or string
Return those items of sequence for which function(item) is true. If
function is None, return the items that are true. If sequence is a tuple
or string, return the same type, else return a list.
2、参数分析:
1、function:接受一个参数,返回布尔值True或False
2、sequence:序列可以是str,tuple,list
3、语法
filter函数会对序列参数sequence中的每个元素调用function函数,最后返回的结果包含调用结果为True的元素。返回值的类型和参数sequence的类型相同
4、示例
filter(lambda x: x%2, [1, 2, 3, 4])
[1, 3]
filter(None, "she")
'she'
5、reduce
1、help(reduce):
reduce(...)
reduce(function, sequence[, initial]) -> value
Apply a function of two arguments cumulatively to the items of a sequence,
from left to right, so as to reduce the sequence to a single value.
For example, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) calculates
((((1+2)+3)+4)+5). If initial is present, it is placed before the items
of the sequence in the calculation, and serves as a default when the
sequence is empty.
2、参数分析:
1、function:该函数有两个参数
2、sequence:序列可以是str,tuple,list
3、initial:固定初始值
3、语法
reduce依次从sequence中取一个元素,和上一次调用function的结果做参数再次调用function。 第一次调用function时,如果提供initial参数,会以sequence中的第一个元素和initial 作为参数调用function,否则会以序列sequence中的前两个元素做参数调用function。 注意function函数不能为None。
4、示例
reduce(lambda x, y: x+y, [1,2,3,4])
10
reduce(lambda x, y: x+y, [1,2,3,4], 5)
15
reduce(lambda x, y: x+y, ['aa', 'bb', 'cc'], 'dd')
'ddaabbcc'
6、sorted
1、help(sorted):
sorted(...)
sorted(iterable, cmp=None, key=None, reverse=False) --> new sorted list
2、参数分析:
自定义cmp比较函数,返回三种情况:
x<y 返回-1
x>y 返回1
x==y 返回0
3、示例
def cmp_ignore_case(s1, s2):
u1 = s1.upper()
u2 = s2.upper()
if u1 < u2:
return -1
if u1 > u2:
return 1
return
-------------------迭代器-------------------
1、概念:
迭代器仅是一容器对象,它实现了迭代器协议。
2、next():
1、返回容器的下一个元素
2、在结尾时引发Stoplteration异常
3、iter():
数据通过iter转换为跌打器的格式,返回跌打器自身
-------------------生成器-------------------
1、概念:
生成器是这样一个函数,它记住上一次返回时在函数体中的位置。对生成器函数的第二次(或第 n 次)调用跳转至该函数中间,而上次调用的所有局部变量都保持不变。
2、特点:
1.生成器是一个函数,而且函数的参数都会保留。
2.迭代到下一次的调用时,所使用的参数都是第一次所保留下的,即是说,在整个所有函数调用的参数都是第一次所调用时保留的,而不是新创建的
3.节约内存
3、案例:
#generation.py
def gen():
for x in xrange(4):
tmp = yield x
if tmp == "hello":
print "world"
else:
print "itcastcpp ", str(tmp)
#执行到yield时,gen函数作用暂时保存,返回x的值;tmp接收下次c.send("python"),send发送过来的值,c.next()等价c.send(None)
>>>from generation import gen
>>>c=gen()
>>>c.next()
0
>>>c.next()
itcastcpp None
1
>>>c.send("python")
itcastcpp python
2
4、应用场景:
1、当需要一个非常大的列表时,为了减少内存消耗,可以使用生成器
案例:
class A(object):
def __init__(self, i):
from time import sleep, time
sleep(i)
print (time())
1、for c in [A(i) for i in range(5)] :[]是通过遍历可迭代对象生成一个list
2、for c in (A(i) for i in range(5)) :()是直接返回可迭代对象
5、小结:
1、无限递归成为可能
2、极大的降低了线程或进程间上下文切换的开销
3、用户手工指定线程调用,避免了锁开销
-------------------上下文-------------------
-------------------functools函数-------------------
1、概念:
functools 是python2.5被引人的,一些工具函数放在此包里。
2、操作:
1、import functools :引用对应的包
2、dir(functools) :查看包中对应的工具函数
1、partial函数(偏函数):
1、概念:
把一个函数的某些参数设置默认值,返回一个新的函数,调用这个新函数会更简单。
2、示例:
import functools
def showarg(*args, **kw):
print(args)
print(kw)
p1=functools.partial(showarg, 1,2,3)
p1()
p1(4,5,6)
p1(a='python', b='itcast')
p2=functools.partial(showarg, a=3,b='linux')
p2()
p2(1,2)
p2(a='python', b='itcast')
2、wraps函数:
1、概念:
使用装饰器时,有一些细节需要被注意。例如,被装饰后的函数其实已经是另外一个函数了(函数名等函数属性会发生改变)。Python的functools包中提供了一个叫wraps的装饰器来消除这样的副作用
2、示例:
import functools
def note(func):
"note function"
@functools.wraps(func)
def wrapper():
"wrapper function"
print('note something')
return func()
return wrapper
@note
def test():
"test function"
print('I am test')
test()
print(test.__doc__)