Python快速学习第五天

    xiaoxiao2025-06-05  15

    第五天:抽象

    1、    函数

    检测函数是否可调用:callable

    >>> import math

    >>> y=math.sqrt

    >>> callable(y)

    True

    >>> x=1

    >>> callable(x)

    False

       注意:Python3.0不在支持callable,需要使用表达式hasattr(func,_call_call_)代替

       创建函数:def functionname(params):

    >>>def fibs(num):

    ...     'Get fibonaqi sequnce! '

    ...     result=[0,1]

    ...     for i in range(num-2):

    ...            result.append(result[-2]+result[-1])

    ...     return result

    ...

    >>>fibs(10)

    [0, 1,1, 2, 3, 5, 8, 13, 21, 34]

     

    用于def后面的'Getfibonaqi sequnce! '添加文档字符串,相当于注释#,使用help()可以查询函数的文档字符串

    help(fibs)

    Help on function fibs in module __main__:

     

    fibs(num)

        Getfibonaqi sequnce!

    ...skipping...

    Help on function fibs in module __main__:

     

    fibs(num)

        Getfibonaqi sequnce!

     

     return后不加值,只表示函数的结束,而没有返回值,这样可以避免应该返回序列时,意外返回None

    >>> def test():

    ...     print 'tanggao'

    ...     return

    ...     print 'tanggao isgood'

    ...

    >>> x=test()

    tanggao

    >>> print x

    None

     

    2、   参数对外部变量影响

       函数内给参数赋值,不会改变外部变量的值,参数存储在局部作用域中

    >>> def try_to_change(n):

    ...     n=3

    ...

    >>> t=4

    >>> try_to_change(t)#虽然在函数内部重新赋值,但外部不变

    >>> t

    4

     

    但是对于可改变的数据结构,如列表,参数的内部赋值会改变外部变量的值

       内部参数与外部变量指向同一个列表,所以会被修改

       若不想改变外部列表,可以传进一个副本

    >>> def change(n):

    ...    n[0]='tanggao'

    ...

    >>> names=['hello','world']

    >>> change(names)

    >>> names

    ['tanggao', 'world']

    >>>  #采用普通方法进行模拟 

    ...

    >>> names=['hello','world']

    >>> n=names

    >>> n[0]='tanggao'

    >>> names

    ['tanggao', 'world']

     

     

    完整示例——存储名字,并能用名字、中间名或姓来查找联系人

       若名字为'MagusLie Hetland'存储格式类似

       data = {

               'first':{ 'Magus': 'Magus Lie Hetland'},

               'middle':{'Lie': 'Magus Lie Hetland'},

               'last':{'Hetland': 'Magus Lie Hetland'}

           }

       注意insert(index,value)函数,在列表的索引位置插入值

    Python代码  

    1.  >>> def init(data):  #data作为存储表,初始化  

    2.      data['first'] = {}  

    3.      data['middle'] = {}  

    4.      data['last'] = {}  

    5.    

    6.  >>> def store(data, full_name): #存储,将全名存储到表中  

    7.      names = full_name.split()  #将名字按空格(即first,middle,last)分开,返回列表,如'Ma Li He'返回['Ma', 'Li', 'He']  

    8.      if len(names) == 2: names.insert(1, '')#若无中间名,则插入空来表示中间名['Mr', 'Zha']返回['Mr', '', 'Zha']  

    9.      labels = 'first''middle''last'  #元组  

    10.     for label, name in zip(labels, names):  #元组与序列间也可使用zip  

    11.         people = lookup(data, label, name)  

    12.         if people:  

    13.             people.append(full_name)  

    14.         else:  

    15.             data[label][name] = [full_name] #当键不存在时,自动添加键值对,  

    16.                                                                          #但如果输出不存在键对应值,则报错  

    17.   

    18. >>> def lookup(data, label, name): #查找,根据label查找是name的中间人  

    19.     return data[label].get(name)  

    20.   

    21.               

    22. >>> MyNames = {}  

    23. >>> init(MyNames)  

    24. >>> store(MyNames, 'Magnus Lie Hetland')  

    25. >>> lookup(MyNames, 'middle''Lie')  

    26. ['Magnus Lie Hetland']  

    27. >>> store(MyNames, 'Robin Hood')  

    28. >>> store(MyNames, 'Robin Locksley')  

    29. >>> lookup(MyNames, 'first''Robin')  

    30. ['Robin Hood''Robin Locksley']  

    31. >>> store(MyNames, 'Mr. Gumby')  

    32. >>> lookup(MyNames, 'middle''')  

    33. ['Robin Hood''Robin Locksley''Mr. Gumby']  

     

       例2. 不可变的数字和可改变的参数

    Python代码  

    1.  >>> def inc(x): return x + 1  

    2.    

    3.  >>> foo = 10  

    4.  >>> inc(foo)  

    5.  11  

    6.  >>> foo #外部变量未发生变化  

    7.  10  

    8.  >>> foo = inc(foo) #将foo重新赋值  

    9.  >>> foo  

    10. 11  

     

       使用列表外部变量foo改变了

    Python代码  

    1.  >>> def inc(x): x[0] = x[0] + 1  

    2.    

    3.  >>> foo = [10]  

    4.  >>> inc(foo)  

    5.  >>> foo  

    6.  [11]  

     

    3. 关键字参数和默认值

       位置:是指根据参数的对应位置传参,如def a(a,b,c):,调用a(1,2,3),1传给a,2传给b,3传给c,这样参数位置容易记混。

       关键字参数,适用于大规模程序,清晰

    Python代码  

    1.  >>> def hello(name, greeting):  

    2.      print '%s, %s!' %(greeting, name)  

    3.    

    4.        

    5.  >>> hello('sun''Hello')  #位置参数  

    6.  Hello, sun!  

    7.  >>> hello(name = 'Sun', greeting = 'Hello')  #关键字参数  

    8.  Hello, Sun!  

    9.  >>> hello(greeting = 'Hello', name = 'Sun'#关键字参数,不必关心位置  

    10. Hello, Sun!  

     

       默认值

    Python代码  

    1.  >>> def hello(name = 'world', greeting = 'Hello'):  

    2.      print '%s, %s!' %(greeting, name)  

    3.    

    4.        

    5.  >>> hello()  

    6.  Hello, world!  

    7.  >>> hello('Sun')  

    8.  Hello, Sun!  

    9.  >>> hello(greeting = 'Hi')  

    10. Hi, world!  

     

       位置参数与关键字参数混用,将位置参数放在前面。尽量避免这么用,容易引起混乱。

    Python代码  

    1.  >>> def hello(name, greeting = 'Hello', punc = '!'):  

    2.      print '%s, %s%s' %(greeting, name, punc)  

    3.    

    4.        

    5.  >>> hello('Sun')  

    6.  Hello, Sun!  

    7.  >>> hello('Sun''Hi')  

    8.  Hi, Sun!  

    9.  >>> hello('Sun', punc = '..')  

    10. Hello, Sun..  

    11. >>> hello()   #因为name是必须要有,若有默认值,则可没有  

    12.   

    13. Traceback (most recent call last):  

    14.   File "<pyshell#385>", line 1, in <module>  

    15.     hello()  

    16. TypeError: hello() takes at least 1 argument (0 given)  

    17. >>>   

     

    4. 收集参数——在定义时使用*或**,用来收集参数,允许使用不定数量的参数

       *:收集其余的位置参数并作为元组 返回

    Python代码  

    1.  >>> def print_params2(title, *params):  

    2.      print title  

    3.      print params  

    4.    

    5.        

    6.  >>> print_params2('Param:', 1, 2, 3)  

    7.  Param:  

    8.  (1, 2, 3)  #以元组形式返回  

    9.  >>> print_params2('Param:'#不提供收集元素时,返回空元组  

    10. Param:  

    11. ()  

    12. >>> print_params2('Param:', 1)   

    13. Param:  

    14. (1,) #只有一个元素时,仍为元组  

     

       **:收集其余的关键字参数并作为字典 返回,可与其他混用

    Python代码  

    1.  >>> def print_params3(x, y, z = 3, *pospar, **keypar):  

    2.      print x, y, z  

    3.      print pospar  

    4.      print keypar  

    5.    

    6.        

    7.  >>> print_params3(1,2,3,4,5,6,7, fool = 1, bar = 2)  

    8.  1 2 3  

    9.  (4, 5, 6, 7)  

    10. {'fool': 1, 'bar': 2}  

    11. >>> print_params3(1,2)  

    12. 1 2 3  

    13. ()  

    14. {}  

     

    5. 收集参数的翻转过程——在调用时使用*或**,将参数分配到定义的参数中,用于字典或列表分割时

       用于列表

    Python代码  

    1.  >>> def add(x,y): return x + y  

    2.    

    3.  >>> params = (1,2)  

    4.  >>> add(*params)  

    5.  3  

     

       用于字典

    Python代码  

    1.  >>> def hello(name, greeting):  

    2.      print '%s, %s!' %(greeting, name)  

    3.    

    4.        

    5.  >>> params = {'name''Sir Robin''greeting''Welcome'}  

    6.  >>> hello(**params)  

    7.  Welcome, Sir Robin!  

    8.    

    9.     

     

       参数使用实例

    Python代码  

    1.  #模拟步长大于0的range()  

    2.  >>> interval(10)  

    3.  start = 0 stop = 10 step =  1  

    4.  [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]  

    5.  >>> def interval(start, stop=None, step=1):  

    6.      'Imitates range() for step > 0'  

    7.      if stop is None: #若未给stop指定值  

    8.          start, stop = 0, start #多个赋值,0赋值给start,start的值赋值给stop  

    9.      result = []  

    10.     i = start  

    11.     while i < stop:  

    12.         result.append(i)  

    13.         i += step  

    14.     return result  

    15.   

    16. #  

    17. >>> def story(**kwds):  

    18.     return '%(job)s called %(name)s.' %kwds  

    19.   

    20. >>> def power(x, y ,*others):  

    21.     if others:  

    22.         print 'Received redundant parameters:',others  

    23.     return pow(x,y)  

    24.   

    25. #使用  

    26. >>> params = {'job':'language','name':'python'}  

    27. >>> print story(**params) #调用时分割字典,定义中收集  

    28. language called python.  

    29. >>> del params['job']  

    30. >>> print story(job='test', **params)  

    31.   

    32. >>> power(2,3,'test')  

    33. Received redundant parameters: test  

    34.   

    35. >>> params = (5,) * 2 #即(5,5)  

    36. >>> power(*params) #先分割,在赋给x,y  

    37. 3125  

     

    6.作用域

       x = 1, 将名字x引用到值1上,类似字典

       内建函数vars()返回这个字典

    Python代码  

    1.  >>> x = 1  

    2.  >>> scope = vars()  

    3.  >>> scope['x']  

    4.  1  

    5.  >>> scope['x'] += 1 #一般情况下,vars()返回的字典不能修改  

    6.  >>> x  

    7.  2  

     

       局部变量,全局变量

       函数内部访问全局变量,慎用!

    Python代码  

    1.  >>> def com(para): print para + external  

    2.    

    3.  >>> external = 'external'  

    4.  >>> com('param ')  

    5.  param external  

     

       若全局变量与局部变量名字相同,会被局部变量覆盖,可使用global()类似vars(),获得全局变量的字典

    Python代码  

    1.  >>> def com(para): print para + globals()['para']  

    2.    

    3.  >>> para = 'berry'  

    4.  >>> com('test ')  

    5.  test berry  

     

       重绑定全局变量,将变量引用到其他新值——函数内部声明全局变量

    Python代码  

    1.  >>> x = 1  

    2.  >>> def change_global():  

    3.      global x  

    4.      x = x + 1  

    5.    

    6.        

    7.  >>> change_global()  

    8.  >>> x  

    9.  2  

     

       嵌套作用域——函数中定义函数,例如闭包

       外部作用域中的变量一般不能被改变,但是用闭包,每次调用外层函数,内部函数都会被重新绑定,也即外部作用域factor每次都有一个新值

    Python代码  

    1.  >>> def multiplier(factor):  

    2.      def multiplyByFactor(number):  

    3.          return number * factor  

    4.      return multiplyByFactor  #返回一个函数,这时并未调用  

    5.    

    6.  >>> double = multiplier(2)  #double是一个函数  

    7.  >>> double   #double是一个函数  

    8.  <function multiplyByFactor at 0x0214C6F0>  

    9.  >>> double(5)  #调用multiplyByFactor(number)  

    10. 10  

    11. >>> multiplier(2)(5) #效果同上  

    12. 10  

     

       7. 递归——每调用一个函数,都会创建一个新的命名空间,意味着当函数调用自身时,实际上调用的是两个不同的函数

        阶乘

    Python代码  

    1.  >>> def factorial(n):  

    2.      if n == 1:  

    3.          return 1  

    4.      else:  

    5.          return n * factorial(n-1)  

    6.    

    7.  >>> factorial(5)  

    8.  120  

        幂

    Python代码  

    1.  >>> def power(x, n):  

    2.      if n == 0:  

    3.          return 1  

    4.      else:  

    5.          return x * power(x, n - 1)  

    6.    

    7.        

    8.  >>> power(2,3)  

    9.  8  

     

       递归实例——二元搜索

       前提:排好序

       若上下限相同,则那就是数字所在位置,返回;

       否则,找到两者的中间,查找数字是在左侧还是右侧,继续查找数字所在的那半部分。

    Python代码  

    1.  >>> def search(sequence, number, lower = 0, upper = None):  

    2.      if upper is None: upper = len(sequence) - 1  

    3.      if lower == upper:  

    4.          assert number == sequence[upper]  

    5.          return upper  

    6.      else:  

    7.          middle = (lower + upper) // 2  

    8.          if number > sequence[middle]:  

    9.              return search(sequence, number, middle + 1, upper)  

    10.         else:  

    11.             return search(sequence, number, lower, middle)  

    12.   

    13.           

    14. >>> seq = [34, 67, 8, 123, 4, 100, 95]  

    15. >>> seq.sort()  

    16. >>> seq  

    17. [4, 8, 34, 67, 95, 100, 123]  

    18. >>> search(seq, 34)  

    19. 2  

     

    总结:

    元组输出格式化,直接使用键,而不需要加引号

    Python代码  

    1.  >>> d = {'a':1, 'b':2}  

    2.  >>> print '%(a)s corresponds to %(b)s.' %d #注意a有括号,无引号  

    3.  1 corresponds to 2.  

     

    转载请注明原文地址: https://ju.6miu.com/read-1299639.html
    最新回复(0)