python基础学习(3)——自定义函数

本文详细介绍了Python中的函数定义规则,包括必选参数、默认参数、可变参数、关键字参数和命名关键字参数。此外,还涵盖了函数调用、返回值、匿名函数以及变量作用域的概念,比较了Python与其他语言在这些方面的差异。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


函数

函数定义

  我们可以定义一个由自己想要功能的函数,以下是简单的规则:
(1)函数代码块以def关键词开头,后接函数标识符名称和圆括号()。
(2)任何传入参数和自变量必须放在圆括号中间,圆括号之间可以用于定义参数。
(3)函数的第一行语句可以选择性地使用文档字符串——用于存放函数说明。
(4)函数内容以冒号起始,并且缩进。
(5)Return[expression]结束函数,选择性地返回一个值给调用方。不带表达式的return相当于返回None。

语法:

def functionname(parameters):
    "函数_文档字符串"
    function_suite
    return [expression]

默认情况下,参数值和参数名称是按函数声明中定义的的顺序匹配起来的。
案例:
将一个字符串作为传入参数,再打印到标准设备上。

def printme(str):
    "打印传入的字符串到标准显示设备上"
    print (str)
    return

空函数

如果想定义一个什么事也不做的空函数,可以用pass语句:

def nop ():
    pass

函数调用

  这个函数的基本结构完成以后,你可以通过另一个函数调用执行,也可以直接从Python提示符执行。
Python里不用像C语言里需要先申明函数再使用。
如下实例调用了printme()函数:

# 先定义函数
def printme(str):
    "打印传入的字符串到标准显示设备上"
    print (str)
    return



#调用函数
printme("我要调用用户自定义函数!") #输出结果:我要调用用户自定义函数!
printme("再次调用同一函数")#输出结果:再次调用同一函数

函数参数

以下是调用函数时可使用的正式参数类型:

  • 必选参数:fun(name,age)
  • 默认参数:fun(name=‘yjc’,age=18)
  • 可变参数:fun(*args)
  • 关键字参数:fun(name,age,**kw)
  • 命名关键字参数:fun(name,age,*,city)

必须参数

  必选参数也称位置参数。必选参数须以正确的顺序传入函数。调用时的数量必须和声明时的一样。
调用printme(函数,你必须传入一个参数,不然会出现语法错误:

# 先定义函数
def printme(str):
    "打印传入的字符串到标准显示设备上"
    print (str)
    return



#调用函数
printme() 
#输出结果:
#TypeError                                 Traceback (most recent call last)
#Cell In[12], line 1
#----> 1 printme()

#TypeError: printme() missing 1 required positional argument: 'str'

默认参数

  在这里插入代码片调用函数时,默认参数的值如果没有传入,则被认为是默认值。下例会打印默认的age,如果age没有被传入:

def printinfo(name,age = 35):
    "打印任何传入字符串"
    print("Name:", name );
    print("Age", age);
    return;

# 调用printinfo函数
printinfo("miki") # Name:miki  age 35
printinfo("miki",50)  # # Name:miki  age 50
#当不按顺序提供部分默认参数时,需要把参数名写上:
printinfo(name = 'miki' ,age = 50)# # Name:miki  age 50

可变参数

  在Python函数中,还可以定义可变参数。顾名思义,可变参数就是传入的参数个数是可变的,可以是1个、2个到任意个,还可以是0个。基本语法如下:

def functionname()*var_args_tuple):
    "函数_文档字符串 "
    function_suite
    return [expression]

加星号的变量名会存放所有未命名的变量参数。例如:

def calc(*numbers):
    sum = 0
    for n in numbers:
        sum = sum + n * n
    return sum 

在函数内部,参数numbers接收到的是一个tuple,调用该函数时,可以传入任意个参数,包括0个参数:

>>> calc(1,2)
5
>>> calc()
0

如果已经有一个list或者tuple,要调用一个可变参数怎么办?Python允许你在list或tuple前面加一个*号,把list或tuple的元素变成可变参数传进去:

>>> a = [1,2,3]
>>> calc(*a)
14

*a表示把a这个list的所有元素作为可变参数传进去。

关键字参数

关键字参数允许我们在传入必选参数外,还可以接受关键字参数kw:

def person(name,age,**kw):
    print('name:',name,'age:',age,'other:',kw)

上面函数name和age是必选的,kw是可选,也就是说第三个参数开始我们可以传入任意个数的关键字参数:

>>> person('Bob',35,city = 'Beijing')
name: Bob age: 35 other: {'city': 'Beijing'}
>>> person('Adam', 45, gender='M', job='Engineer')
name: Adam age: 45 other: {'gender': 'M', 'job':Engineer'}

从上面的例子可以看出,关键字参数让我们保证能接收到name和age以外,还可以提供更多的参数。
实际上关键字参数kw是个dict,如果我们已经准备好了dict,只需要在前面加**就可以转换成参数传入:

param = {'gender':'M','job':'Engineer'}
>>> person('Adam', 45, **param)
name: Adam age: 45 other: {'gender': 'M', 'job': 'Engineer'}

注: 关键字参数kw获得的dict是param的一份拷贝,对kw的改动不会影响到函数外的param。

命名关键字参数

如果要限制关键字参数的名字,就可以用命名关键字参数,就如:只接收city和job作为关键字参数。具体如下:

def person (name , age , * , city , job);
    print (name,age,city,job)

# 调用
person('yjc',22,city = 'Beijing',job = 'IT')
# 输出结果
yjc 22 Beijing IT

和关键字参数**kw不同,命名关键字参数需要一个特殊分隔符——星号,星号后面的参数被视为命名关键字参数。
  命名关键字参数必须传入参数名,这和位置参数不同。如果没有传入参数名,调用将报错。如果调用时缺少参数名city和job,Python解释器把这4个参数均视为位置参数,但person()函数仅接受2个位置参数。
如果函数定义中已经有了一个可变参数,后面跟着的命名关键字参数就不再需要一个特殊分隔符*
了:

def person (name , age , *args , city , job):
    print (name , age , city , job)

命名关键字参数可以有缺省值,从而简化调用:

def person(name, age, *, city='Beijing', job): 
    print(name, age, city, job)

由于命名关键字参数city具有默认值,调用时,可不传入city参数。

传递参数

和其他语言不一样,传递参数的时候,python不允许程序员选择采用传值还是传引用。
Python参数传递采用的肯定是“传对象引用”的方式。实际上,这种方式相当于传值和传引用的一种综合。
如果函数收到的是一个可变对象(比如字典或者列表)的引用,就能修改对象的原始值——相当于通过"传引用"来传递对象。如果函数收到的是一个不可变对象(比如数字、字符或者元组)的引用,就不能直接修改原始对象——相当于通过“传值”来传递对象。
如:

def changeme(mylist):
    "修改传入的列表"
    mylist.append([1,2,3,4])
    print ("函数内取值:", mylist)
    return

mylist = [10,20,30]
changeme(mylist)
print("函数外取值:",mylist)
#输出的结果:
#函数内取值:[10,20,30,[1,2,3,4]]
#函数外取值:[10,20,30,[1,2,3,4]]


#不可变对象
def changeFixed(age):
    age + =5
    print(age)
age = 10
changeFixed(age)
print (age)


#输出结果:
# 15
# 10

  有时候,并不想函数修改了原列表,我们就会想到既然列表互相赋值是地址引用,引入新的变量名也是不行的,那么,可以复制一个列表出来,这样内存里用的就不是同一个地址,也就不会改变原数组了:

def changeme(mylist):
    "修改传入的列表"
    mylist.append([1,2,3,4])
    print ("函数内取值:", mylist)
    return
# 调用函数
mylist = [10,20,30]
#tmp = mylist # 这样还是引用同一个地址,达不到不修改原列表目的
tmp = mylist[:] # 将原来的列表复制一份,地址将不再试相同的
changeme( tmp )
print ("函数外取值:",mylist)    


#输出结果
# 函数内取值:[10,20,30,[1,2,3,4]]
# 函数外取值:[10,20,30]

返回多个值

Python 里的函数是可以返回多个值:

def updPoint(x,y):
    x+=5
    y+=10
    return x,y

x, y = updPoint(1,2)
print(x,y)
#输出结果: 6  12

但其实这只是一种假象,Python函数返回的仍然是单一值:

r = updPoint(1,2)
print(r)

#输出结果:(6,12)

  返回值是一个tuple!但是,在语法上,返回一个tuple可以省略括号,而多个变量可以同时接收一个tuple,按位置赋给对应的值,所以,Python的函数返回多值其实就是返回一个tuple,但写起来更方便。

匿名函数

在Python中是用lambda来创建匿名函数的,lambda只是一个表达式,函数体比def简单很多。
  lambda的主体是一个表达式,而不是一个代码块。仅仅能在lambda表达式中封装有限的逻辑进去。lambda函数有自己的名字空间,且不能访问自有参数列表外或全局名字空间里的参数。虽然lambda函数看起来只写了一行,但是不等同于C或C++的内联函数,后者目的是调用小涵书时不占用栈内存从而增加运行效率。
lambda函数语法只包含一个语句:

lambda [arg1[,arg2,......,argn]]:expression

实例:

# 可写函数说明:
sum = lambda arg1,arg2:arg1+arg2;
# 调用sum函数
print "相加后的值为 :" ,sum(10,20) #输出结果:30
print "相加后的值为 :" ,sum(30,20) #输出结果:50

return 语句

return 语句用于退出函数,选择性地调用方返回一个表达式。不带参数值的return语句返回None。之前的例子都没有示范如何返回数值,下面实例:

#可写函数说明
def sum (arg1,arg2):
    # 返回2个参数的和
    total = agr1+agr2
    print("函数内 :" ,total)
    return total;

#调用函数
total = sum (10.20)
print ("函数外:",total)

# 输出结果:
# 函数内:30
# 函数外:30

变量

  一个程序的所有的变量并不是在哪个位置都可以访问的。访问权限决定于这个变量是在哪里赋值的。
变量的作用域决定了在哪一部分程序你可以访问哪个特定的变量名称。两种最基本的变量作用域如下:
(1)全局变量
(2)局部变量

定义在函数内部的变量拥有一个局部作用域,定义在函数外的拥有全部作用域。
局部变量只能再其被声明的函数内部访问,而全部变量可以在整个程序范围内(也包括函数里面)访问。如:

total = 0 # 这个是全局变量

# 可写函数说明
def sum (arg1 , arg2):
    #返回2个参数的和
    total = agr1 + agr2  # total在这里就是一个局部变量
    print "函数内局部变量 :" ,total
    return total

# 调用sum函数

sum( 10,20)
print "函数外是全局函数 :", total


# 输出的结果:
##  函数内是局部变量:30
##  函数外是全局变量:0

但是如果在函数中定义的局部变量如果和全局变量同名,则它会隐藏该全局变量。例如:

a = 10

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

test();

输出:10
如果把上面代码的注释去掉,运行会报错:
UnboundLocalError:local variable’a’referenced before assignment,这点非常值得注意。

如果要给全局变量在一个函数里赋值,必须使用global语句

  global VarName表达式会告诉Python,VarName是一个全局变量,这样Python就不会在局部命名空间里寻找这个变量了。例如,我们在全局命名空间里定义一个变量money。我们再在函数内给变量money赋值,然后Python会假定money是一个局部变量。然而,我们并没有在访问前声明一个局部变量money,结果就是会出现一个UnboundLocalError的错误。取消global语句的注释就能解决这个问题。

Money = 2000

def AddMoney():
    # 想改正代码就取消以下注释:
    #  global Money
    Money = Money + 1

print (Money)

AddMoney ()
print(Money)

C、Python 、js区别:

  • c语言里函数外定义的变量在函数内部是可见可修改的。但函数内部定义的变量(含同名)作用域是局部的;
  • js语言里函数外定义的变量在函数内部是可见可修改的。但函数内部定义的变量(含同名)作用域是局部的。另外js变量在函数内部还有变量提升的特性;
  • pyhon里函数外定义的变量在函数内部是可见的但是不能修改。且函数里存在和函数外变量同名,函数外变量不可用。如果想修改函数外的变量,需要函数内使用global语句。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值