Python学习笔记【六】——《python基础教程》:: 抽象

第6章 抽象

6.3. 创建函数

  1. 判断函数是否可调用。
    Python3.0前,使用内建函数callable(func)
    Python3.0后,使用表达式hasattr(func, __call__)
  2. 定义函数,使用def,格式如下:

    def func(args):
        dosomething
        return result 

    示例如下:

    >>> def hello(name):
    ...     return 'hello', name+'!'
    ... 
    >>> print hello('world')
    hello world!

6.3.1. 记录函数

文档字符串:写在函数开头的字符串,作为函数的一部分进行存储。

>>> def test_doc_string():
...     'Test doc string'
...     return
... 

可通过__doc__方法访问文档字符串。

>>> test_doc_string.__doc__
'Test doc string'

另外,当调用内建help函数是,也可已得到响应函数的文档字符串信息。

>>> help(test_doc_string)
Help on function test_doc_string in module __main__:

test_doc_string()
    Test doc string

6.4. 参数魔法

6.4.2. 我能改变参数吗

  1. 当参数为字符串、数字和元组时,函数内为参数赋予新值不会改变外部任何变量的值。

    >>> def try_to_change(n):
    ...     n = 'new string'
    ... 
    >>> name = 'old string'
    >>> try_to_change(name)
    >>> name
    'old string'

    若想使用函数内对参数的修改,需要将修改后的参数返回。例如:

    >>> def inc(x): return x+1
    ... 
    >>> foo = 10
    >>> foo = inc(foo)
    >>> foo
    11
    
  2. 当参数为可变的数据结构(如列表)时,以下面代码为例:

    >>> names = ['aaa', 'bbb', 'ccc']
    >>> def try_to_change(n):
    ...     n[0] = 'aaa1'
    ... 
    >>> try_to_change(names)
    >>> names
    ['aaa1', 'bbb', 'ccc']
    

    从结果可见,实参发生了变化。在调用函数时,实参的输入相当于将实参赋值给函数内的局部参数,即实参与函数内的局部参数引用了同一个列表。

★Python中,函数只能修改参数对象本身。

6.4.3. 关键字参数和默认值

  1. 关键字参数:函数调用时,使用参数名提供参数。
    位置参数:函数调用时,只提供参数的值。

    
    #假设有函数声明为
    
    function(arg1, arg2, ... argN)
    
    #使用位置参数调用格式为
    
    function(value1, value2, ... valueN)
    
    #使用关键字参数调用格式为
    
    function(arg1=value1, arg2=value2, ... argN=valueN)
  2. 关键字参数作用
    -每个参数含义清晰。参数的顺序可以与声明不同,只要将参数名和参数值进行对应即可。
    -定义函数时,可以给参数提供默认值。

    def function(arg1=default_value1, arg2=default_value2, ... argN=default_valueN):
        function_body

    -可以位置参数和关键字参数混合使用,但是调用函数时,位置参数需要放在关键字参数之前,否则解释去无法识别。

    
    #定义函数并指定各个参数的默认值
    
    >>> def hello(name='world', year=2017, month=1, day=1):
    ...     print "hello, %s! %d-%d-%d" % (name, year, month, day
    ... 
    
    #使用关键字参数调用函数
    
    >>> hello(name='holly', year=1990, month=2, day=30)
    hello, holly! 1990-2-30
    
    #使用关键字参数调用函数可以修改参数的位置
    
    >>> hello(year=1990, month=2, day=30, name='holly')
    hello, holly! 1990-2-30
    
    #使用关键字参数调用函数时,缺省的参数使用默认值
    
    >>> hello(year=1990, month=2, day=30)
    hello, world! 1990-2-30
    
    #位置参数和关键字参数可以混合使用,要求位置参数在关键字参数之前
    
    >>> hello('holly', year=1990, month=2, day=30)
    hello, holly! 1990-2-30
    >>> hello(name='holly', 1990, month=2, day=30)
      File "<stdin>", line 1
    SyntaxError: non-keyword arg after keyword arg
    

6.4.4. 收集参数

定义函数时,参数名前添加”*”,表示收集其余的位置参数,作为元组输入;添加”**”,表示收集其余的关键字参数,作为字典输入。

>>> def test_collect(x, y, z=2, *param1, **param2):
...     print x, y
...     print param1
...     print param2
... 
>>> test_collect(1, 2, 3, 'a', 'b', c=1, d=2)
1 2
('a', 'b')
{'c': 1, 'd': 2}

6.4.5. 反转过程

调用函数时,在元组类型参数前添加”*”,元组的元素依次作为位置参数输入;在字典类型参数前添加”**”,字典的键-值对依次组成关键字参数输入。

#元组输入
>>> def add(x, y):
...     return x+y
... 
>>> numbers=(2,3)
>>> add(*numbers)
5
#字典输入
>>> def test_distribute(name, greeting):
...     print "%s, %s!"%(greeting, name)
... 
>>> test_distribute(**args)
Hello, world!

6.5. 作用域

  1. Python中执行变量赋值操作后,相当于将该变量和值形成键-值对,添加到“不可见”的字典中,这个字典即为命名空间作用域

    这个字典可以通过var()内建函数获取。

    >>>x=1
    >>> vars()['x']
    1
  2. 除全局作用域外,当调用函数时,会创建新的作用域。作用与C语言相同。

  3. 当局部变量与全局变量重名时,从函数内无法直接访问全局变量。有以下两种解决方案:

    -可以通过内建函数globals()[‘parameter’],从函数内访问重名的全局变量。

    >>> parameter='global'
    >>> def test_region(parameter):
    ...     print parameter, globals()['parameter']
    ... 
    >>> test_region('local')
    local global

    -在函数内将变量声明为全局变量后可直接访问。

    >>> def change_global():
    ...     global x
    ...     x += 1
    ... 
    >>> x=1
    >>> change_global()
    >>> x
    2
  4. 嵌套作用域,下例为嵌套作用域的突出应用。

    
    #定义multiplier,用于定义并返回multiplyByFactor函数。返回的函数可以访问它的定义所在的作用域。
    
    >>> def multiplier(factor):
    ...     def multiplyByFactor(number):
    ...         return number*factor
    ...     return multiplyByFactor
    ... 
    
    #每次调用外部函数时,它内部的函数都被重新绑定,factor有一个新值,而内部定义的函数可以访问factor。
    
    >>> double = multiplier(2)
    >>> double(3)
    6
    >>> multiplier(5)(4)
    20

6.6. 递归

有用的递归函数包含以下几部分:

■当函数直接返回值时有基本实例(最小可能性问题);
■递归实例,包括一个或者多个问题最小部分的递归调用。

6.6.1. 两个经典:阶乘和幂

阶乘

>>> def factorial(n):
...     if n == 1:
...         return 1
...     return n * factorial(n-1)
... 
>>> factorial(3)
6
>>> factorial(4)
24
>>> factorial(5)
120

>>> def power(x, n):
...     if n == 0:
...         return 1
...     return x * power(x, n-1)
... 
>>> power(2,3)
8
>>> power(3,2)
9

6.6.2. 另外一个经典:二元查找

>>> def search(sequence, number, lower, upper):
...     if lower == upper:
...         if sequence[lower] == number:
...             return lower
...         else:
...             return 'no match found'
...     else:
...         middle = (lower+upper)//2
...         if sequence[middle] > number:
...             return search(sequence, number, lower, middle-1)
...         else:
...             return search(sequence, number, middle, upper)
... 
>>> sequence = range(1000)
>>> print search(sequence, 298, 0, len(sequence)-1)
298

函数型程序设计

  1. map:将序列中的元素全部传递给一个函数。
  2. filter:基于一个返回布尔值的函数对元素进行过滤。
  3. reduce:将序列前两个元素于给定函数联合使用,并将返回值和第3个元素继续联合使用,直到整个序列都处理完毕。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值