Python3快速入门—5.函数

5.函数

5.1函数的定义

在Python中,函数定义的格式如下:

def funcname(parameter_list):

    pass

其中,funcname是函数名称,parameter_list是函数的参数列表,pass表示函数体。

'''this is run.py'''

def print_info(a):

    print(a)

 

f = 1.234

print_info(f)

运行结果:

1.234

在Python中可以使用help来查看函数的信息。

'''this is run.py'''

def print_info(a):

    print(a)

 

help(print_info)

help(print)

运行结果:

Help on function print_info in module __main__:

 

print_info(a)

 

Help on built-in function print in module builtins:

 

print(...)

    print(value, ..., sep=' ', end='\n', file=sys.stdout, flush=False)

 

    Prints the values to a stream, or to sys.stdout by default.

    Optional keyword arguments:

    file:  a file-like object (stream); defaults to the current sys.stdout.

    sep:   string inserted between values, default a space.

    end:   string appended after the last value, default a newline.

    flush: whether to forcibly flush the stream.

在上述代码中,查看了print_info的函数信息和内置函数print的函数信息。

函数具有3大特点:功能性、模块性、复用性。

功能性:函数的作用是为了实现某一具体的功能。

模块性:将多行代码存放在函数代码块中,使用函数名来调用。

复用性:函数可以使用在多个场景。

5.2函数名、参数列表和返回值

函数名不能和已有的函数名重复,不然会覆盖之前的函数定义。

例1:

'''this is run.py'''

i = 1

print(i)

 

def print(a):

    a += 1

 

print(i)

运行结果:

1

第一个print是builtins模块内的函数,第二个print是我们自己创建的函数。

例2:

'''this is run.py'''

i = 1

 

#打印参数a

def print_info(a):

    print(a)

 

print_info(i)

 

#打印参数a+1

def print_info(a):

    print(a+1)

 

print_info(i)

运行结果:

1

2

函数的参数列表可以是对象,也可以是空对象。在其他编程语言中,可以使用void表示函数无参数;但是在Python中并没有void。

'''this is run.py'''

#打印1

def print_info():

    print(1)

 

print_info()

运行结果:

1

函数的返回值有3种情况:(1)返回None,即没有返回值;(2)返回一个变量;(3)返回多个变量。

例1:返回None                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          

'''this is run.py'''

#打印a

def print_info(a):

    print(a)

 

i = 1.2345

print_info(i)

运行结果:

1.2345

例2:使用return返回None

'''this is run.py'''

#打印a

def print_info(a):

    print(a)

return #或return None

 

i = 1.2345

val = print_info(i)

 

print(val)

print(type(val))

运行结果:

1.2345

None

<class 'NoneType'>

例3:返回一个变量

'''this is run.py'''

#计算a加b,并返回

def add(a,b):

    return a+b

 

val = add(1,2)

print(val)

运行结果:

3

例4:返回多个变量

'''this is run.py'''

#计算a+1、b+1,并返回

def add(a,b):

    return a+1,b+1

#方法1:

val = add(1,2)

print(val)

 

#方法2

val1,val2 = add(1,2) #序列解包

print(val1,val2)

运行结果:

(2, 3)

2 3

当函数返回多个变量时,若用一个变量来获取返回值,则此返回值是一个元组;若用相同数量的变量来获取返回值,则按位置赋予相应的数值。

例5:将返回的多个变量打包

'''this is run.py'''

#计算a+1、b+1,并返回

def add(a,b):

    return [a+1,b+1]

#方法1:

val = add(1,2)

print(val)

 

val1, val2 = add(3,4)

print(val1,val2)

运行结果:

[2, 3]

4 5

使用return时,不仅可以将多个变量打包成列表,还可以是元组、集合。

5.3序列解包

问题1:在5.2节中,当函数返回多个变量时,发现实际上返回的是元组,为什么?

答案:元组的赋值和返回是不需要加括号的。

'''this is run.py'''

tup = 1,2,3,'hello'

print(tup)

print(type(tup))

运行结果:

(1, 2, 3, 'hello')

<class 'tuple'>

问题2:为什么元组(返回值)可以将对应位置的元素分别赋值给别的变量。

答案:不仅是元组,字符串、列表、集合、字典等都可以将对应位置的元素依次赋值给变量(但变量个数应该和元素个数相等)。我们将这种操作称为“序列解包”,虽然称呼不是很准确,因为序列只包括字符串、列表、元组。

'''this is run.py'''

#元组

tup = 1,2,'hello'

print(tup)

print(type(tup))

a,b,c = tup

print(a,b,c)

 

#字符串

s = "hello"

a,b,c,d,e = s

print(a,b,c,d,e)

 

#列表

l = [1,2,3]

a,b,c = l

print(a,b,c)

 

#集合

set1 = {1,2,3,4}

a,b,c,d = set1

print(a,b,c,d)

 

#字典

d = {1:'hello',2:'world'}

a,b = d

print(a,':',d[a],b,':',d[b])

a,b = d.items()

print(a,b)

运行结果:

(1, 2, 'hello')

<class 'tuple'>

1 2 hello

h e l l o

1 2 3

1 2 3 4

1 : hello 2 : world

(1, 'hello') (2, 'world')

5.4函数参数

讲到函数,几乎所有的编程语言都会涉及到2个概念:形参、实参。

在函数定义中的参数,称为形参;在函数实际调用时传递的参数,称为实参。

在Python中,参数有多种分类:必须参数、关键字参数、默认参数、可变参数等,这些参数在实际调用中又该怎么使用呢?

注:在Python中,函数中的形参定义、关键字定义等,不能以数字开头,必须以字母和_开头。

5.4.1必须参数和关键字参数

必须参数:在函数实际调用中,必须要传递的参数。

'''this is run.py'''

 

def person(name,age,profession):

    print('my name is '+str(name))

    print('I am '+str(age))

    print('I am a '+str(profession))

 

person('Jack',28,'teacher')

运行结果:

my name is Jack

I am 28

I am a teacher

在函数的实际调用中,实参必须和函数定义中的形参一一对应,不能多、不能少、不能顺序颠倒。

关键字参数:在函数的实际调用中,实参可以使用形参列表中的变量名称,来指定具体的参数。使用关键字参数,其参数顺序可以颠倒;但必须参数要放在关键字参数的前面,否则函数不知道这个必须参数对应哪一个形参。

'''this is run.py'''

 

def person(name,age,profession):

    print('my name is '+str(name))

    print('I am '+str(age))

    print('I am a '+str(profession))

 

person('Jack',profession='teacher',age = 28)

运行结果:

my name is Jack

I am 28

I am a teacher

5.4.2默认参数

参数顺序颠倒的问题可以用关键字参数解决了;但若是在函数实际调用中,参数写少了,该怎么办呢?

默认参数:在定义函数时,使用赋值运算符(=)为参数指定默认值。若实际调用中,此参数未传递实际数值,则使用默认值。

'''this is run.py'''

 

def person(name,age = 18,profession = 'student'):

    print('my name is '+str(name))

    print('I am '+str(age))

    print('I am a '+str(profession))

 

person('Jack')

运行结果:

my name is Jack

I am 18

I am a student

在函数定义时,若有一个参数设置成默认参数,则其右侧所有参数都必须定义成默认参数。

'''this is run.py'''

 

def person(name,age = 18,profession):

    print('my name is '+str(name))

    print('I am '+str(age))

    print('I am a '+str(profession))

 

person('Jack',profession = 'teacher')

运行结果:

  File ".\run.py", line 3

    def person(name,age = 18,profession):

              ^

SyntaxError: non-default argument follows default argument

原因:若参数profession没有定义成默认参数,那解释器不知道哪个默认参数没有传递。

在函数调用时,若有一个默认参数没有传递数值而使用默认值;则其右侧的默认参数若想传递数值,必须使用关键字参数。

'''this is run.py'''

 

def person(name,age = 18,profession = 'student'):

    print('my name is '+str(name))

    print('I am '+str(age))

    print('I am a '+str(profession))

 

person('Jack','teacher')

运行结果:

my name is Jack

I am teacher

I am a student

原因:函数错认为'teacher'传递给默认参数age。

'''this is run.py'''

 

def person(name,age = 18,profession = 'student'):

    print('my name is '+str(name))

    print('I am '+str(age))

    print('I am a '+str(profession))

 

person('Jack',profession = 'teacher')

运行结果:

my name is Jack

I am 18

I am a teacher

5.4.3可变参数

可变参数:在函数定义中,参数名称前加上星号(*),表示此参数为可变参数,其传入的实际参数可以是任意个。

'''this is run.py'''

 

def person(*param):

    print('my name is '+str(param[0]))

    print('I am '+str(param[1]))

    print('I am a '+str(param[2]))

 

person('Jack',28,'teacher')

运行结果:

my name is Jack

I am 28

I am a teacher

当person中,传递的'Jack',28,'teacher',实际上是一个元组,即param = ('Jack',28,'teacher')。

'''this is run.py'''

 

def person(*param):

    print(param)

    print(type(param))

    

person('Jack',28,'teacher')

运行结果:

('Jack', 28, 'teacher')

<class 'tuple'>

问题1:可变参数可以放在默认参数后吗?

答案:不可以。因为当默认参数未传递数值时,后面可变参数的第一个数值将代替默认参数传入。

问题2:可变参数可以放在默认参数前吗?

答案:可以。当默认参数不传递数值时,会使用默认值;当默认参数传递数值时,必须使用关键字参数来指定。

例1:

'''this is run.py'''

 

def func(param1,*param2,param3 = '默认参数'):

    print(param1)

    print(param2)

    print(param3)

 

 

func('必须参数',1,2,3,'可变参数')

运行结果:

必须参数

(1, 2, 3, '可变参数')

默认参数

例2:

'''this is run.py'''

 

def func(param1,*param2,param3 = '默认参数'):

    print(param1)

    print(param2)

    print(param3)

 

 

func('必须参数',1,2,3,'可变参数',param3 = '关键字参数 + 默认参数')

运行结果:

必须参数

(1, 2, 3, '可变参数')

关键字参数 + 默认参数

5.4.4关键字可变参数

关键字可变参数:在函数定义中,参数名称前加上星号(**),表示此参数为关键字可变参数,其传入的实际关键字参数可以是任意个。

'''this is run.py'''

 

def func(**param):

    print(param)

    print(type(param))

 

func(n1 = '伊芙琳',n2 = '卡兹克',n3 = '李青',n4 = '伊莉丝')

运行结果:

{'n1': '伊芙琳', 'n2': '卡兹克', 'n3': '李青', 'n4': '伊莉丝'}

<class 'dict'>

5.4.5参数解包

在前面学习了序列解包,这一节会学习当函数参数是一个序列、集合、字典,又该如何传递呢?

'''this is run.py'''

#错误实例

def person(name, age, profession):

    print('my name is '+str(name))

    print('I am '+str(age))

    print('I am a '+str(profession))

 

tup = ('Jack',18,'student')

 

person(tup)

运行结果:

Traceback (most recent call last):

  File ".\run.py", line 10, in <module>

    person(tup)

TypeError: person() missing 2 required positional arguments: 'age' and 'profession'

为什么不可以,在前面不是说name, age, profession = ('Jack',18,'student')

原因:在函数实际传递参数时,解释器并不知道要将元组('Jack',18,'student')解包成3个参数。

在前面的”可变参数"章节中,其代码如下。

'''this is run.py'''

 

def person(*param):

    print(param)

    print(type(param))

    

person('Jack',28,'teacher')

运行结果:

('Jack', 28, 'teacher')

<class 'tuple'>

可以看到param = ('Jack', 28, 'teacher'),而*param = 'Jack',28,'teacher'。因此,星号(*)在这里的作用是解包。同理,在关键字可变章节中,**的作用是为字典解包。

'''this is run.py'''

 

def person(name, age, profession):

    print('my name is '+str(name))

    print('I am '+str(age))

    print('I am a '+str(profession))

 

tup = ('Jack',18,'student')

person(*tup)

 

def func(Jungle,Topsolo):

    print('Jungle',':',Jungle)

    print('Topsolo',':',Topsolo)

 

#Jungle:打野;Topsolo:上单

dic = {'Jungle':'伊芙琳','Topsolo':'武器大师'}

 

func(**dic)

运行结果:

my name is Jack

I am 18

I am a student

Jungle : 伊芙琳

Topsolo : 武器大师

5.5变量作用域

在Python中,只有2种变量:全局变量,局部变量。

全局变量:在函数体外定义的变量。

局部变量:在函数体内定义的变量。

例1:

'''this is run.py'''

 

def add(a,b):

    c = 1.234

    return a + b

 

my_sum = add (1,2)

print('my_sum = %s'%my_sum)

 

print('c = %.6f'%c)

运行结果:

my_sum = 3

Traceback (most recent call last):

  File ".\run.py", line 10, in <module>

    print('c = %.6f'%c)

NameError: name 'c' is not defined

原因:由于c是在函数体内定义的局部变量,因此在函数体外无法打印。

例2:

'''this is run.py'''

c = 1.234

def add(a,b):

    print('c = %.6f'%c)

    c = a + b

    print('c = %d'%c)

    return c

 

add(1,2)

print('c = %.3f'%c)

运行结果:

Traceback (most recent call last):

  File ".\run.py", line 21, in <module>

    add(1,2)

  File ".\run.py", line 16, in add

    print('c = %.6f'%c)

UnboundLocalError: local variable 'c' referenced before assignment

若定义的局部变量和全局变量名称相同,则不能在局部变量定义之前去打印全局变量。

例2.1:修改

'''this is run.py'''

 

c = 1.234

def add(a,b):

    c = a + b

    print('c = %d'%c)

    return c

 

add(1,2)

print('c = %.3f'%c)

运行结果:

c = 3

c = 1.234

全局变量的作用域是所有模块都有效;局部变量的作用域是只在函数体内有效。若函数体定义的局部变量名称和全局变量相同,则在函数体内局部变量会覆盖全局变量。

例3:低级变量覆盖高级变量

'''this is run.py'''

a = 1

 

def print_info1():

    a = 2

    print('print_info1中的局部变量 a = %d'%a)

    def print_info2():

        a = 3

        print('print_info2中的局部变量 a = %d'%a)

    print_info2()

 

print('全局变量 a = %d'%a)

print_info1()

运行结果:

全局变量 a = 1

print_info1中的局部变量 a = 2

print_info2中的局部变量 a = 3

例4:for语句

'''this is run.py'''

 

l = [1,2,3,4]

 

for a in l:

    b = 1.234

    print(a)

 

print('a = %d'%a,'b = %.3f'%b)

运行结果:

1

2

3

4

a = 4 b = 1.234

在很多其他的编程语言中,把流程控制语句内的变量也定义为局部变量;但是在Python中,在流程控制语句中定义的变量也是全局变量。

例5:global关键字

 

'''this is run.py'''

 

def func():

    global a

    a = 1

 

func()  #函数必须执行才会有a

print('a = %d'%a)

运行结果:

a = 1

在函数体内,可以使用global关键字来创建全局变量;需要注意的是,函数一定要执行了,才会去创建全局变量。

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值