学了 Python 中的数据类型, 语句, 接下来就来说一下 Python 中的函数, 函数是结构化编程的核心. 我们使用函数可以增加程序的可读性. 自定义函数时使用关键字 def 函数由多条语句组成. 在定义函数的时候我们可以使用如下的方式给函数定义一个解释文档.
- def square(x):
- 'This is comment of this method !'
- return x * x
- # 获取方法注释信息
- square.__doc__
上面定义的函数我们就可以通过函数名.__doc__的方式获取方法的文档字符串.
另外, 所有的函数都有返回值, 如果你没有显示的告诉它返回什么, 则返回 None
一个函数怎么能少得了参数的部分呢, 一不留神可能就会搞错, 这里大概说一下, 若传递的参数为不可变的参数, 则不会修改参数的值, 像是 数字, 字符串, 元组, 但若是引用值的话, 就可能会将原来的值改变. 比方说 列表, 字典. 可以采用切片的方式避免对传入列表的修改, 如: change(names[:]) 这样的话我们传入的是 names 列表的一个复制版本, 而对 names 本身没有影响.
关键字参数和默认值, 举例说明
- def hello(greeting = 'Hello',name = 'world'):
- print('{},{}!'.format(greeting,name))
- hello()
- Hello,world!
- hello(name = 'YJK923')
- Hello,YJK923!
可变参数: 允许用户提供任意数量的参数. 使用 * 号将提供的所有参数收集到一个元组中. 这种用法在赋值的时候也遇到过. 举例
- def print_params(*param):
- print(param)
- print_param('Testing')
- Testing
- print_param(1,2,3)
- (1,2,3)
星号的参数最好放在最后, 不然在调用方法的时候需要指出星号参数后面的参数的值是多少.
还有一种使用两个星号, 是用于收集带有关键字参数的方法, 得到的值是一个字典而不是一个元组.
- def print_dict(**params):
- print(params)
- print_dict(x = 1,y = 2,z = 3)
- {'z':'3','x':'1','y':'2'}
上面两个都是在定义函数的时候使用了 * , 那我们在调用的函数的时候也可以使用星号, 这也就是分配参数, 像这样
- def add(x,y):
- return x + y
- param = (1,2) # 定义一个元组, 用做参数
- add(*param) # 使用 * 来分配参数
- 3 # 结果为 3 , 这就是分配参数之后的结果
Python 中的作用域的概念类似于 Java, 所以理解起来没有问题, 但是 Python 好像都不是老老实实的, 我们知道在方法里的变量是局部变量, 我们在方法里使用时, 全局变量不受影响, 但是 Python 社区的小伙伴就是想改变全局变量的值, 该怎么操作呢? 发明了一个关键字 global 用于指定某个方法里的值为全局变量.
- x = 1
- def change(x):
- global x # 此时的 x 就是指向全局变量 x
- x = x + 1
- change(x)
此时 x = 2
递归 : 函数之间的相互调用是很正常的, 存在这么一种情况, 那就是自己调用自己, 这就是递归调用.
举例说明
- # 计算数字 n 的阶乘 n ! = n * (n-1) * (n -2) * ... * 1
- # 分析: 1 的阶乘为 1, 大于 1 的数 n 的阶乘等于 n-1 的阶乘 * n
- def factorial(n):
- if n == 1 :
- return 1
- else :
- return n * factorial(n-1)
递归函数通常包含两部分内容, 一是基线条件, 满足条件函数将直接放回一个值, 像上面的 n = 1 return 1 二是包含一个或多个调用, 这些调用旨在解决问题的一部门. 这里的关键是, 通过将问题分解为较小的部门, 可避免递归没完没了, 因为问题终将被分解成基线条件可以解决的最小问题.(抽象啊, 多看看, 体会体会吧!)
- # 计算某一个数的幂
- # 分析: power(x,n) 表示计算 x 的 n 次幂. 也就是将数 x 自乘 n-1 次.
- # 对于任意数来说, n 为 0 的时候结果都为 1,n> 0 的时候, power(x,n) = x * power(x,n-1) , 是不是感觉可以用递归做点什么!
- def power(x,n):
- if n == 0 :
- return 1
- else :
- return x * power(x,n-1)
好吧, 上面两个递归运算还没有理解递归的概念, 没关系, 还有一个!
- # 使用 python 递归实现二分法查找
- # 介绍: 在有序的列表中, 所要查找数据和中间数据比较. 依次拆分, 比较中间的数.
- def search(list,number,lower,upper):
- '使用二分法查找指定数据的索引, list 是排好序的列表, number 是查找的数据 lower,upper 指定查找的起始位置'
- if lower == upper:
- assert number == list[upper]
- return upper
- else :
- middle = (lower + upper) // 2 # // 表示不留小数除
- if number> list[middle] :
- return search(list,number,middle+1,upper)
- else :
- return search(list,number,lower,middle)
说了以上这么多, 对函数式编程的理解也是马马虎虎, 用函数来编写程序 ? 可能看到了 Python 中提供的这几个函数, 能对函数式编程加深一下感觉. map filter reduce 给几个例子看一下
- list(map(str,range(5))) # 与 [srt(i) for i in range(5)] 等价
- ['0','1','2','3','4']
- # 可以使用 filter 根据布尔函数的返回值对元素进行过滤
- # 首先你得有一个可以返回布尔值的函数
- def func(x):
- return x.isalnum() # isalnum 方法检测字符串是否由字母或数字组成
- seq = ['foo','x41','***','?!']
- list(filter(func,seq))
- ['foo','x41']
- # 同样的实现可以这么来
- [x for x in seq if x.isalnum()]
- # 还有一种叫 lambda 表达式的玩意, 是这样写的
- filter(lambda x : x.isalnum(),seq)
- # lambda 表达式是一个匿名的函数, 简单的理解, 冒号前面是参数, 冒号后面是方法体 (返回值)
- lambda x , y : x + y # 这就是表示有两个参数返回值是参数和的匿名函数呗!
- # 使用指定的函数将序列的前两个元素和二为一, 再将结构与第三个元素和二为一, 最终处理完序列得到一个结果.
- numbers = [72,42,7,9,23,67,97,245]
- from functools import reduce
- reduce(lambda x,y:x+y,numbers)
- # 当然, 就这个案例来说, 倒不如使用内置函数 sum 求和.
好吧, 以上就是 Python 中函数相关的问题, 至此, 我们已经学习了 Python 的数据类型以及数据类型的常用操作, 后便是语句, 语句中牵扯到一些循环和条件判断语句的使用, 而函数可以看成是对语句的简单抽象与封装, 而真正的面向对象的思想还在下一节类的相关概念中.
来源: https://www.cnblogs.com/YJK923/p/9534405.html