Python函数

Python中使用def来定义一个函数,先看一个例子:

编写一个函数,实现求斐波那契数列的第n项:

def qf(n):
    '''实现求斐波那契数列的第n项'''
    if(n==1 or n==2):
        return 1
    else:
        return qf(n-1) + qf(n-2)
n = input()
n = int(n)
print(qf(n),end="")

Python中单行注释可以用#,多行的较长注释可以用’’’ ‘’’,或者 “”" “”",另外,这样的注释方式如果用在函数头部还可以对函数进行说明,如本例,当用help()函数调用这个qf()函数时,会输出说明内容,例:

>>> help(qf)
Help on function qf in module __main__:

qf(n)
    实现求斐波那契数列的第n项

help()得到的是对函数的详细说明,当然你也可以通过__doc__方法只看文档字符串:

>>> qf.__doc__
'实现求斐波那契数列的第n项'

通过这个例子,相信对Python中的函数你已经了解了一些,继续往下看;

一.传递实参

1.传入可变对象与不可变对象

对于无参函数来说怎样都无所谓了,但是对于需要传递参数的函数来说就要格外注意一点,在C语言的函数里面,不带引用的传递或者传递的不是指针类型的参数的话,在函数体内对参数的修改是不会使函数外的参数发生改变的,比如:

int change_x(int a){
    a = 10;
    return a;
}
int main()
{
    x = 7;
    int rel = change_x(x);
    printf("%d",rel);// 7
}

这种情况在Python中也存在,Python中一切皆对象,类型属于对象,而变量是没有类型的,变量仅仅是对对象的引用,对于向函数中传入不可变对象与传入可变对象,效果也是不一样的;

传入不可变对象:

def change_x(a):
    a = 10
x = 7
change_x(x)
print(x)# 7

在这个过程里,把x传递给函数时,传递的只是x的副本a,这个时候a和x都指向int对象7,之后新建了一个int对象10,并让a重新指向10,故从始至终x的指向一直未变,故仍然输出7;

传入可变对象:

def change_list(list_a):
    list_a.append('hello')
list_x = [1,2,3]
change_list(list_x)
print(list_x)# [1, 2, 3, 'hello']

传入不可变对象时,实际上传入的是地址,为了更好说明,我这里借用一下C语言中指针的概念,以上例为参照,我们要传入实参列表list_x,但list_x只是一个变量,它指向[1,2,3],或者说list_x是一个指针,它保存着[1,2,3]的地址,在调用change_list函数时,Python会再复制出一个指针,它是list_x的副本,即函数体内的list_a并不是list_x,它们是两个指针,只不过两个指针都指向[1,2,3],又因为是指针,保存的是地址,因此在函数体内对列表的修改也就是对原列表的直接操作;

2.传递参数的几种方式

位置参数:
这个很好说明,位置参数就是说要按函数体中形参的顺序来传递实参,例:

def create_messages(name,language):
    name = name.title()
    language = language.title()
    message = name + "'s favorite language is " + language + "."
    print(message)
create_messages('lihua','c')
#输出:
Lihua's favorite language is C

#很显然,如果这里把 'lihua' 'c' 的位置弄错了的话,就会得到错误信息

关键字参数:

def create_messages(name,language):
    name = name.title()
    language = language.title()
    message = name + "'s favorite language is " + language + "."
    print(message)
create_messages(language = 'c',name = 'lihua') #在函数调用时给形参指定实参,这样即使位置混乱也没有关系

默认值:

仍旧以上面的函数例子说明,如果大部分人都喜欢C语言,那么为了节约编码时间,可以将language设置一个默认值,默认是’c’,即:

def create_messages(name,language = 'c'):
    name = name.title()
    language = language.title()
    message = name + "'s favorite language is " + language + "."
    print(message)

这样当你在调用该函数时,如果不对language形参传递实参,Python将使用默认值;

不定长参数:

如果你在声明一个函数时不知道将来要给它传递多少参数,那么可以使用不定长参数,例子如下:

def p_shopping(*goods):
    '''打印顾客购买的所有商品'''
    print(goods)
p_shopping('cakes','drink','toys','short') #调用函数
#输出:
('cakes', 'drink', 'toys', 'short')

注意goods前的星号*让Python创建了一个名为goods的空元组,并将受到的所有值都装在这个元组中;

如果你想在一个函数里面使用不同类型的参数,那么在函数定义里面必须把不定长参数放在最后面,在进行参数匹配时先匹配位置参数和关键字参数以及默认值,最后再把剩下的所有参数都与不定长参数匹配;

不定长关键字参数:

如果你想在函数里使用任意数量的关键字参数,但预先不知道会传入什么信息,可以使用任意数量的关键字实参,例子如下:

def stu_data(name,**s_data):
    '''创建一个存储学生信息的字典并返回'''
    s_dict = {}
    s_dict['name'] = name
    for key,value in s_data.items():
        s_dict[key] = value
    return s_dict
stu1_data = stu_data('jeha',sage=18,sex='girl') #键不加'',值加''
print(stu1_data)
#输出:
{'name': 'jeha', 'sage': 18, 'sex': 'girl'}

如上s_data前两个星号**让Python创建了一个名为s_data的空字典,并把所有收到的键值对封装在里面;

二.变量作用域

1.四种作用域

在Python里面也有变量作用域,Python中的作用域一共有四种,分别是:

L(Local):局部作用域
包含在del定义的代码块中,每次函数创建都会创建一个新的局部作用域,包括递归,局部作用域内的变量生存周期短,在函数调用结束之后,该空间也随之被释放;

E(Enclosing):嵌套作用域
如果函数里面嵌套有函数,那么两个函数都会有作用域,外围函数产生嵌套作用域,嵌套函数则产生局部作用域;

G(Global):全局作用域
在模块层次定义的变量拥有全局作用域,每个模块都是一个全局作用域,但模块与模块之间仍不相通;

B(Built-in):内置作用域
系统里固定模块里定义的变量,但与之相关的变量名自身并没有导入到内置作用域内,必须导入文件才能使用;

在查找变量时,Python以 L -> E -> G -> B 的顺序查找;

Python中只有模块、类、以及函数才会引入新的作用域;

2.global与nonlocal关键字

如果你想在内部作用域内定义外部作用域变量,就需要global与nonlocal关键字了;

global关键字:

global关键字可以在函数体内定义全局变量,例:
def test():
    global a
    a = 7
test()
print(a)# 7

这里只需注意一点,global定义的变量不能直接赋值,即 global a = 7 这种方式是错误的;

nonlocal关键字:

nonlocal关键字可以在局部作用域内定义嵌套作用域变量,例:
def outer():
    a = 10
    def inner():
        nonlocal a
        a = 7
    inner()
    return a
a = outer()
print(a)# 7

这里也只需注意一点,nonlocal与global是有区别的,global是直接定义出了一个全局变量,而nonlocal则是修改变量的作用域,它要求变量一点要事先存在,而且它只能把局部作用域内的变量作用域修改为嵌套作用域;

注意点:

如果没有global或者nonlocal来修改变量定义域,不同层次的定义域内的变量哪怕名字相同但也不是一样的,例:

a = 10
def test():
    a = a**2
    print(a)
test()

运行后会报错,因为test函数里面的a是局部定义域内的变量,尚未被定义,但是如果仅仅是用来输出的话就没问题:

a = 10
def test():
    print(a)
test() #10

这是因为Python默认在给变量赋值时就是定义了一个新变量;

还有下面这种区别:

a = 10
def test():
    a = 7
    print(a)
test() # 7

a = 10
def test():
    print(a)
    a = 7
test() #运行错误

三.函数高级用法

1.使用函数变量

def p_message(name):
    print('my name is %s' % (name.title()))
temp_p = p_message #把函数赋给变量temp_p
temp_p('jeha')# my name is Jeha

2.使用函数作为函数形参

3.使用函数作为函数返回值

四.匿名函数

Python使用lambda来创建匿名函数,匿名函数不需要def关键字,且自身非常的简洁,Python要求lambda函数只能有一行;
但这并不妨碍lambda的简洁好用,lambda函数的主体是表达式,但lambda有自己的命名空间,不能访问自己参数列表之外或者全局命名空间里的参数;

使用lambda函数的例子:

num = lambda a,b,c : a+b+c
print(num(2,8,-5)) # 5

部分内容(不限于本文)参考自:

菜鸟编程
廖雪峰的官方网站
c语言中文网
以及《Python编程-从入门到实践》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值