zoukankan      html  css  js  c++  java
  • 11ch

    11.1.1函数和过程

    函数可以不带参数,最后返回一个值,

    过程是简单,特殊,没有返回值的函数。

    返回的对象的数目 python实际返回的对象
    0   .None
    1 object
    >1 tuple

    11.2.2关键字参数

    你可以按顺序输入对应的参数也可以显式的给定参数

    比如:def foo(x)       foo(x = 2)

    11.2.4参数组

    你可以向函数传递没有显式定义的参数,比如元组和字典

     func(positional_args,keyword_args,*tuple_grp_nonkw_args, **dict_grp_kw_args)

     1 from operator import add, sub
     2 from random import randint, choice
     3 
     4 ops = {'+':add, '-':sub}
     5 MAXTRIES = 2
     6 def doprob():
     7     op = choice('+-')
     8     nums = [randint(1,10) for i in range(2)]
     9     nums.sort(reverse = True)
    10     ans = ops[op](*nums)
    11     pr = '%d %s %d='%(nums[0], op, nums[1])
    12     oops = 0
    13     while True:
    14         try:
    15             if int(raw_input(pr)) == ans:
    16                 print "correct"
    17                 break
    18             if oops == MAXTRIES:
    19                 print 'answer
     %s%d'%(pr,ans)
    20             else:
    21                 print'incorrect... try again'
    22                 oops += 1
    23         except (KeyboardInterrupt, 
    24                 EOFError, ValueError):
    25             print 'invalid input...try again'
    26 
    27 def main():
    28     while True:
    29         doprob()
    30         try:
    31             opt = raw_input('Again? [y]').lower()
    32             if opt and opt[0] == 'n':
    33                 break
    34         except(KeyboardInterrupt, EOFError):
    35             berak
    36 if __name__ == '__main__':
    37     main()

    这是一个让人解算术题的程序

     11.3.5内部/内嵌函数

    在函数的内部定义函数时,这个函数的作用域是它的外部函数。

    如果内部函数的定义里包含了对在外部函数里定义的对象的引用(或者说这个对象在外部函数之外),

    这时内部函数将是一个闭包(closure)

    11.3.6函数装饰器

    装饰器看起来是这样的:

    @decorator()

    def func2Bdecorated(func_opt_args):

    效果相当于

    def func2Bdecorated(func_opt_args):

    func2Bdecorated = decorator(func2Bdecorated)

    之前的例子中装饰器没有参数,现在给出有参数的例子:

    @deco1(deco_arg)

    @deco2

    def func():pass

    相当于
    func = deco1(deco_arg) (deco2(func))

    通过一个例子更好的理解装饰器:

     1 from time import ctime, sleep
     2 
     3 def tsfunc(func):
     4     def wrappedFunc():
     5         print '[%s] %s() called' % (ctime(), func.__name__)
     6         return func()
     7     return wrappedFunc
     8 
     9 @tsfunc
    10 def foo():
    11     pass
    12 
    13 foo()
    14 sleep(4)
    15 
    16 for i in range(2):
    17     sleep(1)
    18     foo()

    11.4传递函数

    在python中函数是可以作为参数传递的(在c语言中的回调函数)

    1 def convert (func, seq):
    2     'conv. sequence of numbers to same type'
    3     return [func (eachNum) for eachNum in seq]
    4 myseq = (123, 45.67, -6.2e8, 999999999L)
    5 print convert(int, myseq)
    6 print convert(long, myseq)
    7 print convert(float, myseq)

    一个抓取网页html代码的程序:

     1 from urllib import urlretrieve
     2 
     3 def firstNonBlank(lines):
     4     for eachLine in lines:
     5         if not eachLine.strip():
     6             continue
     7     else:
     8         return eachLine
     9 
    10 def firstLast(webpage):
    11     f = open(webpage)
    12     lines = f.readlines()
    13     f.close()
    14     print firstNonBlank(lines)
    15     lines.reverse()
    16     print firstNonBlank(lines),
    17 
    18 def download(url = 'http://www.baidu.com',
    19              process = firstLast):
    20     try:
    21         retval = urlretrieve(url)[0]
    22     except IOError:
    23         retval = None
    24     if retval:
    25         process(retval)
    26 
    27 if __name__ == '__main__':
    28     download()
    View Code

    11.6可变长度的参数

    通过元组和字典可以实现函数参数的长度可变,

    在描述这样一个函数时,参数的循序应该是 位置参数(调用时参数按顺序落位)--> 默认参数 --> 元组 --> 字典。

    函数式编程举例

    函数式编程的另外一个有用的应用出现在调试和性能测量的方面上

     1 def testit(func, *nkwargs):
     2     try:
     3         retval = func(*nkwargs)
     4         result = (True, retval)
     5     except Exception, diag:
     6         result = (False, str(diag))
     7     return result
     8 def test():
     9     funcs = (int, long, float)
    10     vals = (1234, 12.34,"1234", "12.34")
    11     for eachFunc in funcs:
    12         print "-" * 20
    13         for eachVal in vals:
    14             retval =testit(eachFunc, eachVal)
    15             if retval[0]:
    16                 print"%s(%s)=" % (eachFunc.__name__,eachVal), retval[1]
    17             else:
    18                 print "%s(%s) =failed:" % (eachFunc.__name__, eachVal), retval[1]
    19  
    20 if __name__ == "__main__":
    21     test()

    11.7函数式编程
    11.7.1匿名函数与lambda

    命名函数可以写成:def true(): return True

    而匿名函数则写成:lambda: True

    def add(x, y): return x+y

    lambda x, y: x + y

    在使用的时候,lambda要赋给一个变量

    11.7.2内建函数apply(), filter(), map(), reduce()

    filter(func, seq):seq中的每个元素都放进func,返回值为True的元素一起成一个序列,filter返回这个序列。

    这个函数的实现可以是这样:

    1 def filter(bool_func, seq):
    2     filtered_seq = []
    3     for eachItem in seq:
    4         if bool_func(eachItem):
    5             filtered_seq.append(eachItem)
    6 return filtered_seq

    应用filter()可以写一个获取任意奇数的代码

    from random import randint
    
    def odd(n):
        return n % 2
    allNums = []
    for eachNum in range(9):
        allNums.append(randint(1, 99))
    print filter(odd, allNums)

    第一次重构,使用lambda表达式:

    from random import randint
    allNums = []
    for eachNum in range(9):
        allNums.append(randint(1,99))
    print filter(lambda n: n%2, allNums)

    第二次重构,使用列表解析

    1 from random import randint
    2 
    3 allNums = []
    4 for eachNum in range(9):
    5     allNums.append(randint(1,99))
    6 print [n for n in allNums if n % 2]

    第三次重构,再度使用列表解析(并且重命名randint)

    1 from random import randint as ri
    2 print [n for n in [ri(1,99) for i in range(9)] if n % 2]

    3.map()

    map()将把函数映射到每个序列的元素上,并返回一个含有所有返回值的列表。

    zip()可以这样使用

    >>>zip([1,3,5],[2,4,6])

    [(1,2),(3,4),(5,6)]

    换成map()来模仿(这体现了map如何并发迭代序列的)

    >>>map(None, [1,3,5],[2,4,6])

    [(1,2),(3,4),(5,6)]

    4.reduce()

     reduce(func, [1,2,3]) = func(func(1,2),3)

    使用python来实现reduce():

    1 def reduce(bin_func, seq, init = None):
    2     lseq = list(seq)
    3     if init is None:
    4         res = lseq.pop(0)
    5     else:
    6         res = init
    7     for item in lseq:
    8         res = bin_func(res, item)
    9     return res

    像这样的代码:

    def mySum(x,y): return x+y
    allNums = range(5)
    total = 0
    for eachNum in allNums:
        total = mySum(total, eachNum)
    print total #10

    使用lambda和reduce()可以写成:

    print reduce((lambda x,y: x+y) , range(5))
    #10

    11.7.3偏函数应用

    当你使用包含大量参数的函数的时候,偏函数应用(PFA)可以帮助你避免写大量重复的代码(有点像模板)

    警惕关键字:
    为了让参数以正确的顺序传入函数,有时候你不得不使用关键字命名,这里有一个没用关键字命名的错误示例,

    baseTwoBAD = partial(int, 2)
    baseTwoBAD('10010')
    TypeError
    因为int(num, base)
    故num = 2,而'10010' = base
    所以我们应该使用关键字命名:
    baseTwo = partial(int, base = 2)
    baseTwo('10010')
    #18

     简单GUI类的例子

    使用GUI时常常会遇到很多参数,这时也很适合使用PFA

     1 from functools import partial
     2 import Tkinter
     3 root = Tkinter.Tk()
     4 Mybutton = partial(Tkinter.Button, root, fg='white',bg='blue')
     5 b1 = Mybutton(text = 'Button1')
     6 b2 = Mybutton(text = 'Button2')
     7 qb = Mybutton(bg = 'red', text = 'QUIT', command = root.quit)
     8 b1.pack()
     9 b2.pack()
    10 qb.pack(fill = Tkinter.X, expand=True)
    11 root.title('PFAs!')
    12 root.mainloop()

    11.8变量作用域

    11.8.2 global语句

    在函数内部使用global arg即可访问全局变量,而不会覆盖掉全局变量。

    11.8.4闭包

    如果在内部函数中对外部作用域(但不是全局作用域)的变量进行引用,那么内部函数就比认为是闭包(closure)的,

    定义在外部函数内,但由内部函数引用的变量被称为自由变量。

    例子:

    1 def counter(start_at=0):
    2     count = [start_at]
    3     def incr():
    4         count[0] +=1
    5     return count[0]
    6 return incr        

    >>>count = counter(5)

    >>>print count()

    6

    >>>print count()

    7

    一个使用闭包,装饰器的例子

     1 from time import time
     2 def logged(when):
     3     def log(f,*args,**kargs):
     4         print'''Called:
     5 function: %s
     6 args: %r
     7 kargs: %r''' %(f, args, kargs)
     8 
     9     def pre_logged(f):
    10         def wrapper(*args, **kargs):
    11             log(f, *args, **kargs)
    12             return f(*args, **kargs)
    13         return wrapper
    14 
    15     def post_logged(f):
    16         def wrapped(*args, **kargs):
    17             now = time()
    18             try:
    19                 return f(*args, **kargs)
    20             finally:
    21                 log(f,*args,**kargs)
    22                 print "time delta: %s" % (time()-now)
    23         return wrapped
    24     try:
    25         return {"pre":pre_logged,
    26                 "post":post_logged}[when]
    27     except KeyError, e:
    28         raise ValueError(e), 'must be "pre" or "post"'
    29 
    30 @logged("pre")
    31 def hello(name):
    32     print "Hello,", name
    33 
    34 hello("World!")
    View Code

    11.8.5作用域和lambda

     1 >>> def foo():
     2     y = 5
     3     bar = lambda(y):x+y
     4     print bar(y)
     5     y = 8
     6     print bar(y)
     7 
     8     
     9 >>> foo()
    10 15
    11 18
    12 >>> def foo():
    13     y = 5
    14     bar = lambda:x+y
    15     print bar()
    16     y = 8
    17     print bar()
    18 
    19     
    20 >>> foo()
    21 15
    22 18
    23 >>> def foo():
    24     y = 5
    25     bar = lambda y=y:x+y
    26     print bar()
    27     y = 8
    28     print bar()
    29 
    30     
    31 >>> foo()
    32 15
    33 15
    View Code

    lambda和普通的函数一样有作用域,lambda y=y将内置一个作用域在lambda里的局部变量y。

    11.10生成器

    协同程序:协同程序是可以运行的独立函数调用,可以暂停或者挂起,并从程序离开的地方继续或者重新开始

    (这本书讲的不好,生成器迭代器另外找资料看)

  • 相关阅读:
    空值判断(is not null)
    http协议相关面试题
    Linux基本面试题。(感觉也就这几个了)
    1、了解django运行流程
    python笔试常见题
    selenium中一些可能用到的js操作
    元素判断
    二次封装
    关于在阿里云上面安装mysql遇到的一些问题。
    linux常用的一些基本命令
  • 原文地址:https://www.cnblogs.com/autoria/p/4488790.html
Copyright © 2011-2022 走看看