Python-5-Python函数的使用
5-1 函数的特点
函数功能强大,调用方便,灵活高效。
Python声明一个函数,不需要声明函数返回值类型,也不需要说明参数类型,这也符合python一切皆对象的特点。
print('lemon', 'pear', sep='...', end='。。。') //lemon...pear。。。 2 ** 3 //8 2的3次方, power(2, 3) 也是一样
5-2 函数的基本形式
函数格式:
def <函数名> (参数): <函数语句> return <返回值>
需要注意的地方:def 声明一个函数,默认2个空格缩进的语句是函数体,可以没有参数,return后也可以没有返回值,若没有return语句,默认返回的是None.
help('keywords') //查看python的关键字 dir(__builtins__) //查看python内置函数,还可以dir(其它)
例子:
#定义并调用函数 def hello(): print('hello lemon') hello() #调用 ======================= def add(x, y): return x+y add(4, 6) #调用
5-3 函数参数类型
支持类型:
def func_name(param1, *args, param2=0, **kwargs): pass
声明函数时可以不定义任何形式的参数。如果需要定义形参时,型参类型有: 必须参数、可变参数、默认值参数、可变关键字参数 这四种。一般有以下常见形参:
param1 必须参数 定义了多少个参数就必须传多少个参数 *args 可变参数 可以传递任意个数 param2 默认值参数 给参数赋默认值 **kwargs 可变关键字参数 可以传递任意个关键字参数
这四种参数可以部分或一起使用,若一起使用的话次序最好是 必须参数、可变参数、默认参数、关键字可变参数。
5-4 必须参数
声明一个函数的时候,定义了多少个必须参数,调用时就必须传递多少个参数,如上面的 add()
例子:
def detail(apple, lemon): print('apple: ' + str(apple), end=' ') print('lemon: ' + str(lemon)) detail(5, 10) #apple: 5 lemon: 10 detail(lemon=10, apple=5) #apple: 5 lemon: 10 调用时若记不清参数次序,可以使用关键字参数传参
5-5 默认值参数
格式:
def func_name(param1='default1', param2='default2'): pass
默认值参数指的是参数定义时设置默认值,调用函数的时候,如果需要修改默认值,建议使用关键字参数,因为其可以不遵循默认值参数顺序。
def message(name, age, sex='male', nationality='China'): print('我叫 ' + str(name)) print('今年 ' + str(age)) print('性别 ' + str(sex)) print('国籍 ' + str(nationality)) message('xiaoming', 18, sex='female', nationality='USA') #最后两个传参位置可以替换 ----------------------- 我叫 xiaoming 今年 18 性别 female 国籍 USA
5-6 可变参数
先说一下序列解包,序列解包就是,将序列中的元素平铺出来,按照顺序分别赋值给多个变量。序列包含字符串、列表、元组。注意赋值的变量数量需要与序列中的元素数量一致。
序列解包-字符串
s='123' a,b,c=s print('a的值为:' + str(a) + ' 类型为: ' + str(type(a))) print('b的值为:' + str(b) + ' 类型为: ' + str(type(b))) print('c的值为:' + str(c) + ' 类型为: ' + str(type(c))) ----------------------- a的值为:1 类型为: <class 'str'> b的值为:2 类型为: <class 'str'> c的值为:3 类型为: <class 'str'>
序列解包-列表
s=[1, 2, 3] a,b,c=s print('a的值为:' + str(a) + ' 类型为: ' + str(type(a))) print('b的值为:' + str(b) + ' 类型为: ' + str(type(b))) print('c的值为:' + str(c) + ' 类型为: ' + str(type(c))) ----------------------- a的值为:1 类型为: <class 'int'> b的值为:2 类型为: <class 'int'> c的值为:3 类型为: <class 'int'>
序列解包-元组
s=(1, 2, 3) a,b,c=s print('a的值为:' + str(a) + ' 类型为: ' + str(type(a))) print('b的值为:' + str(b) + ' 类型为: ' + str(type(b))) print('c的值为:' + str(c) + ' 类型为: ' + str(type(c))) ----------------------- a的值为:1 类型为: <class 'int'> b的值为:2 类型为: <class 'int'> c的值为:3 类型为: <class 'int'>
对于可变参数,我们可以传递任意个参数,这些参数在函数调用时自动组装为一个tuple(元组).
例子:
def func_args(*args): print(args) print(type(args)) func_args(1, 2, 'a', 'hello', [1, 2], (2, 3, 4), {'aa':4, 'bb':5}, {1, 2, 3}) ----------------------- (1, 2, 'a', 'hello', [1, 2], (2, 3, 4), {'aa': 4, 'bb': 5}, {1, 2, 3}) <class 'tuple'> ======================= a=(1, 2) func_args(a) ----------------------- ((1, 2),) #打印结果是元组里面嵌套元组 <class 'tuple'> ======================= func_args(*a) ----------------------- (1, 2) #上面传*a就不是嵌套元组了,传列表,字典,集合也一样 <class 'tuple'>
函数调用时,*号的作用就是将元组里面的元素平铺出来,传递到可变参数的函数里面。这就是序列解包。
实现一个可以计算任意多个参数和的可变参数函数,例子:
def add_all(*args): sum = 0 for i in args: sum += i return sum add_all(1,2) #3 add_all(1,2,3,4,5,6) #21 a=(1,2,3,4,5,6) add_all(*a) #21 传元组要*解包一下
5-7 可变关键字参数
可变关键字函数,在调用时可以传递任意个关键字参数,这些关键字参数在函数调用的时候会自动组装成一个dict(字典)
def func_kwargs(**kwargs): #两个**号代表我们可以传递任意个关键字参数 print(kwargs) print(type(kwargs)) func_kwargs(lemon=5, apple=10) ----------------------- {'lemon': 5, 'apple': 10} <class 'dict'> func_kwargs() ----------------------- {} <class 'dict'> fruits={'pear':4, 'orange':7} func_kwargs(**fruits) #可以传字典,但同样需要虚拟解包方式。传 fruits 和 *fruits 都报错。 ----------------------- {'pear': 4, 'orange': 7} <class 'dict'>
两个**号可以将元组中的键值对给评估出来,然后逐一传递到可变参数中。
可变参数 与 可变关键字参数 总结
(1) 可变参数: 可以传入任意个参数。如果传入的是一个序列(字符串、列表、元组),可使用 * 将每个元组平铺出来,然后再传递到可变参数函数里面。
(2) 可变关键字参数:可传入任意个关键字参数。如果传入的是一个字典,可使用 ** 将每个键值对平铺出来,传递到可变关键字参数函数里面。
5-8 函数参数类型顺序
函数中如果定义了必须参数,那么必须参数最好排在第一位。必须参数必须放在可变参数(带*号的)前面,也要放在默认参数(定义式有=的)前面。如果定义了可变关键字参数,那么它必须放在最后。
可以这样记:必须参数放在最前面,可变参数第二,默认参数最后。==>应该可变参数和默认参数不应该同时出现在一个函数中。
def func_args(param1, *args, param2=0, **kwargs): #成功,若将关键字参数放在最前,第二位,第三位都报错。 pass
5-9 变量作用域
Python中有以下几种作用域:
L Local 局部作用域 B Encloasing 嵌套函数外层非全局作用域 G Global 全局作用域 B Built-in 内建作用域
变量根据作用域可分为局部变量和全局变量,前者作用域在函数内,后者全局。若两个变量同名,互不影响。
例子:
lemon=5 def fruit(): lemon=20 #识别为变量定义而不是赋值,这是不同于C的地方,若是注释掉这行,函数调用就打印5 print(lemon) fruit() print(lemon) ----------------------- 20 5
函数内部也可以引用全局变量,会先使用函数内部的局部变量,若没有则会向上查找全局变量。函数外一般情况下是不可以引用局部变量的,但是global关键字可以实现。
可以从外部引用代码块(if, while, for)里面定义的变量!Python里面是没有块级作用域这个概念的。
5-10 作用域链
作用域链:作用域具有链式查找特性。特点为函数内部引用变量,会优先引用最近局部变量,然后才是逐级向上寻找。
5-11 global 关键字
函数外部一般是不可以引用局部变量的,但是使用global关键字可以实现。使用关键字global同样可以实现函数内对全局变量进行赋值
例子:
def fruits(): global lemon, pear #若没有这行会报错 lemon=10 pear=15 fruits() print(lemon, pear) ----------------------- 10 15 ======================= lemon=1 pear=2 def fruits(): global lemon, pear lemon=10 pear=15 print(lemon, pear) fruits() print(lemon, pear) ----------------------- 10 15 10 15
总结:可以使用global关键字声明多个局部变量为全局变量,也可以给全局变量进行赋值。
5-12 函数 return 的用法
程序运行第一个return语句后,大多数情况下会跳出该函数,不再执行代码。(在 try excepy finally 中还会执行finally后面的代码)
return支持返回多个结果
def fruit_double(lemon, apple): lemon = lemon * 2 apple = apple * 2 return lemon, apple #返回多个结果 print(fruit_double(2, 4)) type(fruit_double(2, 4)) #返回的是一个元组 ----------------------- (4, 8) tuple
5-13 案例-斐波那契数列
1. 斐波那契数列又称黄金分割数列,以兔子繁殖为例引入,数列前两项是1,从第三项开始,每一项都是前两项的和。
F(1)=1
F(2)=1
F(n)=F(n-1)+F(n-2) (n>=3)
#用户输入任意数字,返回第N项数字 def fib(num): if num<=0: raise Exception('num should bigger than 0') #中断程序触发异常 if num==1 or num==2: return 1 return fib(num-1)+fib(num-2)
注:调用fib(1000)就崩溃了。
2. 将第一项扩展到第N项,存为一个列表
列表推导式:
[循环变量名 for 循环变量名 in 可迭代对象 if 条件判断]
例子:
#创建一个列表一般方法 a=[] for i in range(10): a.append(i) a ----------------------- [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] ======================= b=[i for i in range(10)]; b ----------------------- [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] ======================= b=[i for i in range(10) if i>5]; b ----------------------- [6, 7, 8, 9]
扩展到N项的实现:
def fib(num): if num<=0: raise Exception('num should bigger than 0') if num==1 or num==2: return 1 return fib(num-1)+fib(num-2) num = int(input('Please input a num: ')) fibs_list=[fib(i) for i in range(1, num+1)]; #对于每一个i都将fib(i)的结果存入列表 fibs_list ----------------------- Please input a num: 10 [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
posted on 2023-08-01 14:56 Hello-World3 阅读(27) 评论(0) 编辑 收藏 举报