python 之用户自定义函数

什么是函数?

函数无非就是将代码块进行封装,想用的时候拿来用,减少代码量,提高效率。

函数的定义

定义一个函数需要:

1.def关键字,def 后面空一格输入函数名称,函数命名时尽量简短,且具有意义,能通过函数名窥见该函数实所实现的功能,函数名称后面紧跟着一对英文圆括号()和英文冒号:

def关键字、函数名、括号、冒号缺一不可

2.括号里面存放参数,根据需要可传可不传

3.一般使用三重引号注释函数所实现功能,并放于第一行(根据编码者习惯可写可不写)

4.冒号以下都是函数内容

5.return 可写可不写,根据实际情况,若不填写时,该函数无返回值

def my_fun(parameters):
    """
    实现XXXXX功能
    :return:
    """
    Function body

    return expression

定义一个简单的函数

def marks():
    """
    分数校验
    :return:
    """
    mark = float(input("请输入分数:"))
    if mark < 60:
        return False
    else:
        return True

函数定义后不会执行,需要调用才会去执行

 函数的调用

def sub(a, b):
    """
    实现减法
    :param a:
    :param b:
    :return:
    """
    return a - b


result = sub(2, 5)
print(result)
"D:\Program Files\Python\Python37-32\python.exe" D:/demo/funtion_1.py
-3

或者由其他函数调用执行

import random
import string
import hashlib


def random_str(number):
    """
    生成随机码
    :param number:
    :return:
    """
    code = ''.join(random.sample(string.digits + string.ascii_letters, int(number)))
    return code


def md5_str(number):
    """
    md5加密
    :param number:
    :return:
    """
    md5_data = hashlib.md5()
    md5_data.update(random_str(number).encode())  # 调用random_str()函数生成随机数
    sign = md5_data.hexdigest()
    return sign


if __name__ == '__main__':
    string = md5_str(8)
    print(string)
"D:\Program Files\Python\Python37-32\python.exe" D:/demo/funtion_1.py
345b36fc3ee89f786bc122cb3f8c26f2

参数使用

上面的例子中已用到了参数,在python实际使用中,参数分为形参、实参

形参:定义函数时传递的参数

实参:调用函数时传递的参数

def len_str(data):  # 形参 data
    """
    获取字符串长度
    :param data:
    :return:
    """
    count = 0
    for i in data:
        count += 1
    return count


print(len_str("If you plant a melon, you get a melon"))  # 传入实参
"D:\Program Files\Python\Python37-32\python.exe" D:/demo/funtion_1.py
37

位置参数(必备参数)

调用时传入的参数必须与声明中的参数一一对应,包括位置、数量、参数类型

def max_data(da):
    """
    获取列表中最大值
    :param da:
    :return:
    """
    for i in range(len(da) - 1):
        for j in range(len(da)-1 - i):
            if da[j] > da[i]:
                temp = da[j]
                da[j] = da[j+1]
                da[j+1] = temp
    return da[len(da) - 1]


print(max_data())
"D:\Program Files\Python\Python37-32\python.exe" D:/demo/funtion_1.py
Traceback (most recent call last):
  File "D:/demo/funtion_1.py", line 63, in <module>
    print(max_data())
TypeError: max_data() missing 1 required positional argument: 'da'
def student(name, age):
    stu = {"张三": 19, "李四": 20, "王二": 19, "麻子": 20}
    for key, value in stu.items():
        if name == key and age == value:
            return "该考生存在"
     

print(student(19, "王二"))  # name 对应19, age 对应王二
"D:\Program Files\Python\Python37-32\python.exe" D:/demo/funtion_1.py
查无此人
def student(name, age):
    stu = {"张三": 19, "李四": 20, "王二": 19, "麻子": 20}
    for key, value in stu.items():
        if name == key and age == value:
            return "该考生存在"


print(student("王二", 19))  # name 对应王二, age 对应19
"D:\Program Files\Python\Python37-32\python.exe" D:/demo/funtion_1.py
该考生存在

关键字参数

关键字参数是指在调用时,使用形参名+传入的参数值(parameter1=value1,parameter2=value2),使用关键字参数时不需要与声明中的位置对应

def student(name, age):
    stu = {"张三": 19, "李四": 20, "王二": 19, "麻子": 20}
    for key, value in stu.items():
        if name == key and age == value:
            return "该考生存在"


print(student(age=19, name="王二"))  # name、age 位置可不对应
"D:\Program Files\Python\Python37-32\python.exe" D:/demo/funtion_1.py
该考生存在

位置参数与关键字参数混合使用

混合使用时,位置参数一定要在关键字参数前,不然程序报错,不可执行

def student(name, age):
    stu = {"张三": 19, "李四": 20, "王二": 19, "麻子": 20}
    for key, value in stu.items():
        if name == key and age == value:
            return "该考生存在"


print(student(age=19, "王二"))  # 当关键字参数在位置参数前时抛出"位置参数必须在关键字参数前"
  File "D:/demo/funtion_1.py", line 73
    print(student(age=19, "王二"))  # 当关键字参数在位置参数前时抛出"位置参数必须在关键字参数前"
                         ^
SyntaxError: positional argument follows keyword argument
def student(name, age):
    stu = {"张三": 19, "李四": 20, "王二": 19, "麻子": 20}
    for key, value in stu.items():
        if name == key and age == value:
            return "该考生存在"


print(student("王二", age=19,))
"D:\Program Files\Python\Python37-32\python.exe" D:/demo/funtion_1.py
该考生存在

关键字参数与位置参数混合使用,容易出现一个坑,TypeError: xxxxx() got multiple values for argument xxxxx'

def student(name, age):
    stu = {"张三": 19, "李四": 20, "王二": 19, "麻子": 20}
    for key, value in stu.items():
        if name == key and age == value:
            return "该考生存在"


print(student(19, name="王二"))
"D:\Program Files\Python\Python37-32\python.exe" D:/demo/funtion_1.py
Traceback (most recent call last):
  File "D:/demo/funtion_1.py", line 73, in <module>
    print(student(19, name="王二"))
TypeError: student() got multiple values for argument 'name'

默认参数

 默认参数是指在定义时传入参数值,调用时未传入参数则使用默认传入的参数值,否则使用调用传入的参数值


def marks(mark=60):
    mar = float(input("请输入你的分数"))
    if mar > mark:
        return "及格线为: %s, 你及格了" % mark
    else:
        return "及格线为: %s, 你需要补考" % mark


print(marks(85))  # 传入参数,此时使用调用时传入的参数值
"D:\Program Files\Python\Python37-32\python.exe" D:/demo/funtion_1.py
请输入你的分数80
及格线为: 85, 你需要补考
def marks(mark=60):
    mar = float(input("请输入你的分数"))
    if mar > mark:
        return "及格线为: %s, 你及格了" % mark
    else:
        return "及格线为: %s, 你需要补考" % mark


print(marks())  # 不传入参数,此时使用定义时传入的参数值
"D:\Program Files\Python\Python37-32\python.exe" D:/demo/funtion_1.py
请输入你的分数80
及格线为: 60, 你及格了

动态参数

动态参数又称为不定长参数,在使用时,根据需要可以传入任意个参数,动态参数有两种形式,*args, **kwargs,参数间的位置排序为:位置参数、默认参数、*args动态参数、**kwargs动态参数、关键字参数

*args: 表示接受任意多个实际参数将其放到一个元组中,如果参数是个列表,会将整个列表当做一个参数传入

def marks(*args):
    print(args)
    for i in args:
        print(i)


(marks(["张三", "李四", "王二", "麻子"], [50, 50, 70, 90]))
"D:\Program Files\Python\Python37-32\python.exe" D:/demo/funtion_1.py
(['张三', '李四', '王二', '麻子'], [50, 50, 70, 90])
['张三', '李四', '王二', '麻子']
[50, 50, 70, 90]

以上是将列表当成一个参数,若要分解成多个参数,调用时可以在参数前加 *,也称为解包(适用于任何序列类型数据对象)

def marks(*args):
    print(args)
    for i in args:
        print(i)


(marks(*["张三", "李四", "王二", "麻子"], *[50, 50, 70, 90]))
"D:\Program Files\Python\Python37-32\python.exe" D:/demo/funtion_1.py
('张三', '李四', '王二', '麻子', 50, 50, 70, 90)
张三
李四
王二
麻子
50
50
70
90
def marks(*args):
    print(args)
    for i in args:
        print(i)


(marks(*{"张三": 95, "李四": 20, "王二": 88, "麻子": 91}))  # 将字典中的key作为参数
('张三', '李四', '王二', '麻子')
张三
李四
王二
麻子

**kwargs:表示接受任意多个实际参数将其放到一个字典中,类似关键字参数

def marks(**kwargs):
    print(kwargs)
    for name, mark in kwargs.items():
        print(name, ":", mark)


(marks(张三=90, 李四=20))  # 通过关键字传入
"D:\Program Files\Python\Python37-32\python.exe" D:/demo/funtion_1.py
{'张三': 90, '李四': 20}
张三 : 90
李四 : 20
def marks(**kwargs):
    print(kwargs)
    for name, mark in kwargs.items():
        print(name, ":", mark)


(marks(**{"张三": 95, "李四": 20, "王二": 88, "麻子": 91}))  # 通过字典传入,在参数前加入**,函数会把dict中所有键值对转换为关键字参数传进去
"D:\Program Files\Python\Python37-32\python.exe" D:/demo/funtion_1.py
{'张三': 95, '李四': 20, '王二': 88, '麻子': 91}
张三 : 95
李四 : 20
王二 : 88
麻子 : 91

*args, **kwagrs混合使用

def persons(name, age, *args, **kwargs):
    print(args)
    print(kwargs)
    infos = ''
    if "" in name or age < 20:
        if kwargs['address'] == "深圳":
            for info in args:
                infos += info
            for k, v in kwargs.items():
                print(name, "基础资料有", k, ":", v)
            print(name, "年龄在20的深圳小青年,其他信息有", infos)


persons("王二", 19, "文艺", "摇滚", address="深圳", job="student")
"D:\Program Files\Python\Python37-32\python.exe" D:/demo/funtion_1.py
('文艺', '摇滚')
{'address': '深圳', 'job': 'student'}
王二 基础资料有 address : 深圳
王二 基础资料有 job : student
王二 年龄在20的深圳小青年,其他信息有 文艺摇滚

 函数变量作用域

根据变量的定义位置,决定变量的作用范围

局部变量:定义在函数内部的变量,只在函数内部有效,执行完后,局部变量会被释放,无法再次访问

全局变量:定义在整个文件层次上,可以在整个程序范围内访问

def sum(a, b):
    count = a + b
    return count  # count 局部变量


print(sum(1, 4))
"D:\Program Files\Python\Python37-32\python.exe" D:/demo/funtion_1.py
5
guess = -10   # 全局变量


def compare():
    times = 3
    while times > 0:
        value = float(input("请输入你所猜数字, 你还有%s次机会" % times))
        if value == guess:
            return "恭喜,猜对啦"
        else:
            times -= 1
    return "很遗憾,你的次数用完啦"


print(compare())
"D:\Program Files\Python\Python37-32\python.exe" D:/demo/funtion_1.py
请输入你所猜数字, 你还有3次机会3
请输入你所猜数字, 你还有2次机会0
请输入你所猜数字, 你还有1次机会9
很遗憾,你的次数用完啦

尝试在函数内修改全局变量

guess = -10   # 全局变量


def compare():
    times = 3
    while times > 0:
        value = float(input("请输入你所猜数字, 你还有%s次机会" % times))
        if value == guess:
            return "恭喜,猜对啦"
        else:
            guess = 1
            times -= 1
    return "很遗憾,你的次数用完啦"


print(compare())
"D:\Program Files\Python\Python37-32\python.exe" D:/demo/funtion_1.py
请输入你所猜数字, 你还有3次机会24
Traceback (most recent call last):
  File "D:/demo/funtion_1.py", line 135, in <module>
    print(compare())
  File "D:/demo/funtion_1.py", line 127, in compare
    if value == guess:
UnboundLocalError: local variable 'guess' referenced before assignment

在函数内部修改全局变量报错了,这是因为,Python 的解释器会默认函数内部的变量为局部变量,然而局部变量 guess 又没有声明,因此就无法执行相关操作。那么如果要在函数内更改全局变量呢?

这里可以引入 global

def compare():
    global guess
    print("修改前的谜底:%s" % guess)
    times = 3
    while times > 0:
        value = float(input("请输入你所猜数字, 你还有%s次机会" % times))
        if value == guess:
            return "恭喜,猜对啦"
        else:
            guess = 1
            times -= 1
    return "很遗憾,你的次数用完啦", "此时谜底为:%s" % guess


print(compare())
"D:\Program Files\Python\Python37-32\python.exe" D:/demo/funtion_1.py
修改前的谜底:-10
请输入你所猜数字, 你还有3次机会64
请输入你所猜数字, 你还有2次机会978
请输入你所猜数字, 你还有1次机会3
('很遗憾,你的次数用完啦', '此时谜底为:1')

函数嵌套

函数嵌套是指函数里面又存在函数,经典案例递归

def factorial_calculation():
    number = int(input("请输入整数"))
    if number <= 0:
        return "请输入大于0的正整数"

    def factorial(number):
        if number <= 1:
            return 1
        return number * factorial(number-1)
    return factorial(number)


print(factorial_calculation())
"D:\Program Files\Python\Python37-32\python.exe" D:/demo/funtion_1.py
请输入整数6
720

 

posted @ 2020-12-30 18:41  **绵绵羊**  阅读(684)  评论(0编辑  收藏  举报