【循序渐进学Python】6.Python中的函数

简介:

1. 创建函数

一个函数代表一个行为并且返回一个结果(包括None),在Python中使用def关键字来定义一个函数,如下:

def hello(name):
    print 'hello,' + name + '!'

 接下来调用函数,并查看其返回值:

# output:
# hello,gy!
# None
print hello('gy')

可以看到hello函数首先打印了:Hello,gy!,然后我们又将其返回值也打印出来,在这里因为没有返回具体的值,所以返回了None

 

下面我们可以定义一个用于计算斐波那契数列的函数,接收计算的位数(参数),返回计算的结果(返回值),如下:

复制代码
1 def fibs(num):
2     result = [0,1]
3     for i in range(num - 2):
4         result.append(result[-2] + result[-1])
5     return result
6 
7 # output: [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
8 print fibs(10)
复制代码

 

2. 文档字符串

文档字符串指的是在函数开头写下该函数的说明字符串,该字符串会作为函数的一部分进行存储。可以通过调用__doc__属性来查看:

复制代码
1 def fibs(num):
2     "根据指位数来计算斐波那契数列"
3     result = [0,1]
4     for i in range(num - 2):
5         result.append(result[-2] + result[-1])
6     return result
7 
8 # 输出:根据指位数来计算斐波那契数列
9 print fibs.__doc__
复制代码

 

3. 参数

函数使用参数来传递信息,而参数类型又基本分为两大类型:可变类型参考和不可变类型参数。

 

3.1 不可变类型参数

不可变类型(字符串、数字和元组等)是不可变的,即无法修改,只能使用新的值来覆盖。使用不可变类型作为函数的参数时:在函数内为参数赋值不会改变其外部变量的值,如下:

复制代码
 1 # 字符串是不可变的
 2 def try_to_change(n):
 3     n = 'Gumby'
 4 
 5 name = 'Sunshine'
 6 
 7 # 尝试改变参数的值
 8 try_to_change(name)
 9 
10 # output: Sunshine(函数内部的改变对其没有影响)
11 print name
复制代码

 

3.2 可变类型参数

可变类型参数(列表等)指的是:使用可变的数据结构来作为函数的参数使用。在函数内部修改可变类型参数的值时,会同时改变其外部变量的值(因为它们引用的其实是同一个对象),如下所示:

复制代码
 1 # 列表是可变的
 2 def try_to_change2(n):
 3     n[0] = 'Sunshine'
 4 
 5 person = ['Gumby','Bob']
 6 # 尝试改变参数的值
 7 try_to_change2(person)
 8 
 9 # output: ['Sunshine', 'Bob']
10 # 函数内部的改变会作用于外部的变量
11 print person
复制代码

 

如果想避免上面的情况可以对需要作为可变类型的参数的对象复制一个副本,这里是列表可以通过对其进行切片来返回一个新的副本,如下:

复制代码
 1 # 将可变的数据结构(列表)用作参数
 2 def try_to_change2(n):
 3     n[0] = 'Sunshine'
 4 
 5 person = ['Gumby','Bob']
 6 n = person[:] # 通过切片返回新的副本
 7 try_to_change2(n)
 8 print person # ['Gumby', 'Bob']
 9 print n # ['Sunshine', 'Bob']
10 print n is person # False
复制代码

 

3.3 关键字参数和默认值

在我们之前使用参数的形式是:位置参数,即调用该函数给其传值时,是根据输入的值的先后顺序来给参数一一赋值 的。不过有时候如果我们需要定义的函数有大量的参数时,传值时只是于依赖于顺序的话是比较容易出错的。同时如果部分参数在不多数情况下值都是一样的,每次 调用都需要重新赋值也比较麻烦。针对于这种情况Python为我们提供了两个语法糖:即关键字参数默认值。(PS:C#4.0新增的两个特性:具名参数和可选参数,和Python的这两个语法糖很类似,感兴趣的同学可以参考这里:《Effective C#》读书笔记——条目10:使用可选参数减少方法重载的数量<C#语言习惯>)。

使用关键字参数不需要对函数进行任何修改,只需要在调用函数时显示为参数赋值即可(不依赖特定顺序),如下:

1 def hello(gretting,name):
2     print "%s,%s!" % (gretting,name)
3 
4 # output: hello,world!
5 hello(name='world',gretting='hello')

 

可以看到虽然调用时代码变多了,但是每个参数的含义一目了然。不过有时候我们的函数有些参数在大部分情况下使用同样的值,有时候也需要改变,这时候使用默认值,可以很好的解决这种问题,如下:

复制代码
1 def hello(gretting = 'hello',name='world'):
2     print "%s,%s!" % (gretting,name)
3 
4 hello() # hello,world!
5 hello(name = 'Sunshine') # hello,Sunshine!
6 hello('Greetings') # Greetings,world!
复制代码

 可以看到,如果没有给任何值的话,函数自动使用默认值,也可以通过关键字参数指定部分值,其他的依然使用默认参数,这为我们的方法调用提供了很大的灵活性。

 

3.4 使用任意参数列表

前面介绍的参数的个数基本都是固定的,有时候可以接收任意多的参数也是很有必要的,这时候可以使用Python为我们提供的语法糖(*号)来实现:

复制代码
 1 def print_params(number,*params):
 2     print number
 3     print params
 4 
 5 # output: 
 6 # 6
 7 # (1, 2, 3, 4, 5, 6)
 8 print_params(6,1,2,3,4,5,6)
 9 
10 # output:
11 # 0
12 # ()
13 print_params(0)
复制代码

 

我们可以看到参数前的*号将所有的值放置到一个元组中(可以理解为将其他的参数收集起来)。如果没有为*号后的参数赋值则其值为一个空的元组。不过使用一个*号这样的语法不能处理关键字参数,如下:

1 def print_params(*params):
2     print params
3 
4 # TypeError: print_params() got an unexpected keyword argument 'params'
5 print_params(params = (1,2,3))

 

解决的办法很简单,使用**来修饰参数即可,如下所示:

复制代码
1 # -- coding: utf-8 --
2 def print_params(**params):
3     print params
4     print type(params)
5 
6 # output: {'params': (1, 2, 3)}
7 # output: <type 'dict'>
8 print_params(params = (1,2,3))
复制代码

 可以看到使用**修饰的参数本质上其实是一个字典类型。可以通过这个字典来收集参数。

 

3.5 解包参数列表

除了通过才定义函数的参数(形参)前添加*或者**来收集参数,我们还可以在调用函数时在实参前调解这两个操作符,它们表示其对应的逆过程。如下所示:

复制代码
1 def add(x,y):
2     print x + y
3 
4 params = (1,2)
5 
6 # output: 3
7 add(*params)
复制代码

 

通过使用*操作符我们将params参数分割了add函数所需的两个参数,同样我们也可以使用**操作符来分割字典对象:

复制代码
1 def hello(greeting,name):
2     print '%s,%s' %(greeting,name)
3 
4 params = {'greeting':'hello','name':'world'}
5 
6 # output: hello,world
7 # 这里使用*操作符也是可以的
8 hello(**params)
复制代码

 

参考资料&进一步阅读

Python基础教程(第二版)

Python入门教程——深入函数定义

分类:  Python
本文转自gyzhao博客园博客,原文链接:http://www.cnblogs.com/IPrograming/p/Python_function.html ,如需转载请自行联系原作者
相关文章
|
2月前
|
Python
【python从入门到精通】-- 第五战:函数大总结
【python从入门到精通】-- 第五战:函数大总结
81 0
|
23天前
|
搜索推荐 Python
利用Python内置函数实现的冒泡排序算法
在上述代码中,`bubble_sort` 函数接受一个列表 `arr` 作为输入。通过两层循环,外层循环控制排序的轮数,内层循环用于比较相邻的元素并进行交换。如果前一个元素大于后一个元素,就将它们交换位置。
125 67
|
17天前
|
Python
Python中的函数是**一种命名的代码块,用于执行特定任务或计算
Python中的函数是**一种命名的代码块,用于执行特定任务或计算
42 18
|
8天前
|
数据可视化 DataX Python
Seaborn 教程-绘图函数
Seaborn 教程-绘图函数
40 8
|
18天前
|
Python
Python中的函数
Python中的函数
31 8
|
24天前
|
监控 测试技术 数据库
Python中的装饰器:解锁函数增强的魔法####
本文深入探讨了Python语言中一个既强大又灵活的特性——装饰器(Decorator),它以一种优雅的方式实现了函数功能的扩展与增强。不同于传统的代码复用机制,装饰器通过高阶函数的形式,为开发者提供了在不修改原函数源代码的前提下,动态添加新功能的能力。我们将从装饰器的基本概念入手,逐步解析其工作原理,并通过一系列实例展示如何利用装饰器进行日志记录、性能测试、事务处理等常见任务,最终揭示装饰器在提升代码可读性、维护性和功能性方面的独特价值。 ####
|
1月前
|
Python
Python中的`range`函数与负增长
在Python中,`range`函数用于生成整数序列,支持正向和负向增长。本文详细介绍了如何使用`range`生成负增长的整数序列,并提供了多个实际应用示例,如反向遍历列表、生成倒计时和计算递减等差数列的和。通过这些示例,读者可以更好地掌握`range`函数的使用方法。
47 5
|
2月前
|
Python
Python之函数详解
【10月更文挑战第12天】
Python之函数详解
|
2月前
|
存储 数据安全/隐私保护 索引
|
1月前
|
测试技术 数据安全/隐私保护 Python
探索Python中的装饰器:简化和增强你的函数
【10月更文挑战第24天】在Python编程的海洋中,装饰器是那把可以令你的代码更简洁、更强大的魔法棒。它们不仅能够扩展函数的功能,还能保持代码的整洁性。本文将带你深入了解装饰器的概念、实现方式以及如何通过它们来提升你的代码质量。让我们一起揭开装饰器的神秘面纱,学习如何用它们来打造更加优雅和高效的代码。