函数-基础


文章目录

  • 函数-基础
  • 一、函数的作用与定义
  • 1.1、作用
  • 1.2、定义
  • 语法
  • 实例
  • 1.3、函数的调用
  • 二、函数的形参与实参
  • 定义:
  • 实例:
  • 三、函数的参数类型
  • 3.1、类型
  • 3.2、位置参数(必要参数)
  • 说明:
  • 实例:
  • 只有一个位置参数时,你必须传递一个参数。
  • 存在多个位置参数时,你必须传递相同数量的参数,顺序必须与定义的一致。
  • 3.3、关键字参数
  • 说明:
  • 实例:
  • 3.4、默认参数
  • 说明:
  • 实例:
  • 3.5、非固定参数(不定长参数)
  • 说明:
  • 实例:
  • 特别(不建议使用):
  • 3.6、参数优先级
  • 说明:
  • 实例:
  • 四、函数的返回值与作用域
  • 4.1、返回值
  • 说明:
  • 实例:
  • 4.2、作用域
  • 全局与局部变量
  • 说明
  • 实例


一、函数的作用与定义

1.1、作用

函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段。函数能提高应用的模块性,和代码的重复利用率。你已经知道Python提供了许多内建函数,比如print()。但你也可以自己创建函数,这被叫做用户自定义函数。

  • 减少重复代码
  • 使程序变的可扩展
  • 使程序变得易维护

1.2、定义

定义一个函数你可以定义一个由自己想要功能的函数,以下是简单的规则:

  • 函数代码块以 def 关键词开头,后接函数标识符名称和圆括号 ()。
  • 任何传入参数和自变量必须放在圆括号中间,圆括号之间可以用于定义参数。
  • 函数的第一行语句可以选择性地使用文档字符串—用于存放函数说明。
  • 函数内容以冒号起始,并且缩进。
  • return [表达式] 结束函数,选择性地返回一个值给调用方。不带表达式的return相当于返回 None。
语法
def functionname(parameters): 
    "函数_文档字符串" 
    function_suite 
    return [expression]
实例
def printme(str): 
    "打印传入的字符串到标准显示设备上" 
    print(str)
    return

1.3、函数的调用

#!/usr/bin/python3 
# 计算面积函数 
def area(width, height): 
    return width * height 
    
def print_welcome(name): 
    print("Welcome", name) 
    
print_welcome("Runoob") 
w = 4 
h = 5 
print("width =", w, " height =", h, " area =", area(w, h))

二、函数的形参与实参

定义:
  • 形参:只有在被调用时才分配内存单元,在调用结束时,立刻释放所分配的内存单元。因此,形参只在函数内部有效。函数调用结束返回主调用函数后则不能再使用该形参变量
  • 实参:传递的值,可以是常量、变量、表达式、函数等,无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形参。因此应预先给实参赋值。
    实例
实例:

以下哪一个选项可以定义python函数 下面python程序中定义f1_字符串

三、函数的参数类型

3.1、类型

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

  • 位置参数(必需参数)
  • 关键字参数
  • 默认参数
  • 不定长参数

3.2、位置参数(必要参数)

说明:

位置参数须以正确的顺序传入函数。调用时的数量必须和声明时的一样。

实例:
只有一个位置参数时,你必须传递一个参数。
#!/usr/bin/python3
 
#可写函数说明
def printme( str ):
   "打印任何传入的字符串"
   print (str)
   return
 
# 调用 printme 函数,不加参数会报错
printme()

调用 printme() 函数,你必须传入一个参数,不然会出现语法错误:

Traceback (most recent call last):
  File "test.py", line 10, in <module>
    printme()
TypeError: printme() missing 1 required positional argument: 'str'
存在多个位置参数时,你必须传递相同数量的参数,顺序必须与定义的一致。
def stu_register(name,age,country,course):
    print("----注册学生信息------")
    print("姓名:",name)
    print("age:",age)
    print("国籍:",country)
    print("课程:",course)
stu_register("张三",22,"CN","python_devops")
stu_register("李四",21,"CN","linux")
stu_register("王五",25,"CN","linux")

调用 stu_register() 函数,你必须传入4个参数,且顺序必须与定义对应。如果顺序不对应会导致参数传递错误。

3.3、关键字参数

说明:
  • 指定了参数名的参数就叫关键参数。
  • 关键字参数和函数调用关系紧密,函数调用使用关键字参数来确定传入的参数值。使用关键字参数允许函数调用时参数的顺序与声明时不一致,因为 Python 解释器能够用参数名匹配参数值。

但记住一个要求就是,关键参数必须放在位置参数(以位置顺序确定对应关系的参数)之后

实例:
#可写函数说明
def printinfo( name, age ):
   "打印任何传入的字符串"
   print ("名字: ", name)
   print ("年龄: ", age)
   return
 
#调用printinfo函数
printinfo( age=50, name="runoob" )

以上实例在函数 printme() 调用时使用不需要使用指定顺序。

3.4、默认参数

说明:
  • 调用函数时,如果没有传递参数,则会使用默认参数。以下实例中如果没有传入 age 参数,则使用默认值

注意:默认参数一定要用不可变对象,如果是可变对象,程序运行时会有逻辑错误!
注意:默认参数必须放在所有位置参数后面

实例:
#可写函数说明
def printinfo( name, age = 35 ):
   "打印任何传入的字符串"
   print ("名字: ", name)
   print ("年龄: ", age)
   return
 
#调用printinfo函数
printinfo( age=50, name="runoob" )
print ("------------------------")
printinfo( name="runoob" )

以上实例输出结果:

名字:  runoob
年龄:  50
------------------------
名字:  runoob
年龄:  35

3.5、非固定参数(不定长参数)

说明:
  • 若你的函数在定义时不确定用户想传入多少个参数,就可以使用非固定参数。
  • 非固定参数存在两种形式:
  • a、加了一个星号 * 的参数会以元组(tuple)的形式导入,存放所有未命名定义的变量参数。默认变量名称为*args,当然也可以自己定义,比如*var_args_tuple
  • b、加了两个星号 ** 的参数会以字典(dict)的形式导入,存放所有未命名定义的变量参数。默认变量名称为**kwargs ,当然也可以自己定义。
实例:

*args 使用玩法:

def printinfo(name, age, *args):
    "打印任何传入的字符串"
    print("名字: ", name)
    print("年龄: ", age)
    print("非固定参数", args)
    return

printinfo("runoob", 20)
printinfo("runoob", 20, "男", "180cm")

以上结果:

名字:  runoob
年龄:  20
非固定参数 ()
名字:  runoob
年龄:  20
非固定参数 ('男', '180cm')

**kwargs 使用玩法:参数传递时,多的参数使用键值对的形式传递

def printinfo(name, age, **kwargs):
    "打印任何传入的字符串"
    print("名字: ", name)
    print("年龄: ", age)
    print("非固定参数", kwargs)
    return

printinfo("runoob", 20)
printinfo("runoob", 20, sex="男", len="180cm")

以上结果:

名字:  runoob
年龄:  20
非固定参数 {}
名字:  runoob
年龄:  20
非固定参数 {'sex': '男', 'len': '180cm'}
特别(不建议使用):

声明函数时,参数中星号 * 可以单独出现,例如:

def f(a,b,*,c):
    return a+b+c

如果单独出现星号 * 后的参数必须用关键字传入。

>>> def f(a,b,*,c):
...     return a+b+c
... 
>>> f(1,2,3)   # 报错
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: f() takes 2 positional arguments but 3 were given
>>> f(1,2,c=3) # 正常
6
>>>

3.6、参数优先级

说明:

参数定义的顺序必须是:位置参数(必选参数)、默认参数、非固定参数(不定长参数)、命名关键字参数和关键字参数。

实例:
def f1(a, b, c=0, *args, **kw):
    print('a =', a, 'b =', b, 'c =', c, 'args =', args, 'kw =', kw)

def f2(a, b, c=0, *, d, **kw):
    print('a =', a, 'b =', b, 'c =', c, 'd =', d, 'kw =', kw)
    
f1(1, 2) #a = 1 b = 2 c = 0 args = () kw = {}
f1(1, 2, c=3) #a = 1 b = 2 c = 3 args = () kw = {}
f1(1, 2, 3, 'a', 'b') #a = 1 b = 2 c = 3 args = ('a', 'b') kw = {}
f1(1, 2, 3, 'a', 'b', x=99)#a = 1 b = 2 c = 3 args = ('a', 'b') kw = {'x': 99}
f2(1, 2, d=99, ext=None) #a = 1 b = 2 c = 0 d = 99 kw = {'ext': None}

# 特别通过tuple和dict调用
args = (1, 2, 3, 4)
kw = {'d': 99, 'x': '#'}
f1(*args, **kw) #a = 1 b = 2 c = 3 args = (4,) kw = {'d': 99, 'x': '#'}

args = (1, 2, 3)
kw = {'d': 88, 'x': '#'}
f2(*args, **kw) #a = 1 b = 2 c = 3 d = 88 kw = {'x': '#'}

四、函数的返回值与作用域

4.1、返回值

说明:

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

  • 函数在执行过程中只要遇到return语句,就会停止执行并返回结果,so 也可以理解为 return 语句代表着函数的结束
  • 如果未在函数中指定return,那这个函数的返回值为None
  • 返回值可以是任意类型,包括数据类型,函数、对象、方法均可以。
实例:

以下实例演示了 return 语句的用法:

# 可写函数说明
def sum( arg1, arg2 ):
   # 返回2个参数的和."
   total = arg1 + arg2
   print ("函数内 : ", total)
   return total
 
# 调用sum函数
total = sum( 10, 20 )
print ("函数外 : ", total)

4.2、作用域

全局与局部变量
说明

全局变量:一般定义在文件头部,全局变量作用域(即有效范围)是整个程序。
局部变量:定义在函数内部,局部变量作用域是定义该变量的函数。

  • 变量的查找顺序是局部变量>全局变量
  • 当全局变量与局部变量同名时,在定义局部变量的函数内,局部变量起作用;在其它地方全局变量起作用。见后续实例。
  • 如果想在函数内部修改全局变量,需要使用global关键字,声明全局变量。详见后续实例
实例
NAME = 'Bob'

def print_name():
    NAME = 'Job1'  # 局部变量
    return NAME

def change_name():
    global NAME
    print('改变前名称:', NAME)
    NAME = 'Job2'  # 局部变量
    print('改变后名称:', NAME)

print('打印全局变化', NAME)
print('打印局部局变化', print_name())

change_name()

上述运行结果:

打印全局变化 Bob
打印局部局变化 Job1
改变前名称: Bob
改变后名称: Job2