Python函数

Python 函数

1. 什么是函数

image

函数是指一段可以直接被另一段程序或代码引用的程序或代码。也叫做子程序、方法(OOP中)。

一个较大的程序一般应分为若干个程序块,每一个模块用来实现一个特定的功能。所有的高级语言中都有函数这个概念,用函数实现模块的功能。函数是有组织的可重用代码块,为应用程序提供了更好的模块化,并且可以高度重用代码。

简单来说,在编程语言中函数就类似于是工具,提前定义好之后可以反复使用。

2. 函数语法结构

2.1 如何定义一个函数

函数的定义就相当于事先将函数体代码保存起来,然后将内存地址赋值给函数名,函数名就是对这段代码的引用,这和变量的定义是相似的。如:

def 函数名(参数1,参数2):
    '''函数注释'''
    函数体代码
    return 返回值

image

2.2 函数结构分析

1. 其中 def 为定义函数的关键字,这个是必须要写的 

2.函数名 是必须的要写的,相当于变量名,使用函数就是调用函数名。
函数名的命名规范与风格遵循变量名的

3.() 括号是必须要写的,它紧跟着函数名,里面的参数为可选的,参数可写也可以不写,写的话也可以写多个。
如果不写参数就是定义了一个没有参数的函数,如果写参数的话表示在使用函数之前需要先给这个函数传参

4.函数注释可选,建议写上,主要是对函数的说明:介绍函数功能,参数使用及其他情况

5.函数内代码 这个是必须要写,函数核心的代码逻辑,主要实现了函数的功能,

6.return 返回值 可选,一个函数可以有返回值。也可以没有返回值。

函数定义示例:

# 定义一个没有参数没有返回值的函数
def my_print_v1():
    print("hello")
# 定义一个即有参数又有返回值的函数    
def my_print_v2(name):
    print("hello, %s" % name)
    return 0

2.3 函数的调用

函数调用直接写函数名和括号,如果函数需要参数则括号里写入参数

def my_print_v1():  # 定义一个无参数的函数
    print("hello")	# 打印hello

def my_print_v2(name):	# 定义一个需要传参数的函数 
    print("hello, %s" % name)	# 打印这个传过来的参数
    return 0	# 函数返回值为:0


my_print_v1()  # 函数调用,直接打印hello 
print(my_print_v2("Hans"))	# 执行函数并打印返回值
res = my_print_v2("Jack")  # 执行函数并把返回值赋给res

print("function  my_print_v2 return value: %d" % res) #打印返回赋


# my_print_v1() 执行结果
hello   
# my_print_v2("Hans") 执行结果
hello, Hans
0
# my_print_v2("Jack") 执行结果
hello, Jack
function  my_print_v2 return value: 0

# python中函数要先定义后调用,否则会报错:
my_print_v1()
def my_print_v1():
    print("hello")
# 执行结果:
Traceback (most recent call last):
  File "func.py", line 2, in <module>
    my_print_v1()
NameError: name 'my_print_v1' is not defined
    
# 函数定义时只检测语法不执行代码
def my_print_v1():
    print("hello")
    ksaljf
    saljf
# 执行代码,没有报错(因为只是定义还没有运行)
# 但是如果运行的话就会报错,会提示没有定义

函数定义与调用:

  1. 函数必须先定义后调用(顺序不能乱),没有事先定义函数而直接调用,就相当于在引用一个不存在的’变量名’,会提示没有定义。
  2. 函数在定义阶段只检测语法不执行代码
  3. 函数在调用阶段才会执行函数体代码

3. 函数的分类

  • 内置函数

    python中自带的函数,直接调用就行。

  • 自定义函数

    程序员自己定义的函数,又分为:

    • 无参函数

      def my_print_v1(): 
          print("hello")
      
    • 有参函数

      # 传一个参数
      def my_print_v2(name):
          print("hello, %s" % name)
          return 0
      # 传两个参数
      def sum(a, b):
          sum = a + b
          return sum
      
    • 空函数

      def run():
          pass
      
      # 空函数本身没有含义 但是空函数可以提前规定好编写代码的思路
      

3.1 函数的返回值

  1. 函数体代码没有return关键字
    默认返回None
  2. 函数体代码只有关键字return后面没有跟内容
    默认也是返回None
    函数体代码遇到return立刻结束
  3. 函数体代码有关键字return并且后面跟了数据
    跟了什么就返回什么
    如果跟了多个数据逗号隔开会自动组织成元组返回

3.2 函数练习:

# 简单的注册和登录
import os

userFile = "user.txt"
if not os.path.exists(userFile):
    with open(userFile, 'w', encoding='utf8') as f:
        pass

# 用户输入
def userInput():
    username = input("请输入用户名>>>:").strip()
    password = input("请输入用户密码>>>:").strip()
    return username, password


# 用户注册
def userSignup(username, password):
    with open(userFile, 'r', encoding='utf8') as f:
        for i in f:
            if username == i.split("|")[0]:
                print("用户名已存在,请重新输入")
                break
        else:
            # temp = username + "|" + password
            temp = "%s|%s" % (username, password)

            with open(userFile, 'a', encoding='utf8') as f:
                f.write(temp)
                f.write("\n")
            print('注册成功')


# 用户登录
def userlogin(username, password):
    with open(userFile, 'r', encoding='utf8') as f:
        for i in f:
            tempUser, tempPwd = i.split("|")
            if tempUser == username and tempPwd.strip() == password:
                print("登录成功")
                break
        else:
            print("登录失败")


while True:
    print("""
        1. 用户注册
        2. 用户登录
        3. 退出系统
    """)
    choice = input("你选择的功能:").strip()
    if choice == '1':
        # 用户注册
        username, password = userInput()
        userSignup(username, password)
    elif choice == '2':
        # 用户登录
        username, password = userInput()
        userlogin(username, password)
    elif choice == '3':
        print("退出系统")
        break
    else:
        print("没有该功能")

4. 函数参数

image

4.1 函数参数的分类

函数的参数分为形式参数和实际参数,简称形参和实参.

  • 形参:

    在函数定义中出现的参数可以看做是一个占位符,它没有数据,只能等到函数被调用时接收传递进来的数据,所以称为形式参数,简称形参

    简单来说,在函数定义阶段括号内所填写的参数就是形参

    def func1(arg1,arg2):
        pass
    
    # arg1和arg2就是形参
    
  • 实参:

    函数被调用时给出的参数包含了实实在在的数据,会被函数内部的代码使用,所以称为实际参数,简称实参

    简单来说,在函数调用阶段括号内传入的参就是实参。

    def func1(arg1,arg2):
        print(arg1, arg2)
    # 函数调用:
    func1("Hello", "Hi")
    Hello Hi
    
    # "Hello" 和 "Hi" 就是实参
    

形参和实参的区别和联系:

  1. 形参变量只有在函数被调用时才会分配内存,调用结束后,立刻释放内存,所以形参变量只有在函数内部有效,不能在函数外部使用。

  2. 实参可以是常量、变量、表达式、函数等,无论实参是何种类型的数据,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形参,所以应该提前用赋值、输入等办法使实参获得确定值。

  3. 实参和形参在数量上、类型上、顺序上必须严格一致,否则会发生“类型不匹配”的错误。当然,如果能够进行自动类型转换,或者进行了强制类型转换,那么实参类型也可以不同于形参类型。

  4. 函数调用中发生的数据传递是单向的,只能把实参的值传递给形参,而不能把形参的值反向地传递给实参;换句话说,一旦完成数据的传递,实参和形参就再也没有瓜葛了,所以,在函数调用过程中,形参的值发生改变并不会影响实参。

4.2 位置参数与关键字参数

  1. 位置参数

    按照从左往右的顺序依次填入的参数。

  2. 位置形参

    在函数定义阶段括号内按照从左往右的顺序依次填入的变量名

  3. 位置实参

    在函数调用阶段括号内按照从左往右的顺序依次传入的数据值

示例:

def func1(arg1, arg2):   # 定义了函数名为func1,它需要两个参数(形参)var1和var2
    print("arg1=%s arg2=%s" % (arg1, arg2))
    
    
func1("Hello", "Hi")  # 给函数传两个参数(实参),其实hello就对应arg1, Hi为arg2,如果Hello和Hi的位置调换则arg1为Hi,arg2为Hello
# 执行结果:
arg1=Hello arg2=Hi

func1("Hello")  # 只传一个参数(少传一个参数)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: func1() missing 1 required positional argument: 'arg2'
>>> func1("Hello", "Hi", "Ha")  # 传三个参数(多传一个参数)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: func1() takes 2 positional arguments but 3 were given
    
# 关键字参数
func1(arg2="Haha", arg1="Heihei")  #直接指定,这样可以不关心它的位置   
# 执行结果:
Heihei Haha

在调用函数,指定的实际参数的数量,必须和形式参数的数量一致(传多传少都不行),否则 Python 解释器会抛出 TypeError 异常,并提示缺少必要的位置参数。

4.3 默认参数

在定义函数时,直接给形式参数指定一个默认值。这样的话,即便调用函数时没有给拥有默认值的形参传递参数,该参数可以直接使用定义函数时设置的默认值。

def signUp(name, age, gender="M"):
    print(name, age, gender)

signUp("Lucy", 18, "F")  # 给gender传值则gender为传的值。如,F

name = "Hans"
age = 18
signUp(name, age)    # 不给gender传值则gender为默认的值。M

# 执行结果:
Lucy 18 F
Hans 18 M

def signUp(name, age, gender="M"):
    print(name, age, gender)
    
name = "Hans"
age = 18

signUp(gender="F", name, age)
执行结果:
signUp(gender="F", name, age)
                      ^
SyntaxError: positional argument follows keyword argument  # 报错,位置参数跟在了关键参数后面

注意: 位置形参与默认值形参在定义的时候,位置形参必须在默认值形参的前面。

4.3.1 默认参数难点

难点1

# 代码:
def func(name, age, hobby=[]):
    hobby.append(age)
    print('%s:%s:%s' % (name, age, hobby))

func('Hans', 18)
func('Jack', 20)
func('Tony', 22)
# 执行结果:
Hans:18:[18]
Jack:20:[18, 20]
Tony:22:[18, 20, 22]
# 本来想第一个给name,第二个给age,后面列表把age添加过去,元素里面只有一个元素。但打印结果不符合预期
# 如果想打印预期结果则:
def func(name, age, hobby=[]):
    hobby.append(age)
    print('%s:%s:%s' % (name, age, hobby))

func('Hans', 18,[])
func('Jack', 20,[])
func('Tony', 22,[])
# 打印结果:
Hans:18:[18]
Jack:20:[20]
Tony:22:[22]
        
或者:
def func(name, age, hobby=[]):
    hobby=[]
    hobby.append(age)
    print('%s:%s:%s' % (name, age, hobby))

func('Hans', 18)
func('Jack', 20)
func('Tony', 22)
#执行结果:
Hans:18:[18]
Jack:20:[20]
Tony:22:[22]

原因:默认形参如果绑定的是一个列表 那么指向的是固定的一个地址,即它们三个共用一个列表地址,后面两个则是给列表重新赋了个地址。

难点2

# 代码:
m = 200
def func(a, b, c=m):
    print(a, b, c)
m = 400
func(1, 2) 
# 执行结果:
1 2 200
# 结果为200,不是后面定义的400。

原因:默认值形参在函数定义阶段就已经固定死了,不会随着后续的变化而变化,即在定义def func(a, b, c=m)c已经等于200了。后面的m为多少都和c没有关系了。也可以简单理解为:变量名与值的绑定关系,m200绑定了,然后c等于mc200绑定上了, 后面m等于400就和前面的200断了关系,但c依然和200绑定。

4.4 可变长参数

image

前面介绍过,在调用函数,指定的实际参数的数量,必须和形式参数的数量一致(传多传少都不行),如果想在函数调用时无论传几个参数函数都能正常运行,则到用可变长参数

可变长位置参数

# 代码:
def func1(*args):
    print(args)

func1()
func1(1)
func1('a','b','c')

# 执行结果:
()
(1,)
('a', 'b', 'c')

# 使用长变长参数*args在函数中表示接收多余的位置参数,并组织成元组的形式赋值给*号后面的变量名

def func1(a, b, *args):
    print(a, b, args)

func1(1, 2)
func1(1, 2, 3)
func1(1, 2, 3, 4)

# 执行结果:
1 2 ()
1 2 (3,)
1 2 (3, 4)

# 如果不给参数:
# 代码:
def func1(a, b, *args):
    print(a, b, args)

func1()
# 执行结果:
func1()
TypeError: func1() missing 2 required positional arguments: 'a' and 'b'
# 虽然使用了可变长参数,但是可变长参数前面还有两个位置形参,它们两个必须要传值,所以不传值则报错

# 如果可以变长参数在定义时在前面。
# 代码:
def func1(*args, a, b):
    print(args, a, b)

func1(1, 2, 3)
# 执行结果:
    func1(1, 2, 3)
TypeError: func1() missing 2 required keyword-only arguments: 'a' and 'b' # 传的值都给了可变长参数args, a 和 b没有值,则报错。
# 如果可变长参数一定在前面,则传参:
def func1(*args, a, b):
    print(args, a, b)

func1(1, a=2, b=3)
# 执行结果:
(1,) 2 3

#推荐把可以变长参数放在最后面。

使用长变长参数*args在函数中表示接收多余的位置参数,并组织成元组的形式赋值给 *号后面的变量名

可变长关键字参数

函数无论传入多少关键字参数都可以正常运行。

# 代码:
def func1(**kwargs):
    print(kwargs)

func1()
func1(name="Hans", age=18)

# 执行结果:
{}
{'name': 'Hans', 'age': 18}

# 位置形参+可变长关键字参数
# 代码
def func1(a,**kwargs):
    print(a,kwargs)

func1(1)  
func1("hello", name="Hans", age=18)

# 执行结果:
1 {}
hello {'name': 'Hans', 'age': 18}

# 上面函数传参时,形参a的值必须要传

# 一个函数无论传入多少位置参数和关键字参数都可以正常运行
# 代码:
def func1(*args,**kwargs):
    print(args,kwargs)

func1()
func1("Hi")
func1(a=1,b=2)
func1("hello","Hi","Haha", name="Hans", age=18, gender='m')
# 执行结果:
() {}
('Hi',) {}
() {'a': 1, 'b': 2}
('hello', 'Hi', 'Haha') {'name': 'Hans', 'age': 18, 'gender': 'm'}

**用于接收多余的关键字参数 并组织成字典的形式赋值给**号后面的变量名

把列表/字典中的元素当成参数一次性赋值

# 把列表的每个元素都传给函数
# 代码:
def func1(*args):
   print(args)

list1 = [1, 2, 3, 4, 5, 6]
func1(list1)

# 执行结果:
([1, 2, 3, 4, 5, 6],)
# 上面的结果把整个列表给了函数,成为一个参数,这个不符合要求。

# 修改:
def func1(*args):
   print(args)


list1 = [1, 2, 3, 4, 5, 6]
func1(*list1)   # 在列表前面加个*号
# 执行结果:
(1, 2, 3, 4, 5, 6)   #把列表中的每个元素,分开传给了函数

# *号在实参中的使用: 会将列表、元组内的元素打散成位置参数的形式一一传值


# 把字典的每个键值对传给函数
# 代码:
def func1(**kwargs):
   print(kwargs)

dict1= {"name":"Hans", "age":18}
func1(**dict1)
# 执行结果:
{'name': 'Hans', 'age': 18}

# **号在实参中的使用,会将字典内的键值对打散成关键字参数传入

可变长形参 ***后面的变量名其实是可以随便定义的,但是python中推荐使用:

*args

**kwargs

4.5 其他函数参数补充

命名关键字参数

# 代码:
def signUp(name, age, *, sex, weight):
    print(name, age, sex, weight)

signUp("Hans", 18, sex='M', weight=180)  # sex和weght在传入实参的时候必须以关键字参数的形式

# 执行结果:
Hans 18 M 180

# def signUp(name, age, *, sex, weight) # 这种函数传值时,sex和weght在传入实参的时候必须以关键字参数的形式,即:sex='M', weight=180方式

5. 名称空间/命名空间

5.1 什么是名称空间

A namespace is a mapping from names to objects.Most namespaces are currently implemented as Python dictionaries

命名空间是从名称到对象的映射。大多数名称空间目前都是作为Python字典实现的。简单来说,名称空间用于存放变量名与变量值绑定关系的地方。

5.2 名称空间的分类

  • 内置名称(built-in names), Python 语言内置的名称,python解释器提前给定义好的,比如函数名 abs、char 和异常名称 BaseException、Exception 等等。
  • 全局名称(global names),模块中定义的名称,记录了模块的变量,包括函数、类、其它导入的模块、模块级的变量和常量。
  • 局部名称(local names),函数中定义的名称,记录了函数的变量,包括函数的参数和局部定义的变量。(类中定义的也是)
img

命名空间的生命周期:

命名空间的生命周期取决于对象的作用域,如果对象执行完成,则该命名空间的生命周期就结束。

存活周期

  1. 内置名称空间
    python解释器启动与关闭而创建和销毁
  2. 全局名称空间
    随着py文件的运行与结束而创建和销毁
  3. 局部名称空间
    随着函数体代码的执行与结束而创建和销毁
# 代码:
len = 2  # 全局空间

def func1():
    len = 3  # 局部空间
    print("func1:", len)
func1()   # 会打印 len 为3
print(len) #  会打印 len 为2

# 执行结果:
func1: 3
2

5.3 查找顺序

Python中名称空间查找顺序:局部的命名空间去 -> 全局命名空间 -> 内置命名空间

命名空间查找时,还要看自己当时在哪里。

# 代码:
x = 1
def foo1():
    x = 2
    def foo2():
        x = 3
        print(x)
    foo2()
foo1()
# 执行结果:
	3
    
# 如果把foo2()中的x=3删除
# 代码:
x = 1
def foo1():
    x = 2
    def foo2():
        print(x)
    foo2()
foo1()
# 执行结果:
	2
    
# 把foo1()中的x=2删除:
# 代码:
x = 1
def foo1():
    def foo2():
        print(x)
    foo2()
foo1()
# 执行结果:
1
5.3.1 查找顺序难点

难点1

# 代码:
1  x = 1
2  def foo1():
3      def foo2():
4          print(x)
5          x = 2
6      foo2()
7
8  foo1()


# 执行结果:
Traceback (most recent call last):
  File "j.py", line 8, in <module>
    foo1()
  File "j.py", line 6, in foo1
    foo2()
  File "j.py", line 4, in foo2
    print(x)
UnboundLocalError: local variable 'x' referenced before assignment
# 为什么会报错,一般会认为x = 2,或者x为全局的值,x = 1

原因:函数在定义阶段名字的查找顺序就已经固定死了,它里面已经定义了x = 2了,所以函数认为有值了,不会找全局空间的值,但是在打印的时候在x=2赋值前,还没有赋值就打印了,违背了先定义再使用,所以会报错。

难点2

# 代码:
x  = 111
def func():
    def index():
        print(x)
    index()
    
x = 222
func()
# 执行结果:
222

image

5.4 名称空间作用域

什么是作用域?

名称空间所能够作用的范围.

  • 内置名称空间

    程序任何阶段任何位置均可使用(全局有效)

  • 全局名称空间

    程序任何阶段任何位置均可使用(全局有效)

  • 局部名称空间

    默认情况下只在各自的局部名称空间中有效

5.5 global 和nonlocal关键字

global

正常情况下全局名称空间里定义的变量,在局部名称空间里是不能修改的。

# 代码:
x = 1
def foo():
    x  = 2
foo()
print(x)

# 执行结果:
1

如果要在局部名称空间里修改全局名称空间定义的变量,则要使用关键字global来完成。

# 代码:
x = 1
def foo():
    global x #局部修改全局变量 需要使用关键字声明
    x  = 2
foo()
print(x)

#执行结果:
2

但是如果全局名称空间定义的是一个可变类型(集合,字典等),则可以直接修改

# 代码:
list1 = [1, 2, 3]
def foo():
   list1.append(4) 

foo()
print(list1)
# 执行结果:
[1, 2, 3, 4]

如果想在局部修改全局数据:

  • 如果数据为不可变类型需要关键字global声明
  • 如果数据为可变类型则无需关键字global声明

nonlocal

内部局部名称空间是没有办法修改外部名称空间定义的变量。

# 代码:
def foo():
   x = 1
   def my_foo():
       x = 2
    
   my_foo()
   print(x)
foo()
#执行结果:
1

如果要修改则使用nonlocal关键字

# 代码:
def foo():
   x = 1
   def my_foo():
       nonlocal x
       x = 2
   my_foo()
   print(x)
foo()
#执行结果:
2

如果外部局部名称空间是可变类型,则可以直接修改

# 代码:
def foo():
   list1 = ['a', 'b', 'c']
   def my_foo():
       list1.append("d")
   my_foo()
   print(list1)
foo()
# 执行结果:
['a', 'b', 'c', 'd']

内部的局部修改外部局部定义的变量:

  • 不可变类型数据,需要关键字nonlocal声明

  • 可变类型数据,不需要关键字nonlocal声明

6. 函数对象(函数名)的使用方法

函数名遇到括号就会调用

6.1 函数名可以给变量名赋值

# 代码:
def foo():
   print("Hello, foo")

func = foo   #函数foo赋值给func变量
func()   #其实它调用的就是foo()函数

# 执行结果:
Hello, foo

6.2 函数名还可以当做函数的实参

# 代码:
def foo():
   print("Hello, foo")


def func(args):
    print(args)
    args()
    print("Hello, func")

func(foo)   # 把foo当成一个参数传给func函数

# 执行结果:
<function foo at 0x7f795eec0f28>  # 打印foo函数的内存地址
Hello, foo
Hello, func

6.3 函数名还可以当做函数返回值

# 代码:
def foo():
   print("Hello, foo")

def func():
    print("Hello, func")
    return foo

res = func()   # 把 foo函数当返回值,赋值给了res
res()    # 执行函数

print("res:", res)
print("foo:",foo)

# 执行结果:
Hello, func
Hello, foo
res: <function foo at 0x7ff32f39af28>
foo: <function foo at 0x7ff32f39af28>
#  res 和 foo打印相同的内存地址,res就是foo

6.4 函数名可以当做容器类型(内部可以存放多个数据)的元素

1. 函数当元素的时候只写函数名,不调用(不加())
# 代码:
def foo():
   print("Hello, foo")

def func():
   print("Hello, func")

list1 = [1, 2, foo, func]
print(list1)
# 执行结果:
[1, 2, <function foo at 0x7fb4d67ccf28>, <function func at 0x7fb4d66ed268>]
# 函数没有加()即没有调用,列表中为它们的内存地址。


2. 函数没有返回值,当元素的时候函数调用(加())
# 代码:
def foo():
   print("Hello, foo")

def func():
   print("Hello, func")

list1 = [1, 2, foo(), func()]
print(list1)
# 执行结果:
Hello, foo
Hello, func
[1, 2, None, None]
# 函数加()就是调用,所以会先执行函数代内的代码,然后列表里是函数的返回值,没有写return则返回None

3. 函数有返回值,当元素的时候函数调用(加())
# 代码:
def foo():
   print("Hello, foo")
   return 3

def func():
   print("Hello, func")
   return 4

list1 = [1, 2, foo(), func()]
print(list1)
# 执行结果:
Hello, foo
Hello, func
[1, 2, 3, 4]
# 函数加()就是调用,所以会先执行函数代内的代码,然后列表里是函数的返回值,所以分别是3 和4

利用函数名可以当做容器类型的元素,示例:

# 代码:
def signUp():
    print("注册")

def logIn():
    print("登录")

def shopping():
    print("购物")

def listShop():
    print("查看")

shop_dict = {
        '1':signUp,
        '2':logIn,
        '3':shopping,
        '4':listShop
        }

while True:
    print(
    """
    1. 注册
    2. 登录
    3. 购物
    4. 查看
    """)

    choice = input("Please your choice:").strip()
    
    if choice in shop_dict:
        funcName = shop_dict.get(choice)
        funcName()

    else:
        print("暂时没有该功能")

# 执行代码:
[root@hans_tencent_centos82 tmp]# python3 l.py 

    1. 注册
    2. 登录
    3. 购物
    4. 查看
    
Please your choice:1
注册

    1. 注册
    2. 登录
    3. 购物
    4. 查看
    
Please your choice:2
登录

    1. 注册
    2. 登录
    3. 购物
    4. 查看
    
Please your choice:3
购物

    1. 注册
    2. 登录
    3. 购物
    4. 查看
    
Please your choice:4
查看

    1. 注册
    2. 登录
    3. 购物
    4. 查看
    
Please your choice:5
暂时没有该功能

    1. 注册
    2. 登录
    3. 购物
    4. 查看
    
Please your choice

7. 函数嵌套

7.1 函数嵌套定义

函数内部定义其他函数

def shop_site(num):
    def signUp():
        print("注册")

    def logIn():
        print("登录")

    def shopping():
        print("购物")

    def listShop():
        print("查看")
        
    if num == '1':
        signUp()
    elif num == '2':
        logIn()
    elif num == '3':
        shopping()
    elif num == '4': 
        listShop()
        
shop_site('1')

# shop_site()函数内容定义了四个不同的函数,可以将复杂的功能全部隐藏起来,暴露一个简单的接口

7.2 函数嵌套调用

函数嵌套调用:函数内部调用其他函数

# 代码:
def foo():
    print("Hello foo()")

def func():
    foo()   # 在func()里调用foo()
    print("Hello func()")

func()

#执行结果:
Hello foo()
Hello func()
posted on 2021-11-12 16:37  Hans_Wang  阅读(161)  评论(0编辑  收藏  举报

回到顶部