callable函数

判断函数是否可以被调用
该函数在python3上并不被支持!!!!!

In [1]:
import math
In [2]:
x = 1
In [3]:
y = math.sqrt     #关联到函数
In [4]:
callable(x)
Out[4]:
False
In [5]:
callable(y)
Out[5]:
True

def语句、return语句

创建函数、返回值

In [6]:
def hello(name):
    return 'Hello, ' + name + '!'
In [7]:
print hello("Zk")
Hello, Zk!

文档字符串

在函数、模块、类开头写下相关文档,即直接写一个字符串~
这个字符串会被储存起来,可以供给查看

In [8]:
def square(x):
    'Calculates the square of the number x'      #看!这就是文档字符串啦
    return x*x
In [9]:
print square(2)
4

In [10]:
#可以通过__doc__属性查看
square.__doc__
Out[10]:
'Calculates the square of the number x'
In [11]:
#也可以通过内建函数help查看
help(square)
Help on function square in module __main__:

square(x)
    Calculates the square of the number x


  • 函数也可以没有return语句
    或者有return语句但不带值
    其实函数默认返回的是空值None
In [12]:
def test():
    print 'Hello!'
In [13]:
x = test()
Hello!

In [15]:
print x
None

参数

  • 在函数内改变一般的参数,原变量不变
  • 列表跟C的数组类似,值被改变后,原变量会被改变
  • 【小技巧】如果要修改一般参数的的值,可以把这个变量放进列表里,建立一个单个元素的列表

位置参数

跟C语言一样,每个实参和形参的位置必须一一对应

关键词参数

通过“形参=实参”的形式传递值

In [3]:
def hello(name, greeting):
    print '%s, %s!' % (greeting, name)
In [4]:
hello(greeting='Hello', name='world')
Hello, world!

In [8]:
#参数还可以提供默认值
def hello(name = 'world', greeting = 'Hello'):
    print '%s, %s!' % (greeting, name)
In [9]:
hello()
Hello, world!

In [10]:
hello(greeting = 'Hey')
Hey, world!

位置参数和关键词参数可以混用,但是位置参数必须写在关键词参数前面
关键词参数一般也要有默认值

收集参数

可以收集任意多个参数
*表示收集任意多个位置参数(作为元组)
**表示收集任意多个关键词参数(作为字典)

In [12]:
def print_params(x, y, z = 3, *pospar, **keypar):    #位置参数、关键词参数、两种收集参数混用
    print 'x, y, z = ', x, y, z
    print 'pospar = ', pospar
    print 'keypar = ', keypar
In [13]:
print_params(1, 2, 3, 5, 6, 7, foo = 1, bar = 2)
#先收集位置参数、位置参数
#*收集其余位置参数
#**收集其余关键词参数
x, y, z =  1 2 3
pospar =  (5, 6, 7)
keypar =  {'foo': 1, 'bar': 2}

参数收集的逆过程

用元组为函数的位置参数提供实参
用字典为函数的关键词参数提供实参

In [1]:
def add(x, y):
    return x + y
In [2]:
params = 1, 2
In [3]:
add(*params)      #加上星号表示把元组元素取出来依次作为位置参数的实参
Out[3]:
3
In [4]:
def hello(name, greeting):
    print '%s, %s!' % (greeting, name)
In [5]:
params = {'name' : 'world', 'greeting' : 'Hello'}
In [6]:
hello(**params)     #加上两个星号表示把字典的“键-值”取出来分别作为“关键词-值”来作关键词参数的实参
Hello, world!

判断函数是否接收了多余的参数

In [8]:
def power(x, y, *others):
    if others:         #判断others是否存在
        print 'Received redundant parameters:', others
    return pow(x, y)
In [9]:
power(3, 3, 'Hello world!')
Received redundant parameters: ('Hello world!',)

Out[9]:
27

判断函数是否缺少某个参数

In [12]:
def hello(name, greeting = None):
    if greeting == None:       #把默认值设为空,是否接收这个参数,判断其值是否为空即可
        print "lack for the parameter: 'greeting'"
    else:
        print "%s, %s!" % (greeting, name)
In [13]:
hello('world', 'Hello')
Hello, world!

In [14]:
hello('world')
lack for the parameter: 'greeting'

作用域

  • 变量的值是以“变量名-值”对的形式保存在一个不可见的“键-值”对的字典中
    vars函数可以返回这个字典,这个字典就是作用域(命名空间)
    globals函数返回全局变量的字典
    locals函数返回局部变量的字典
In [2]:
x = 1
In [3]:
scope = vars()
In [4]:
scope
Out[4]:
{'In': ['', u'###\u4f5c\u7528\u57df', u'x = 1', u'scope = vars()', u'scope'],
 'Out': {},
 '_': '',
 '__': '',
 '___': '',
 '__builtin__': <module '__builtin__' (built-in)>,
 '__builtins__': <module '__builtin__' (built-in)>,
 '__doc__': 'Automatically created module for IPython interactive environment',
 '__name__': '__main__',
 '_dh': [u'/home/zk/\u684c\u9762'],
 '_i': u'scope = vars()',
 '_i1': u'###\u4f5c\u7528\u57df',
 '_i2': u'x = 1',
 '_i3': u'scope = vars()',
 '_i4': u'scope',
 '_ih': ['', u'###\u4f5c\u7528\u57df', u'x = 1', u'scope = vars()', u'scope'],
 '_ii': u'x = 1',
 '_iii': u'###\u4f5c\u7528\u57df',
 '_oh': {},
 '_sh': <module 'IPython.core.shadowns' from '/usr/lib/python2.7/dist-packages/IPython/core/shadowns.pyc'>,
 'exit': <IPython.core.autocall.ZMQExitAutocall at 0x7f18307c4a10>,
 'get_ipython': <bound method ZMQInteractiveShell.get_ipython of <IPython.kernel.zmq.zmqshell.ZMQInteractiveShell object at 0x7f18307b2a50>>,
 'quit': <IPython.core.autocall.ZMQExitAutocall at 0x7f18307c4a10>,
 'scope': {...},
 'x': 1}
In [5]:
scope['x']
Out[5]:
1
In [6]:
#一般来说,vars返回的字典不能修改,其结果是未定义的

除了全局变量有作用域外,每个函数调用都会创建一个新的作用域

In [13]:
#函数内取用全局变量,借助globals函数即可
globals()['x']
Out[13]:
1
In [14]:
#在函数内部声明全局变量
def hhhh():
    global x          #用global声明变量
    x = 2
In [15]:
hhhh()
In [16]:
x
Out[16]:
2

python的函数是可以嵌套定义的
函数的嵌套定义是很少用的,一般用来“用一个函数创建另一个函数”
这里把子函数存储子封闭作用域,该行为称为闭包(closure)

In [17]:
def multiplier(factor):
    def multiplyByFactor(number):      #嵌套的子函数
        return number * factor
    return multiplyByFactor        #这里美柚给出实参number,意味着返回的是一个函数名
In [18]:
double = multiplier(2)
#这里创建了一个函数double相当于
#def double(number)
#    return number * 2
#multiplier函数接受了实参factor=2,代入给multiplyByFactor函数,得到一个double函数
In [19]:
double(5)      #return 5 * 2
Out[19]:
10
In [20]:
#其实这也相当于
multiplier(2)(5)
Out[20]:
10

递归实例

递归的效率并不高,但是易懂

In [22]:
#阶乘
def factorial(n):
    if n == 1:
        return 1
    else:
        return n * factorial(n - 1)
In [23]:
factorial(3)
Out[23]:
6
In [24]:
#幂运算
def power(x, n):
    if n == 0:
        return 1
    else:
        return n * power(x, n - 1)
In [3]:
#二分法查找
def search(sequence, number, lower, upper):
    'squence为一个序列,number为目标数字,lower和upper分别表示下限、上限索引号'
    sequence.sort()       #二分法查找需要序列排序
    if lower == uppeer:
        assert number == sequence[upper]    #断言该数字存在于序列之中
        return upper
    else:
        middle = (lower + upper) // 2
        if number > sequence[middle]:
            return search(sequence, number, middle + 1, upper)
        else:
            return search(sequence, number, lower, middle)

函数式编程

map, filter函数可以通过列表推导式取代
reduce函数不常用

In [4]:
#lambda表达式,可以创建短小的函数(lambda在数学中表示匿名函数)
#reduce函数,可以将一个序列的前两个数字作为参数传递给指定函数,将返回值和第三个数字再作为参数,以此类推
In [5]:
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
In [6]:
reduce( lambda x, y: x +y , numbers )
#lambda x, y: x + y表示创建一个函数,接受两个参数x和y,返回他们的和
#numbers为若干要作为参数的的一个序列
#reduce第一个参数为函数,第二个函数为序列,返回处理完整个序列后的结果
Out[6]:
55
In []: