标签:style class blog http tar ext
# -*- coding: utf-8 -*-
# ====================
#File: python
#Author: python
#Date: 2014
#====================
__author__ = ‘Administrator‘
#什么是函数
#就是引用,创建,使用
#例子
def foo():
print ‘233‘
foo()
#返回与函数类型
def foo1():#是一个过程
print ‘hello world!‘
foo1()
foo1=foo1()
foo1
print foo1#返回None
print type(foo1)
#return
def foo():
return [‘xyz‘,123]
def bar():
return ‘abc‘,[123]
print foo()
def bar():
return (1,[2,‘pythin‘],‘dog‘)
print bar()
bar1=bar()
print bar1
x,y,z=bar()
print x,y,z
#调用函数
#关键字
def f1(x):
print x+1
#f1()TypeError: f1() takes exactly 1 argument (0 given)
#f1(‘a‘)#TypeError: cannot concatenate ‘str‘ and ‘int‘ objects
f1(1)
#默认值
def f2(x=2):
print x
f2()
f2(3)
f2(‘a‘)
#参数组
#func(*tuples,**dicts)
#完整的函数语法如下
#func(pos1,pos2,keys,tu=[],*a,**k)
def fx(a,b,c,d=2,f=‘abc‘,*a1,**a2):
print a,b,c,d,f,a1,a2
fx(1,2,3)
#注意:d=2*a,**a,如果是这样的,可以不用输入
#例子
#!/usr/bin/env python
from operator import add, sub
from random import randint, choice
ops = {‘+‘:add,‘-‘:sub} # 全局字典
MAXTRIES = 2 # 全局尝试次数
def doprob(): #定义函数doprob
op = choice("+-") #random.choice()函数随机返回序列中的一个元素
nums = [randint(1,10) for i in range(2)] #[randint(1,10),randint(1,10)]
nums.sort(reverse = True)
ans = ops[op](*nums)
pr = ‘%d %s %d =‘ % (nums[0],op,nums[1])
oops = 0
while True:
try:
if int(raw_input(pr)) == ans:
print ‘correct‘
break
if oops == MAXTRIES:
print ‘answer\n%s%d‘ % (pr,ans)
else:
print ‘incorrect...try again‘
oops += 1
except (KeyboardInterrupt,\
EOFError,ValueError):
print ‘invalid input ...try agin‘
def main():
while True:
doprob()
try:
opt = raw_input(‘Again? [y]‘).lower()
if opt and opt[0] == ‘n‘:
break
except(KeyboardInterrupt,EOFError):
break
#创建函数
#语法
#def funcname(argme):pass
def hello(who):
print str(who)
#向前引用
#例子
#定义了barx()函数,在函数foo()前给出barx()声明
def barx():
print ‘a‘
def foo():
print ‘abcd‘
barx()
foo()
#位置交换一样
def foo():
print ‘abcd‘
barxq()
def barxq():
print ‘ok‘
foo()
#函数属性
#命名空间
#当导入pytho类,函数,模块等时,都会出现名称空间,例如 a1,a2这2个.py
import a1
import a2
print a1
print a2
print dir(a1)
print dir(a2)
print a1.a
print a2.aa
#函数属性是python另一个使用句点并拥有名称空间的领域
def f():
‘foo()222222222222222‘
def b():
‘__doc__ class‘
b.__doc__
f.a=1#函数属性
b.v=1
print b.v+f.a
help(f)
print f.__doc__
print b.__doc__
#嵌套函数
def foo1():
def bar2():
print u‘bar2在内部‘
print u‘foo1()在顶部‘
bar2()
foo1()
#bar2():NameError: name ‘bar2‘ is not defined
#内部函数作用域只在外部函数作用域内,外部访问不了。
#装饰器
"""
Python装饰器学习(九步入门) :http://www.cnblogs.com/rhcad/archive/2011/12/21/2295507.html
"""
#第一步:最简单的函数,准备附加额外功能
#调用2次
def myfunc():
print ‘myfunc().__doc__‘
myfunc()
myfunc()
#第二步:使用装饰函数在函数执行前和执行后分别附加额外功能
#装饰器参数是被装饰的函数,返回原函数对象
#语句体是myfunc=deco(myfunc)
def deco(func1):
print ‘myfunc()‘
func1()
print ‘myfunc func()‘
return func1
myfunc2=deco(myfunc)
myfunc2()
myfunc2()
#第三步:使用语法糖@来装饰函数
#使用语法糖@来装饰函数,相当于myfunc = deco(myfunc)
#但发现新函数只在第一次被调用,且原函数多调用了一次‘‘‘
def deco1(f1):
print ‘@f1‘
f1()
print ‘f1()@‘
return f1
@deco1
def myfunc1():
print ‘@@@@‘
myfunc1()
#第四步:使用内嵌包装函数来确保每次新函数都被调用
#使用内嵌包装函数来确保每次新函数都被调用,内嵌包装函数的形参和返回值与原函数相同,装饰函数返回内嵌包装函数对象
def de1(f2):
def _de11():
print ‘_de1()‘
f2()
print ‘_ed1‘
# 不需要返回f2,实际上应返回原函数的返回值
return _de11
@de1
def m1():
print ‘m1called‘
return ‘ok‘
m1()
m1()
#第五步:对带参数的函数进行装饰
#‘‘‘示例5: 对带参数的函数进行装饰,内嵌包装函数的形参和返回值与原函数相同,装饰函数返回内嵌包装函数对象‘‘‘
def a21(f):
def a211(a,b):
print ‘a211(a,b)‘
ret=f(a,b)
print ‘myfun called:%s‘%(ret)
return ret
return a211
@a21
def mx(a,b):
print ‘%s and %s‘%(a,b)
return a+b
mx(1,2)
mx(3,4)
#第六步:对参数数量不确定的函数进行装饰
#‘‘‘示例6: 对参数数量不确定的函数进行装饰,参数用(*args, **kwargs),自动适应变参和命名参数‘‘‘
def deco222(fx):
def deco2222(*a,**k):
print ‘befo:%s‘%(fx.__name__)
ret=fx(*a,**k)
print ‘%s %s‘%(fx.__name__,ret)
return ret
return deco2222
@deco222
def my(a,b,c):
print ‘%s %s %s‘%(a,b,c)
return a+b+c
my(1,2,3)
#第七步:让装饰器带参数
# ‘‘‘示例7: 在示例4的基础上,让装饰器带参数,和上一示例相比在外层多了一层包装。装饰函数名实际上应更有意义些‘‘‘
def ax(arg):
def _ax(func):
def __ax():
print func.__name__,arg
func()
print func.__name__,arg
return __ax
return _ax
@ax(‘mymoduel‘)
def myx():
print ‘@1‘
myx()
#传递函数
#当赋值给一个变量时,那么这个变量的效果与函数名一样,如果对象是函数当的话,那么这个对象的别名都是可调用的
def f1x():
print ‘f1x()11‘
f2x=f1x()
#可以把函数做为参数传入到其他来进行调用
def bar1(a):
a()
bar1(f1x)
#传递和调用函数
def abc(a22):
print a22
def conv(func,seq):
return [func(axa)for axa in seq ]
abv=(123,456,100000)
print conv(int,abv)
#func参数
def xyz01():
pass
def xyz02(a):
print a
xyz01()
#xyz02()TypeError: xyz02() takes exactly 1 argument (0 given)
#xyz02(1,2)TypeError: xyz02() takes exactly 1 argument (2 given)
xyz02(‘abcd‘)
#这里说明,当func括号里面的变量,有多少时,就需要多少变量的值
#默认值
def mrz(a,b=2):
return a*a+b
print mrz(1)
print mrz(1,1)
#def axxx(a=2,b):这样表示不合法
def nte(a,b,c=1,d=‘year‘):
print a,b,c,d
nte(1,2)
nte(1,2,3,4)
nte(1,2,3)
nte(a=2,b=‘year2‘)
#可变长度的参数
#非关键字可变长参数(元组)
def func1(*a):
print a
func1(1,2,3,4,[‘a‘,‘b‘])
func1()
def func2(a,b,c=2,*d):
print a,b,c,d
func2(1,2,3,3,4,5,6,7,8,9,0)
#关键字变量参数(字典)
def func3(**a):
print a
func3(a=1,b=2,c=4,d=‘str‘)
#混合
def func4(a,b=1,c=‘str‘,d=[],*f,**z):
print a,b,c,d,f,z
func4(1)
#函数式编程(重点)
#匿名函数与lambda
#lambda语法:
"""
lambda arg1[,arg2,...argn]:exr
lambda只是一个表达式,不会把这个函数对象赋给一个标识符,而def则会把函数对象赋值给一个变量
"""
#例子
def tr():
return
#lambda写法
print lambda :True
trune=lambda :True
print trune()
#带参数的
def add1(a,b):return a+b
print add1(1,2)
x_y=lambda x,y:x+y
print x_y(1,2)
#or
a=lambda x,y=2:x+y
print a(1.2,20)
b=lambda *z:z#元组
print b(2,3,4,5,6,7)
c=lambda *z,**a:(z,a)
print c(1,2,3,4)
#4大内建函数体
"""
apply(function, args[, keywords])
#用可选参数来调用function,args为非关键字参数,keywords关键字参数,返回值是函数调用
"""
#未带参数的
def s():
return ‘hello‘
print apply(s)
print apply(lambda:True)
#函数只带元组的参数
def s1(a,b):
return a,b
print apply(s1,(1,2))
#函数带关键字参数
def s2(a=1,b=2):
print a,b
def s3(*a):
return apply(s2,a)
s3()
#filter(function, sequence):对sequence中的item依次执行function(item),将执行结果为True的item组成一个List/String/Tuple(取决于sequence的类型)返回
#编写filter函数功能
# def fiters1(a,b):
# l=[]
# for item1 in b:
# if a(item1):
# l.append(item1)
# return l
from random import randint
def odd(n):
return n%2
a1=[]
for i in range(9):
a1.append(randint(1,99))
print filter(odd,a1)
b=filter(lambda x:x>5,range(1,9))
print b
#如果filter参数值为None,就使用identity()函数,list参数中所有为假的元素都将被删除。如下所示:
a=[0,1,2,3,4,5,6,7,-1,0]
b=filter(None,a)
print b
#map(function, iterable, ...)对一个序列对象中的每一个元素应用被传入的函数,并且返回一个包含了所有函数调用结果的一个列表。
print map(lambda x:x+3,range(1,9))
a=[1,2,3]
b=[4,5,6]
c=[7,8,9]
print map(lambda x,y,z:x+y+z,a,b,c)
#reduce(function, sequence[, initial]) -> value
#reduce 函数可以按照给定的方法把输入参数中上序列缩减为单个的值,具体的做法如下:首先从序列中去除头两个元素并把它传递到那个二元函数中去,求出一个值,再把这个加到序列中循环求下一个值,直到最后一个值 。
print reduce(lambda x,y:x*y,[1,2,3],10)#1,2,3,10
print reduce(lambda x,y:x+y+2,list(range(5)),10)
#继续函数式编程
#filter(function, sequence)
def f(x):
return x*2>10
f1=filter(f,range(2,25))
print f1
#map(function, sequence)
def xxx(x):
return x**3
print map(xxx,range(1,11))
seq=range(8)
def x2(a,b):
return a+b
print map(x2,seq,seq)
#reduce(function, sequence)
def add1(a,b):
return a+b
print reduce(add1,range(1,11))
def syn(ds):
def addx(x,y):
return x+y
return reduce(addx,ds,0)
print syn(range(1,11))
#偏函数应用
"""
使用functools模块中的partial()函数创建偏函数, 第一个参数是基函数的引用, 后面跟随基函数的调用中要使用的一些默认值…这里还可以使用关键字参数调用的方式:
toDecimal = partial(int, base = 2)
调用的时候, 只需要指定在partial中没有指定的参数, 比如: toDecimal(‘101010’)
由于在partial中指定的这些固定的参数是在参数列表的最左边, 所以, 如果不使用关键字参数, 可能会导致参数顺序错误.
"""
#例子
from operator import add,mul
from functools import partial#偏函数
add1=partial(add,1)
mul11=partial(mul,100)
print add1(10)
print mul11(2)
#进制转换
basetwo=partial(int,base=2)
basetwo.__doc__=‘convert base 2string to an int.‘
print basetwo(‘101010‘)
#变量作用域
#全局和局部
"""
简单说来:在函数或者类外面的叫全局变量
在函数或者类内的叫局部变量
"""
#例子
globs1=1
def gl():
locas11=1
print globs1
print locas11
gl()
#globa语句
#语法:globa var[,var2,......]
#作用域的数字
#最多2个作用域
"""
一个函数在局部作用域和全局作用域
,虽然存在多个函数嵌套,但不能访问超过2个作用域
"""
def foo():
m=3
z=1111
def bar():
print m
n=4
print m+n
print z
bar()
#print m:NameError: name ‘m‘ is not defined
#bar()
print ‘foo()‘
foo()
#详细说明:python变量作用域 http://www.cnblogs.com/wait123/archive/2011/09/14/2175554.html
#闭包
#在2.1之前,当作用域规则改变今天之前,内部函数也会遭受相同的问题,如果在一个内部函数里面,对在外部作用域(不是全局作用域)的变量进行引用,那么内部函数就被认为是闭包
#宣言在外部函数内但由内部函数引用或者使用的变量称为自由变量
"""
闭包: 将内部函数自己的代码和作用于以外的外部函数的作用结合起来, 在一个独立的作用域中, 多用于安装计算, 隐藏状态, 函数对象和作用于中随意切换, 回调.
自由变量: 定义在外部函数内(非全局变量), 但是由内部函数引用或者使用的变量.
闭包: 如果在一个函数内, 对在外部作用域的变量(自由变量)进行引用, 那么这个内部函数就被认为是闭包(closure)
闭包完成的功能很像类.
闭包将内部函数自己的代码和作用域以外的外部函数作用结合起来…闭包的词法变量不属于全局名字空间域也不属于局部的, 而是属于其他的名字空间, 带着”流浪”的作用域. 但是, 这又不同于对象, 对象的变量存活在对象的名字空间, 而闭包变量存活在一个函数的名字空间和作用域.
"""
#语法:
"""
def func(s1,s2,s3):#定义外部函数体
args=[a1,a2,a3]#自由变量的参数放到一个可变对象中
def func1(s1):定义嵌套1内部函数,可以接受自己想要的参数
args[0]+=args[1]+s1#改变自由变量,上面将自由变量放到一个可变对象中是为了能够保存这种改变
return args[0]#返回修改后的自由变量值
return func1
"""
#调用
#clouer=func(1,2,3)#得到一个闭包(调用外部函数,返回内部函数引用,实际上就形成一个闭包,这个闭包作用域内持有外部函数内定义args自由变量和内部函数本身)
#closure2 = out_function(4, 5, 6) //得到一个闭包
#closure1(100) //调用闭包局部的实参是100
#closure2(200) //调用闭包返回的
"""
调用闭包返回的结果很类似调用对象的方法, 但是, 闭包是一种能够有自己的独立作用域的方法, 而对象则是类实例.
得到一个闭包的实例(实际上就是一个方法), 查看它的func_closure属性, 可以查看该闭包含有的自由变量.
一个闭包和装饰器结合的绝妙的例子见python-15-function下的closureAndDecorator4Log.py
"""
#简单装饰的例子
def count11(start1=0):
count1=[start1]
def icr():
count1[0]+=1
return count1[0]
return icr
#count11()做了唯一一件事情,接受一个初始化值来计数,并将该值赋值给列表count1唯一一个成员,然后定义icr()内部函数
#通过内部使用变量count1这样就创建了一个闭包,因为它现在携带了整个count11()作用域,icr()增加了正在运行的count1返回它,然后最后魔法就 count11()返回icr
#一个(可调用的)函数对象,
print u‘调用这个闭包呢‘
count2=count11(5)
print count2()
print count2()
count21=count11(100)
print count21()
print count2()
#闭包高级部分暂时不看
#作用域与lambda
#lambda定义的函数作用域, 生命周期和普通函数是一致的, lambda也可以不指定参数, 也可以使用全局或外部变量.
#例子:
x=100#全局变量
def foo():
y=5
bar=lambda :x+y
print bar()
foo()
#注意:在2.1之前如果是上面的例子,就会出现错误,虽然lambda表达式在foo()局部作用域中创建,但它仅仅只能访问大个作用域:它自己局部作用域和全局作用域
#解决方法是这样的,设置一个默认参数:var=lambda y=y:x+y
#由于这个改变了,程序也能运行,外部y值会作了一个参数,成为局部y(lambda函数局部变量)
#比如
x1=10
def foo():
y1=5
bar=lambda y1=y1:x1+y1
print bar()
y1=8
print bar()
foo()
#虽然未出现异常,但错误了
#原因是外部的y值被传入在lambda中设置,虽然后面的值也改变了,但是lambda定义的未改变,解决方法是:在lambda表达式匮加入对函数局部y的引用局部变量z
#重点
x2=10
def f11():
yx=5
bar=lambda z:z+x2
print bar(yx)
yx=8
print bar(yx)
f11()
#变量作用域与名称空间
#例子:
j,k=1,2
def proc1():
j,k=3,4
print ‘j==%d and k==%d‘%(j,k)
k=5
def proc2():
j=6
proc1()
print ‘j==%d and k==%d‘%(j,k)
k=7
proc1()
print ‘j==%d and k==%d‘%(j,k)
j=8
proc2()
print ‘j==%d and k==%d‘%(j,k)
#在函数体和类体中,查找局部变量和全局变量的位置是:
"""
先从局部变量中查找,当如果局部变量中存在时,返回变量,当局部变量不存在时,再到全局变量查找,当全局变量未想找时,出现异常
位置是从下往上,从左到右的顺序进行查找
"""
#递归
#概念
"""
如果函数包含了对其自身的调用,该函数就是递归的。拗口一点的定义是,如果一个新的调用能在相同过程中较早的调用结束之前开始,那么个该过程就是递归
"""
#详细说明:http://www.cnblogs.com/balian/archive/2011/02/11/1951054.html
#例子
def f(n):
if n==0 or n==1:
return 1
else:
return n*f(n-1)#递归
print f(5)
#说明: 一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法 or 是指在函数的定义中使用函数自身的方法
# 一个超级短的递归阶乘函数: f = lambda n: n == 1 and 1 or (n == 2 and 2 or n * a(n - 1))
#函数生成器
#什么叫生成器
"""
带一个yield语句的函数,一个函数或者子程序只返回一次,但一个生成器能暂停执行并返回一个中间结果(yield功能),当生成器调用next()方法时,它会准确离开这个地址继续
"""
#特征:当到达一个真正的返回或者函数结束没有更多值返回(调用next()),一个stopiteration异常就会抛出
def s1f():
yield 1
yield ‘2-python‘
my=s1f()
print my.next()
print my.next()
print ‘for i.next()‘
#print my.next() StopIteration
#这边for循环有next()调用和StopIteration处理,使用一个for循环比上面的写的代码简洁
for i in s1f():
print i
#许多动机源自身能够迭代穿越序列,而这需要这个函数威力而不是在某个序列中静态对象
#定义: 挂起返回出中间值并多次继续的协同程序成为生成器.
#生成器语法:
"""
def func([ars]):
for i in ars:
yield i
"""
#调用实例
"""
bl=func([ars])
bl.next()
"""
#其他说明
"""
生成器的创建使用了yield语法, 在调用next方法的时候, 返回下一个yield指示的值, 并让生成器在这个位置停留.
当然, yield也可以指示做某一个动作之后停止. 甚至还允许yield指示的动作返回的是一个None
生成器适用于较大的数据场合.
生成器的创建函数中不能有return
生成器还可以接收外部传送回来的数据进行交互. 在外部调用生成器的send方法可以向生成器发送数据,
send方法接受一个参数, 这个参数的值就是yield argument_name词法的返回值. send方法返回的是经过处理之后到下一次yield的值,
其实是和调用next()方法的返回值是一样的, 不过这次是经过了send进来的数据的处理方式.
"""
#例子1
def get01():
yield 1,2,3
print get01()#<generator object get01 at 0x0000000002783360>
get1=get01()
print get1#<generator object get01 at 0x0000000002833360>
#当调用生成器next()方法蜈,生成器才开始执行生成函数(而不是构建生成器时),直接遇到yield暂时执行(挂起),并且yield参数将作为此次next()方法返回值
print get1.next()#(1, 2, 3)
#print get1.next() StopIteration
#4.如果当调用next方法时生成器函数结束(遇到空的return语句或是到达函数体末尾),则这次next方法的调用将抛出StopIteration异常(即for循环的终止条件);
#生成器函数每次暂停执行时,函数体内所有变量将被封存在生成器中,并将的恢复执行时,还原,类似闭包,即使同一个生成器函数返回生成器,封存的变也是互相独立的
def fx():
a=b=1
yield a
yield b
while True:
a,b=b,a+b
yield b
for num in fx():
if num>100:
break
print num;
#看到while True可别太吃惊,因为生成器可以挂起,所以是延迟计算的,无限循环并没有关系。
#生成器函数的FAQ(其他部分)
#生成器可以带参数嘛?当前可以,它支持参数格式
def counts(s=0):
while True:
yield s
s+=1
counts1=counts(2)
print u‘带参数可以的‘
print counts1.next()
print counts1.next()
#从指定数开始计数
#生成器可以使用return 输出返回值?是不可以的
def _retnr():
yield None
#return None生成器函数已经有默认的返回值——生成器了,你不能再另外给一个返回值;对,即使是return None也不行。但是它可以使用空的return语句结束。如果你坚持要为它指定返回值,那么Python将在定义的位置赠送一个语法错误异常,就像这样:
return #这样是可以的
return1=_retnr()
print return1.next()
#释放资源呢?Python会在真正离开try...finally时再执行finally中的代码
def play_u():
try:
yield 1
yield 2
yield 3
finally:
yield 0
for valiu in play_u():print valiu
"""
*这与return的情况不同。return是真正的离开代码块,所以会在return时立刻执行finally子句。
*另外,“在带有finally子句的try块中yield”定义在PEP 342中,这意味着只有Python 2.5以上版本才支持这个语法,在Python 2.4以下版本中会得到语法错误异常
"""
#4.如果我需要在生成器的迭代过程中接入另一个生成器的迭代怎么办?
def sub_get():
yield 1
yield 2
for val in counts(10):
print val
break
sub1=sub_get()
print sub1.next()
print sub1.next()
#协同程序(coroutine)
"""
协同程序(协程)一般来说是指这样的函数:
?彼此间有不同的局部变量、指令指针,但仍共享全局变量;
?可以方便地挂起、恢复,并且有多个入口点和出口点;
?多个协同程序间表现为协作运行,如A的运行过程中需要B的结果才能继续执行。
"""
#特点
"""
决定了同一时刻有一个协同程序正在运行(忽略多线程情况),协和间可以直接传递而不需要考虑资源锁,或者是直接唤醒其他协程而不需要主要休眠,就是内置锁的纯种,在符合协程特点的应用场景,使用协程比线程方便
从另一方面说,协程无法并发其实也将它的应用场景限制在了一个很狭窄的范围,这个特点使得协程更多的被拿来与常规函数进行比较,而不是与线程。当然,线程比协程复杂许多,功能也更强大
"""
#2.5中对生成器增强了
#send(value):
"""
send是除next外另一个恢复生成器的方法。Python 2.5中,yield语句变成了yield表达式,这意味着yield现在可以有一个值,而这个值就是在生成器的send方法被调用从而恢复执行时,调用send方法的参数。
"""
def reprs():
n=0
while True:
n=(yield n)
re1=reprs()
print ‘send()‘
print re1.next()
print re1.send(10)
"""
*调用send传入非None值前,生成器必须处于挂起状态,否则将抛出异常。不过,未启动的生成器仍可以使用None作为参数调用send。
*如果使用next恢复生成器,yield表达式的值将是None。
"""
"""
2.close():
这个方法用于关闭生成器。对关闭的生成器后再次调用next或send将抛出StopIteration异常。
3.throw(type, value=None, traceback=None):
这个方法用于在生成器内部(生成器的当前挂起处,或未启动时在定义处)抛出一个异常。
"""
#更多:http://www.cnblogs.com/huxi/archive/2011/07/14/2106863.html
python基础学习09(核心编程第二版)部分,布布扣,bubuko.com
标签:style class blog http tar ext
原文地址:http://www.cnblogs.com/mhxy13867806343/p/3810099.html