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  阅读(12)  评论(0编辑  收藏  举报

导航