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

来源:互联网 发布:如何将iphone投影到mac 编辑:程序博客网 时间:2024/06/01 08:51

第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)>>> foo11
  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 1SyntaxError: 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()>>> x2
  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