首页 > 技术文章 > 06 python开发之函数

caojiaxin 2020-12-12 20:56 原文

06 python开发之函数

目录

6 函数

6.1 基本使用

6.1.1 基本概念

  • 函数就是用来盛放代码的容器

    ​ 具备某一功能的工具-->工具

    ​ 实现准备好工具的过程-->函数的定义

    ​ 遇到应用场景,拿来就用

  • 使用函数可以解决代码可读性差以及拓展性差的问题

  • 先定义后引用

6.1.2 定义函数

  • 定义函数的语法
def 函数名(参数1,参数2,...):
    """文档描述"""
    函数体
    return 值

# def: 定义函数的关键字;
# 函数名:函数名指向函数内存地址,是对函数体代码的引用。函数的命名应该反映出函数的功能;
# 括号:括号内定义参数,参数是可有可无的,且无需指定参数的类型;
# 冒号:括号后要加冒号,然后在下一行开始缩进编写函数体的代码;
# """文档描述""": 描述函数功能,参数介绍等信息的文档,非必要,但是建议加上,从而增强函数的可读性;
# 函数体:由语句和表达式组成;
# return 值:定义函数的返回值,return是可有可无的。
def say_hello():  # say_hello=函数的内存地址
    print("======")
    print("hello world")
    print("======")

print(say_hello)  # <function say_hello at 0x00000241DA0273A0>
say_hello()

x = 10            # x=10的内存地址
print(x)
  • 函数定义阶段与调用阶段发生的事情
# 函数定义阶段:只检测语法,不执行代码
def foo():
    xxx
    print('from foo')

# 函数调用阶段:执行函数体代码
foo()
  • 示例
示例1
def bar():
    print('from bar')

def foo():
    print('from foo')
    bar()

foo()		# from foo | from bar

示例二
def bar():
    print('from bar')
    foo()

def foo():
    print('from foo')

bar()		# from bar | from foo

示例三
def bar():
    print('from bar')
    foo()

bar()		# 报错,要先定义后引用

def foo():
    print('from foo')
  • 定义函数的三种形式

    • 无参函数
    # 无参函数
    def f1():
        print("hello")
        print("你好")
        print("Hi")
    f1()			# hello | 你好 | Hi
    
    
    def login():
        name = input('username>>>:').strip()
        pwd = input('password>>>:').strip()
        if name == "ccc" and pwd == '111':
            print('ok')
        else:
            print('error')
    
    login()			# username>>>:
    
    • 有参函数
    def login(name,pwd):
        if name == "ccc" and pwd == "123":
            print('ok')
        else:
            print('error')
    
    login("ccc","123")	# ok
    login("ccc","1234")	# error
    
    def f2(x, y):
        print(x)
        print(y)
    
    f2(111, 222)		# 111 | 222
    
    def add(x, y):
        print(x+y)
    
    add(10, 20)	        # 30
    add(30, 40)		# 70
    
    • 空函数
    def login():
        pass
    def transfer():
        pass
    def withdraw():
        pass
    def check_balance():
        pass
    

6.2 调用函数与函数返回值

6.2.1 调用函数三种形式

  • 语句形式
len("hello")
  • 表达式形式
res = len("hello") + 10
print(res)		      # 15
  • 函数调用作为参数的形式
def add(x, y):
    z = x + y
    return z

print(add(5, 5))	      # 10
res = add(add(1, 2), 3)
print(res)		      # 6

6.2.2 函数的返回值return(函数的产品)

  • return作用1:控制返回值
Ⅰ 没有return-->默认返回就是None
def func():
    print(111)

res = func()		      # 111
print(res)		      # None

Ⅱ return 值-->返回就是那一个值
def max2(x, y):
    if x > y:
        return x
    else:
        return y

res = max2(100, 200) * 5
print(res)		      # 1000

Ⅲ return 值1,值2,值3--->返回的是一个元组
def func():
    return [11, 22], 2, 3

res = func()
print(res, type(res))         # ([11, 22], 2, 3) <class 'tuple'>
  • return作用2:函数内可以有多个return,但只要执行一个就会立即种植函数的运行,并且会将return后的值当做本次调用的产品返回
def func():
    print(111)
    return 2201202
    print(2222)
    return 11112222
    print(3333)

res = func()
print(res)          # 111 2201202
  • return就是函数的处理结果

    函数内没有return关键字,或者说return后面没有值-->None

  • return 值
    return 值1,值2,值3--->(值1,值2,值3)

  • 可以有多个return,但只要执行一次整个函数就会立即结束,并且返回值

def f1():
    x = 10
    def f2():
        print('from f2')
    return f2

res = f1()  # 即res=f2的内存地址
print(res)  # <function f1.<locals>.f2 at 0x000001F5886D8700>
res()       # from f2

6.3 Type hinting

6.3.1 定义

  • python3新增类型提示功能,例如我们可以为函数增加类型提示信息,而不影响函数本身的执行:

  • 注释的一般规则是参数名后跟一个冒号(:),然后再跟一个expression,这个expression可以是任何形式。

6.3.2 使用

# Type hinting
def add(x: int, y: int) -> int:
    res = x + y
    return res

print(add.__annotations__)
# {'x': <class 'int'>, 'y': <class 'int'>, 'return': <class 'int'>}

6.4 函数参数

6.4.1 函数分类

  • 形参

    在定义函数时,在括号内指定参数/变量名,称之为形式参数,简称形参

    形参的本质就是变量名

  • 实参

    在调用函数时,括号内传入的值,称之为实际参数,简称实参

    实参的本质就是变量值

  • 实参与形参的关系

    在调用函数时,实参的值会绑定给形参,该绑定关系可以在函数内使用

    在函数调用结束后,会解除绑定关系

6.4.2 参数详解

6.4.2.1 位置形参

  • 在定义函数时,按照从左往右的顺序依次定义的变量名,称之为位置形参

  • 特点:必须被传值,多一个少一个都不行

def func(x, y):
    print(x, y)
func(1, 2)
func(1, 2, 3)       # 报错
func(1)             # 报错

6.4.2.2 位置实参

  • 在调用函数时,按照从左往右的顺序依次传入的值,称之为位置实参

  • 特点:按照位置与形参一一对应

def func(x, y):
    print(x, y)
func(1, 2)
func(2, 1)

6.4.2.3 默认形参

  • 在定义函数时就已经为某个形参赋值了,该形参就称为默认参数

  • 特点:在调用阶段可以不用为默认形参传值

def func(x, y=111):
    print(x, y)
func(1, 2)          # 1 2
func(1)             # 1 111
def register(name, age, gender="male"):
    print(name, age, gender)
register("egon", 18)
register("lxx", 38)
register("hxx", 32, "female")
register("李建国", 30)
register("alex", 31)
register("xxx", 18)

# egon 18 male
# lxx 38 male
# hxx 32 female
# 李建国 30 male
# alex 31 male
# xxx 18 male

6.4.2.4 关键字实参

  • 在调用函数时,按照key=value的形式指定的实参,称之为关键字实参

  • 特点:可以打乱顺序,仍能指名道姓为指定的形参赋值

def func(x, y=2222):
    print(x, y)
func(y=222, x=1212)       # 1212 222
func(x=111)               # 111 2222

6.4.3 实参的混用

  • 位置实参和关键字实参可以混用,注意点:

    Ⅰ 位置实参必须放在关键字实参前面

    Ⅱ 不能为同一个形参重复赋值

def func(x, y=2222):
    print(x, y)
func(1, y=2)              # 1 2
func(y=2, 1)              # 报错
func(1, y=2, x=3)         # 报错

6.4.4 形参的混用

  • 位置形参和默认形参可以混用,注意点:

    位置形参必须放在默认形参前面

def func(x, y=111):
    print(x, y)

def func(y=111, x):     # 报错
    print(x, y)

6.4.5 默认形参使用的注意点

  • 默认形参的值最好是不可变类型
m = 222
def func(x, y=m):
    print(x, y)
m = 666
func(111)               # 得到111 222
def register(name,hobby,hobbies=[]):
    hobbies.append(hobby)
    print('%s 的爱好是 %s' %(name, hobbies))
def register(name, hobby, hobbies=None):
    if hobbies is None:
        hobbies=[]
    hobbies.append(hobby)
    print('%s 的爱好是 %s' %(name, hobbies))
register("egon", "smoke")
register("lxx", "dance")
register("hxx", "drink")

6.5 可变长函数(*与**的应用)

6.5.1 由来

  • 可变长函数是指在调用函数时,传入参数个数不固定,而实参是为形参赋值的

  • 因此必须有对应格式的形参来接受溢出的实参

6.5.2 在形参中使用

6.5.2.1 *args的使用

  • 在形参中带*,*会将溢出的位置实参汇总成元组,然后赋值给其后变量名args
def func(x, y, *z):
    print(x, y, z)
func(1, 2, 3, 4, 5)      # 1 2 (3, 4, 5)
func(1, 2)               # 1 2 ()
func(1)                  # 报错

def my_sum(*args):
    res = 0
    for i in args:
        res += i
    print(res)
my_sum(1)               # 1
my_sum(1, 2)            # 3
my_sum(1, 2, 3)         # 6

6.5.2.2 **kwargs的使用

  • 在形参中带**,**通常会将溢出的关键字实参汇总成字典,然后赋值给其后变量名kwargs
def func(x, y, **kwargs):
    print(x, y, kwargs)
func(1, y=2, a=1, b=2, c=3)        # 1 2 {'a': 1, 'b': 2, 'c': 3}

6.5.3 在实参中使用

6.5.3.1 *的使用

  • 在实参中带*:*会将紧跟其后的实参打散成位置实参
  • 注意*后跟的应该是一个可以被for循环循环的类型
def func(a, b, c, d):
    print(a, b, c, d)
func(*"hello")                          # 报错,不对应
func(*"hell")                           # h e l l
func(*[11, 22, 33, 44])                 # 11 22 33 44
func(11, 22, *[33, 44])                 # 11 22 33 44
func(11, 22, *{"k1": 111, "k2": 222})   # 11 22 k1 k2

6.5.3.2 **的使用

  • 在实参中带**

推荐阅读