函数

在这里插入图片描述

一. 函数简介

  • 函数也是一个对象
  • 函数用来保存一些可执行的代码,并且可以在需要时,对这些语句进行多次调用
    语法
    def 函数名([形参1,形参2,形参3…]):
           代码块
    注意:
    函数名必须符合标识符的规范(可以包含字母、数字、下划线_,但是不能以数字开头)
    print是函数对象 print()是调用函数

示例

# 函数简介
def fun():
    print("这是我的第一个函数")
    
    
fun()

# 函数对象: fun
# 调用函数: fun()

二. 函数的参数

1 形参和实参

  • 形参(形式参数) 定义形参就相当于在函数内部声明了变量,但是并不是赋值
  • 实参(实际参数)指定了形参,那么在调用函数时必须传递实参,实参将会赋值给对应的形参,简单来说,有几个形参就要有几个实参
# 函数的参数
def fun(a, b):  # a,b 叫做形参
    print(a + b)


fun(1, 2)  # 1,2 叫做实参
# 3

2 函数的传递方式

  • 定义形参时,可以为形参指定默认值。指定了默认值以后,如果用户传递了参数则默认值不会生效。如果用户没有传递,则默认值就会生效
  • 位置参数:位置参数就是将对应位置的实参赋值给对应位置的形参
  • 关键字参数 : 关键字参数可以不按照形参定义的顺序去传递,而根据参数名进行传递
  • 混合使用位置参数和关键字参数的时候必须将位置参数写到关键字参数前面

示例1

# 参数的传递方式
def fun1(a, b=0, c=0):  # b=0, c=0 给形参指定默认值,当没有传递实参,使用默认值;当传递了参数,使用传递进来的参数
    print(a)
    print(b)
    print(c)


fun1(1, 2)
'''
1
2
0
'''

示例2

# 参数的传递方式
# 位置传参
def fun1(a, b, c):
    print(a)
    print(b)
    print(c)


fun1(1, 2, 3)
'''
1
2
3
'''

示例3

# 参数的传递方式
# 关键字传参
def fun1(a, b, c):
    print(a)
    print(b)
    print(c)


fun1(a=1, c=2, b=3)
'''
1
3
2
'''

示例4

# 位置传参和关键字传参混合使用,位置传参必须放到关键字传参的前面
def fun1(a, b, c):
    print(a)
    print(b)
    print(c)


fun1(1, b=2, c=3)
'''
1
2
3
'''

示例5

def fun1(a):
    a = 10
    print(a)


b = 1
fun1(b)
print(b)
'''
10
1
'''


def fun2(a):  # a = b = [1, 2, 3]
    a[0] = 10  # a[0] = 10 -> a =b = [10, 2, 3]
    print(a)   # a = b = [10, 2, 3]


b = [1, 2, 3]  # b被改为了[10, 2, 3],不想改b的值,定义c = b.copy(),函数调用c:fun2(c)
fun2(b)
print(b)
'''
[10, 2, 3]
[10, 2, 3]
'''

3 不定长参数

  • 定义函数时,可以在形参前面加一个*,这样这个形参可以获取到所有的实参,它会将所有的实参保存到一个元组中
  • 带*号的形参只能有一个,可以和其他参数配合使用
  • 形参只能接受位置参数,不能接受关键字参数
  • **形参可以接收其他的关键字参数,它会将这些参数统一保存到字典当中。字典的key就是参数的名字,字典的value就是参数的值
  • **形参只有一个,并且必须写在所有参数的后面

示例

# 不定长参数
def fun1(a, *b, c):  # 位置传参的不定长参数:只能存在一个参数有*号,可以和其他的传参方式一起配合使用,
    print(b)  # 位置参数必须放在不定长参数前面
    r = 0  # 不定长参数*b要放到关键字传参的前面
    for i in b:
        r += i
    print(r)


fun1(1, 2, 3, c=4)
'''
(2, 3)
5'''


def fun2(h, i, j, **d):  # 关键字传参的不定长参数
    print(d)  # 位置参数必须放在不定长参数前面
    # 关键字传参要放到不定长关键字参数之前


fun2(4, 5, e=1, f=2, g=3, j=6)
'''
{'e': 1, 'f': 2, 'g': 3}'''


def fun3(*i, j, **d):  # 关键字传参的不定长参数
    print(i, d, j)  # 位置参数必须放在不定长参数前面
    # 关键字传参要放到不定长关键字参数之前


fun3(4, 5, e=1, f=2, g=3, j=6)
'''(4, 5) {'e': 1, 'f': 2, 'g': 3} 6'''


def fun4(*i, **d):  # (万能参数)
    print(i, d)  


fun4(4, 5, e=1, f=2, g=3, j=6)
'''(4, 5) {'e': 1, 'f': 2, 'g': 3, 'j': 6}'''


def fun5(*args, **kwargs):  # 不定长参数标准写法
    pass

4 参数的解包

  • 传递实参时,也可以在序列类型的参数前添加*号,这样它会自动的将序列中元素依次作为参数传递
  • 要求序列中的元素的个数必须和形参的个数一致

示例

# 参数的拆包

def fun1(a, b, c):
    print(a)
    print(b)
    print(c)


tuple1 = (1, 2, 3)
fun1(tuple1[0], tuple1[1], tuple1[2], )
'''
1
2
3'''
fun1(*tuple1)  # 简便方法
'''
1
2
3'''
dict1 = {'a':1,'b':2,'c':3}
fun1(**dict1)  # 简便方法
'''
1
2
3'''

5. 函数的返回值

  • 返回值就是函数执行以后返回的结果
  • 通过return来指定函数的返回值
  • return后面可以跟任意对象,返回值甚至可以是一个函数

示例

# 函数的返回值
def fun1(*args):  # 函数内的变量或执行结果,想要直接到函数外面去使用是不行的
    r = 0
    for i in args:
        r += i
    print(r)
    return r  # 返回了r的值,但是外面不能使用r这个名字 函数的返回值可以返回任何类型的数据


res = fun1(1, 2, 3)
print(res)  # 函数的调用获得了函数返回值的结果
'''
6
6'''


def fun2(*args):
    def fun3():
        pass
    return fun3  # 返回函数的内存地址


res = fun2()   # fun2() = fun3  调用fun3的话:fun2()() = fun3(), 相当于res()
print(res)  # <function fun2.<locals>.fun3 at 0x00000000028ED678>
print(res())  # None  调用fun3()的结果是None
# 一个函数要想有返回值,必须写 return xxxx
# 如果没有return 或者 只有 return没返回对象,那么这个函数的返回值都是None


def fun4():
    print(1)
    return  # return后面的代码都不执行,看到return会直接退出函数
    print(2)


fun4()  
print(fun4())
'''
1
1
None'''

# 函数练习
def fun1(*args):
    r = 0
    for i in args:
        r += i
    print(r)


print(fun1(1+2, 3))
'''
6
None'''


def fun2(*args):
    r = 0
    for i in args:
        r += i
    print(r)
    return args


print(fun2(1+2, 3))
'''
6
(3, 3)'''

# 搞清楚4点:
# 1.函数的参数的传递
# 2.函数的调用
# 3.函数的返回值
# 4.函数的调用等于什么

6. 文档字符串

  • help()是Python中内置函数,通过help()函数可以查询Python中函数的用法
  • 在定义函数时,可以在函数内部编写文档字符串,文档字符串就是对函数的说明

示例

# 文档字符串
"""
# 长字符串
1.保留文档格式
2.作为一个多行注释
"""

# 文档字符串,就是对函数以及类进行说明,及参数、返回值的文档说明
def fun1(a, b):
    """

    :param a:
    :param b:
    :return:
    """

help(print)  # help(函数名)  查看函数说明
'''
print(...)
    print(value, ..., sep=' ', end='\n', file=sys.stdout, flush=False)
    
    Prints the values to a stream, or to sys.stdout by default.
    Optional keyword arguments:
    file:  a file-like object (stream); defaults to the current sys.stdout.
    sep:   string inserted between values, default a space.
    end:   string appended after the last value, default a newline.
    flush: whether to forcibly flush the stream.
'''

7. 函数的作用域

  • 作用域(scope)
    作用域指的是变量生效的区域
    在Python中一共有两种作用域
  • 全局作用域
    全局作用域在程序执行时创建,在程序执行结束时销毁
    所有函数以外的区域都是全局作用域
    在全局作用域中定义的变量,都是全局变量,全局变量可以在程序的任意位置进行访问
  • 函数作用域
    函数作用域在函数调用时创建,在调用结束时销毁
    函数每调用一次就会产生一个新的函数作用域
    在函数作用域中定义的变量,都是局部变量,它只能在函数内部被访问

示例

# 函数的作用域

a = 1  # 全局作用域


def fun1():
    a = 10  # 函数内作用域
    print(a)


fun1()
print(a)  # 1
'''
10
1
'''


a = 1  # 全局作用域
def fun2():
    a = 10  # 局部作用域,相对fun3是全局作用域
    print(a)
    def fun3():
        print(a)
    fun3()


fun2()
print(a)
'''
10
10
1
'''


a = 1  # 全局作用域
def fun4():
    global a   # 使局部作用域变为全局作用域的方法
    a = 15  # a被重新赋值为15
    print(a)
    def fun5():
        print(a)
    fun5()


fun4()
print(a)
'''
15
15
15'''

8. 命名空间

  • 命名空间实际上就是一个字典,是一个专门用来存储变量的字典
  • locals()用来获取当前作用域的命名空间
  • 如果在全局作用域中调用locals()则获取全局命名空间,如果在函数作用域中调用locals()则获取函数命名空间
  • 返回值是一个字典

示例

# 命名空间

a = 1
b = 2
c = 3
s = locals()  # 获取当前作用域的所有变量,并且以一个字典返回出来
print(s)
'''
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x00000000023F3288>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'F:/PycharmProjects/项目/test.py', '__cached__': None, 'a': 1, 'b': 2, 'c': 3, 's': {...}}'''

# 命名空间
a = 1
b = 2
c = 3


def fun1():
    a = 1
    b = 2
    s1 = locals()
    print(s1)
    pass


fun1()
s = locals()  # 获取当前作用域的所有变量,并且以一个字典返回出来
print(s)
'''
{'a': 1, 'b': 2}
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x0000000002423288>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'F:/PycharmProjects/项目/test.py', '__cached__': None, 'a': 1, 'b': 2, 'c': 3, 'fun1': <function fun1 at 0x0000000002804D38>, 's': {...}}'''
# 全部命名空间
a = 1
b = 2
c = 3


def fun1():
    d = 1
    e = 2
    # s = locals()  # 获取局部作用域的命名空间
    s = globals()  # 获取全局作用域的命名空间
    print(s)
    pass


fun1()
s = locals()  # 获取当前作用域的所有变量,并且以一个字典返回出来
print(s)
'''
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000000000205DBC8>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'F:/PycharmProjects/项目/test.py', '__cached__': None, 'a': 1, 'b': 2, 'c': 3, 'fun1': <function fun1 at 0x00000000020ED9D8>}
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000000000205DBC8>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'F:/PycharmProjects/项目/test.py', '__cached__': None, 'a': 1, 'b': 2, 'c': 3, 'fun1': <function fun1 at 0x00000000020ED9D8>, 's': {...}}'''

9. 递归函数

  • 递归是解决问题的一种方式,它的整体思想,是将一个大问题分解为一个个的小问题,直到问题无法分解时,再去解决问题
  • 递归式函数有2个条件
    1.基线条件: 问题可以被分解为最小问题,当满足基线条件时,递归就不执行了
    2.递归条件: 可以将问题继续分解的条件

示例1

# 递归函数
# 求取10的阶乘
# 1! = 1
# 2! = 1*2
# 3! = 1*2*3
n = 1
for i in range(1, 11):
    n *= i
print(n)  # 3628800


def fun1(n):
    r = 1
    for i in range(1, n + 1):
        r *= i
    return r


print(fun1(10))  # 3628800
# 以上都不是递归函数

示例2

# 递归函数简单理解是自己引用自己:递归函数就是在函数中自己调用自己
# 无穷递归
def fun2():
    fun2()


fun2()  # RecursionError: maximum recursion depth exceeded
# [Previous line repeated 996 more times]

# 递归的两个条件:
# 1.基线条件:问题可以被分解为最小的问题,当满足基线条件的时候,再去解决问题
# 2.递归条件:将问题继续分解的条件

示例3

# 递归函数
# 递归函数简单理解是自己引用自己:递归函数就是在函数中自己调用自己
# 递归的两个条件:
# 1.基线条件:问题可以被分解为最小的问题,当满足基线条件的时候,再去解决问题
# 2.递归条件:将问题继续分解的条件
# 求取10的阶乘
# 10! = 10 * 9!  # n! = n * (n-1)!  => fun(num) = n*fun(num-1)
# 9! = 9 * 8!
# 8! = 8 * 7!
# 1! = 1
def fun1(num):  # # fun(num)是为了求取num的阶乘
    if num == 1:
        return 1
    elif num > 1:
        # r = num * fun1(num - 1)  # TypeError: unsupported operand type(s) for *: 'int' and 'NoneType'
        return num * fun1(num - 1)
    # print(r)


print(fun1(10))  # 3628800
  • 递归函数练习:求任意数的任意次幂,判断字符串是否是回文字符串
# 递归函数练习
# 递归函数简单理解是自己引用自己:递归函数就是在函数中自己调用自己
# 递归的两个条件:
# 1.基线条件:问题可以被分解为最小的问题,当满足基线条件的时候,再去解决问题
# 2.递归条件:将问题继续分解的条件
# 求任意数的任意次幂
# 10 ** 5 = 10 * 10 **4
# 10 ** 4 = 10 * 10 **3
# 10 ** 3 = 10 * 10 **2
# 10 ** 2 = 10 * 10 **1

def fun1(a,b):
    if b == 1:
        return a
    elif b > 1:
        return a * fun1(a, b - 1)


print(fun1(10,5))  # 100000

# 求一个字符串是否是回文字符串
# 123456789987654321   12345678987654321
# 2345678998765432
# 34567899876543


def fun2(s):
    if len(s) < 2:
        return True
    elif s[0] != s[-1]:
        return False
    return fun2(s[1:-1])


print(fun2('34567899876543'))  # True
print(fun2('3456789876543'))  # True
print(fun2('34567891876543'))  # False

def fun3(s):
    if len(s) > 2 and s[::-1] == s:
        return True
    else:
        return False


print(fun3('34567899876543'))  # True
print(fun3('3456789876543'))  # True
print(fun3('1'))  # False

10. 高阶函数

  • 接收函数对象作为参数,或者将别的函数对象作为返回值返回的函数就是高阶函数
# 高阶函数
# 接收函数对象作为参数,或者将别的函数对象作为返回值返回的函数就是高阶函数
def fun1(i):
    if i % 2 == 0:
        return True


def fun2(fn):
    list1 = []
    for i in range(101):
        if fn(i):
            list1.append(i)
    return list1


print(fun2(fun1))
'''
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100]'''

11.匿名函数

  • 使用 lambda 来创建匿名函数。
    所谓匿名,就是不再使用 def 语句这样标准的形式定义一个函数。
  • lambda 只是一个表达式,函数体比 def 简单很多。
  • lambda的主体是一个表达式,而不是一个代码块。仅仅能在lambda表达式中封装有限的逻辑进去。
  • lambda 函数拥有自己的命名空间,且不能访问自己参数列表之外或全局命名空间里的参数。
  • 语法
    lambda 函数的语法只包含一个语句,如下:
    lambda [arg1 [,arg2,…argn]]:expression
# 匿名函数
# 所谓匿名,意即不再使用 def 语句这样标准的形式定义一个函数。
# 1.防止重名
# 2.不用再去定义函数,使用方便
# 3.可以作为一个传参工具
# lambda函数就是匿名函数
# 语法: lambda 参数:表达式
print((lambda a, b: a + b)(1, 2))  # 3

# filter(s, list1)  有两个参数,第一个参数是过滤规则,第二个是过滤的数据
list1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
s = lambda a: a % 2 == 0
print(list(filter(s, list1)))  # [2, 4, 6, 8, 10]

12. 闭包

  • 将函数作为返回值,也是高阶函数。我们也称为闭包
  • 闭包的好处
    1.通过闭包可以创建一些只有当前函数能访问的变量
    2.可以将一些私有数据藏到闭包中
  • 行成闭包的条件
    1.函数嵌套
    2.将内部函数对象作为返回值返回
    3.内部函数必须要使用到外部函数的变量

示例

# 闭包  特性:保证被内部使用的外部函数的变量或参数不被销毁
# 函数嵌套
# 将内部函数对象作为返回值返回
# 内部函数必须要使用到外部函数的变量

# 定义一个外部函数
def fun_out(num1):
    # 定义一个内部函数
    def fun_inner(num2):
        res = num1 + num2
        return res
    return fun_inner


# 函数的调用等于函数的返回值
f = fun_out(1)  # fun_out(1)() = fun_inner() = f()
# 内部函数的调用 fun_inner()
print(f(2))  # 3
print(f(3))  # 4


def fun_out1(num1):
    # 定义一个内部函数
    def fun_inner1(num2):
        num1 = 10  # 内部函数没有用到外部函数的变量,所以不是闭包
        res = num1 +num2
        return res
    print(num1)
    fun_inner1(1)
    print(num1)
    return fun_inner1


f1 = fun_out1(1)
'''
1
1
'''
print(f1(2))  # 12


def fun_out2(num1):
    # 定义一个内部函数
    def fun_inner2(num2):
        # global num1   # 修改全局变量没有意义,必须保证被内部使用的外部函数的变量或参数不被销毁
        nonlocal num1   # 告诉解释器,这里使用的不是本地的num1,是外部变量的num1   这样才是闭包
        num1 = 10
        res = num1 + num2
        return res
    print(num1)
    fun_inner2(1)
    print(num1)
    return fun_inner2


f2 = fun_out2(1)
'''
1
10
'''

13. 装饰器的引入

  • 我们可以直接通过修改函数中的代码来完成需求,但是会产生以下一些问题
    如果修改的函数多,修改起来会比较麻烦
    不方便后期的维护
    这样做会违反开闭原则(ocp)
    程序的设计,要求开发对程序的扩展,要关闭对程序的修改

示例1

# 装饰器的引入
# ocp原则,开放对代码的拓展,关闭对代码的修改的原则
def fun(fn):
    print("函数开始执行")
    fn()
    print("函数结束执行")


def fun1():
    print("我是fun1函数")


fun(fun1)
'''
函数开始执行
我是fun1函数
函数结束执行'''

示例2

# 装饰器的引入
def fun(fn, a, b):
    print("函数开始执行")
    r = fn(a, b)
    print(r)
    print("函数结束执行")


def add(a, b):
    return a + b


fun(add, 1, 2)
'''
函数开始执行
3
函数结束执行'''

示例3

# 装饰器的引入
def fun(fn, *args):
    print("函数开始执行")
    r = fn(*args)
    print(r)
    print("函数结束执行")


def add(a, b):
    return a + b


fun(add, 1, 2)
'''
函数开始执行
3
函数结束执行'''

14. 装饰器的使用

  • 通过装饰器,可以在不修改原来函数的情况下来对函数进行扩展
  • 在开发中,我们都是通过装饰器来扩展函数的功能的

示例1

# 装饰器的使用
# 装饰器是一个特殊的闭包函数
def start_fun(fn):
    def new_fun():
        print("函数开始执行")
        fn()
        print("函数结束执行")

    return new_fun


def fun():
    print("我是fun函数")


r = start_fun(fun)  # 首先是要调用外层函数,然后内层函数暂时是不会执行的,因为没有调用。然后外层函数的调用等于内层函数的返回值
# 那么现在外层函数的返回值就是就是内层函数的函数对象,内层函数的调用等于内层函数的函数对象加上一个括号,也就是调用,也就是r()
r()
'''
函数开始执行
我是fun函数
函数结束执行'''

示例2

# 装饰器的使用
# 装饰器是一个特殊的闭包函数
def start_fun(fn):
    def new_fun(c,d):
        print("函数开始执行")
        fn(c,d)
        print("函数结束执行")

    return new_fun


def fun(c,d):
    print("我是fun函数")


r = start_fun(fun)  # 首先是要调用外层函数,然后内层函数暂时是不会执行的,因为没有调用。然后外层函数的调用等于内层函数的返回值
# 那么现在外层函数的返回值就是就是内层函数的函数对象,内层函数的调用等于内层函数的函数对象加上一个括号,也就是调用,也就是r()
r(1,2)
'''
函数开始执行
我是fun函数
函数结束执行'''

示例3

# 装饰器的使用
# 装饰器是一个特殊的闭包函数
def start_fun(fn):
    def new_fun(*args,**kwargs):
        print("函数开始执行")
        fn(*args,**kwargs)
        print("函数结束执行")

    return new_fun


def fun(*args,**kwargs):
    print("我是fun函数")


r = start_fun(fun)  # 首先是要调用外层函数,然后内层函数暂时是不会执行的,因为没有调用。然后外层函数的调用等于内层函数的返回值
# 那么现在外层函数的返回值就是就是内层函数的函数对象,内层函数的调用等于内层函数的函数对象加上一个括号,也就是调用,也就是r()
r()   # 可以传任何参数进去
'''
函数开始执行
我是fun函数
函数结束执行'''

示例4

# 装饰器的使用
# 装饰器是一个特殊的闭包函数
def start_fun(fn):
    def new_fun(*args,**kwargs):
        print("函数开始执行")
        fn(*args,**kwargs)
        print("函数结束执行")

    return new_fun


@start_fun
def fun(*args,**kwargs):
    print("我是fun函数")


fun()

'''
函数开始执行
我是fun函数
函数结束执行'''

示例5

# 装饰器的使用
# 装饰器是一个特殊的闭包函数
def start_fun(fn):
    def new_fun(*args, **kwargs):
        print("函数开始执行")
        fn(*args, **kwargs)
        print("函数结束执行")

    return new_fun


@start_fun  # 装饰器的语法糖写法
def fun(*args, **kwargs):
    print("我是fun函数")
    print(*args, **kwargs)


fun(1, 2)

'''
函数开始执行
我是fun函数
1 2
函数结束执行'''

第八讲作业

1. 打印名片程序:输入姓名,电话号码,性别,最后打印出来名片
  • 控制姓名长度为6-20
  • 电话号码长度11
  • 性别只能允许输入男或女
  • 每一样信息不允许为空
'''
1. 打印名片程序:输入姓名,电话号码,性别,最后打印出来名片
控制姓名长度为6-20
电话号码长度11
性别只能允许输入男或女
每一样信息不允许为空
'''
# 方法1
while True:
    name = input('请输入姓名(长度为6-20个字符):')
    if 6 <= len(name) <= 20:
        while True:
            tel_num = input('请输入长度为11位的手机号码:')
            if tel_num.isdigit() and len(tel_num) == 11:
                while True:
                    sex = input('请输入性别(男或女):')
                    if sex == "男" or sex == "女":
                        print(
'''
********************************                             
     NB公司总经理:%s               
               %s                 
           %s                           
                                                                    
********************************
''' % (name, sex, tel_num))
                        break
                    elif sex == ' ':
                        print("你输入的性别不能为空,请重新输入")
                        continue
                    else:
                        print("你输入的性别不正确,请重新输入")
                        continue
                break
            elif tel_num == ' ':
                print("你输入的手机号码不能为空,请重新输入!")
                continue
            else:
                print("你输入的手机号码为:%s长度为:%s,不符合要求,请重新输入!" % (tel_num, len(tel_num)))
                continue
        break
    elif name == ' ':
        print("你输入的名字name不能为空,请重新输入!")
        continue
    else:
        print("你输入的姓名字符长度为:%s,不符合要求,请重新输入!" % len(name))
        continue
'''
********************************                             
     NB公司总经理:yangyu               
               男                 
           12345678901                           
                                                                    
********************************
'''
# # 方法2
# # 1. 打印名片程序:输入姓名,电话号码,性别,最后打印出来名片
# # - 控制姓名长度为6-20
# # - 电话号码长度11
# # - 性别只能允许输入男或女
# # - 每一样信息不允许为空


def input_name():
    name = input("请输入姓名(长度为6-20个字符):")
    if name == ' ':
        print("错误!输入的姓名不能为空!请重新输入!")
        return input_name()
    elif len(name) < 6:
        print("你输入的姓名长度为%s,过短!!!不符合要求,请重新输入!")
        return input_name()
    elif len(name) > 20:
        print("你输入的姓名长度为%s,过长!!!不符合要求,请重新输入!")
        return input_name()
    else:
        print("输入姓名格式正确")
        return name


def input_tel():
    tel_num = input("请输入11位手机号码:")
    if tel_num == ' ':
        print("你输入的手机号码为空,请重新输入")
        return input_tel()
    elif len(tel_num) != 11:
        print("你输入的手机号码长度不正确,请重新输入")
        return input_tel()
    elif tel_num[0] != "1":
        print("你输入的手机号码第1位必须是1开头,请重新输入")
        return input_tel()
    elif tel_num[1] != "3" and tel_num[1] != "5" and tel_num[1] != "7" and tel_num[1] != "8" and tel_num[1] != "9":
        print("你输入的手机号码第2位不正确,请重新输入")
        return input_tel()
    for i in range(3, 11):
        if tel_num[i] < "0" or tel_num[i] > "9":
            print("你输入的手机号码不正确,请重新输入")
            return input_tel()
    else:
        print("你输入的手机号码为%s" % tel_num)
        return tel_num


def input_sex():
    sex = input('请输入性别(男或女):')
    if sex == "男" or sex == "女":
        print("你输入的性别为:%s" % sex)
        return sex
    elif sex == ' ':
        print("你输入的性别不能为空,请重新输入")
        return input_sex()
    else:
        print("你输入的性别不正确,请重新输入")
        return input_sex()


print("""
*************************
    NB公司CEO:%s
           %s
       %s
*************************
        """ % (input_name(), input_sex(), input_tel()))
'''
*************************
    NB公司CEO:yangyu
           男
       17345678989
*************************
'''

2. 使用函数求前20个斐波那契数列斐波那契数列:1,1,2,3,5,8,13,21…即: 起始两项均为1,此后的项分别为前两项之和
# 方法1
# 使用函数求前20个斐波那契数列斐波那契数列:1,1,2,3,5,8,13,21...即: 起始两项均为1,此后的项分别为前两项之和
def num_list(num):
    list1 = [1, 1, 2]  # 定义列表的初始值
    n = 1
    while n < num:     
        m = list1[n] + list1[n + 1]  # m为下一项的值,等于前两项的和
        list1.append(m)              # 将m追加到list1当中
        n += 1
    list_20 = list1[0:num]  # 切片获取前20项
    print(list_20)          # 打印前20项


num_list(20)  # 调用函数,取前20项

[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765]

# 方法2
# 使用函数求前20个斐波那契数列斐波那契数列:1,1,2,3,5,8,13,21...即: 起始两项均为1,此后的项分别为前两项之和
def feibo(num):
    a, b = 1,1
    list1 = []
    for i in range(num):
        if i == 0:
            list1.append(a)
        if i > 0:
            a, b = b, a + b
            list1.append(a)
    print(list1)


feibo(20)
'''[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765]'''
3. 编写一段代码,定义一个函数求1-100之间所有整数的和,并调用该函数打印出结果
# 3. 编写一段代码,定义一个函数求1-100之间所有整数的和,并调用该函数打印出结果

def sum_num():
    sum_nums = 0
    for i in range(101):
        sum_nums += i
    print(sum_nums)


sum_num()  # 5050

第九讲作业

1. 用函数实现一个判断用户输入的年份是否是闰年的程序

1.能被400整除的年份
2.能被4整除,但是不能被100整除的年份
以上2种方法满足一种即为闰年

# 用函数实现一个判断用户输入的年份是否是闰年的程序
# 1.能被400整除的年份
# 2.能被4整除,但是不能被100整除的年份
# 以上2种方法满足一种即为闰年

year = int(input('请输入年份(如:2021):'))


def if_years(year):
    if (year % 4) == 0:
        if (year % 100) == 0:
            if (year % 400) == 0:
                print("{0} 是闰年".format(year))  # 整百年能被400整除的是闰年
            else:
                print("{0} 不是闰年".format(year))
        else:
            print("{0} 是闰年".format(year))  # 非整百年能被4整除的为闰年
    else:
        print("{0} 不是闰年".format(year))


if_years(year)
'''
请输入年份(如:2021):1800
1800 不是闰年
请输入年份(如:2021):1900
1900 不是闰年
请输入年份(如:2021):2000
2000 是闰年
'''



2. 猴子吃桃问题(递归):

猴子第一天摘下若干个桃子,当即吃了一半,还不瘾,又多吃了一个。第二天早上又将剩下的桃子吃掉一半,又多吃了一个。以后每天早上都吃了前一天剩的一半零一个。到第10天早上想再吃时,见只剩下一个桃子了,求第一天共摘了多少桃子?

# 猴子吃桃问题(递归):
# 猴子第一天摘下若干个桃子,当即吃了一半,还不瘾,又多吃了一个。第二天早上又将剩下的桃子吃掉一半,又多吃了一个。以后每天早上都吃了前一天剩的一半零一个。到第10天早上想再吃时,见只剩下一个桃子了,求第一天共摘了多少桃子?
#
# 逆向思维
# 第10天:1个桃
# 第9天: (剩的1个+多吃的1个) * 2
# 第8天: ((剩的1个+多吃的1个) * 2  + 1) * 2
# 第7天: (((剩的1个+多吃的1个) * 2  + 1) * 2 + 1) * 2
# f(n) = (f(n-1) + 1) * 2

def fun1(num):
    if num == 1:
        return 1
    else:
        return (fun1(num - 1) + 1) * 2


print(fun1(10))
# 1534   
# 妈耶,猴子第1天吃了700多个桃子不得撑死?
# 猴子这么能吃的话,到不了第十天就得饿死吧。


# while循环解决这个问题
def funtaozi(num):
    day = num
    res = 1
    while day > 1:
        res = (res + 1) * 2
        day -= 1
    return res


print(funtaozi(10))
# 1534

# for循环解决这个问题
res = 1
print('第10天吃之前就剩1个桃子')
for i in range(9, 0, -1):
    res = (res + 1) * 2
    print('第%s天吃之前还有%s个桃子' % (i, res))
print('第1天共摘了%s个桃子' % res)
'''
第10天吃之前就剩1个桃子
第9天吃之前还有4个桃子
第8天吃之前还有10个桃子
第7天吃之前还有22个桃子
第6天吃之前还有46个桃子
第5天吃之前还有94个桃子
第4天吃之前还有190个桃子
第3天吃之前还有382个桃子
第2天吃之前还有766个桃子
第1天吃之前还有1534个桃子
第1天共摘了1534个桃子'''

第十讲作业

1.请使用装饰器实现函数执行所花费的时间。使用time模块

# 1. 请使用装饰器实现函数执行所花费的时间。
import time


def time_decorator(fn):
    def elapsed_time(*args, **kwargs):
        print("开始的时间为%s" % time.asctime())
        fn(*args, **kwargs)
        print("开始的时间为%s" % time.asctime())

    return elapsed_time


@time_decorator
def add(num):
    sum_time = 0
    for i in range(num):
        sum_time += i
    print("计算%s次累加消耗的时间为:%s" % (num, time.process_time()))


add(100000000)
'''
开始的时间为Thu Mar 25 21:01:06 2021
计算100000000次累加消耗的时间为:9.9528638
开始的时间为Thu Mar 25 21:01:15 2021'''
Logo

聚焦前沿AI与大模型技术探索,汇聚开发者及爱好者,共享开源项目、学习资源与行业资讯。

更多推荐