• 函数


    函数定义:

    函数(Functions)是指可重复使用的程序片段。
    它们允许你为某个代码块赋予名字,允许你通过这一特殊的名字在你的程序任何地方来运行代码块,并可重复任何次数。这就是所谓的调用(Calling)函数
    函数能提高应用的模块性,和代码的重复利用率。Python提供许多内建函数,比如print(),len()等。但自己创建函数,这被叫做用户自定义函数。
     函数创建规则:
            只能通过关键字def来定义。这一关键字后跟一个函数的标识符名称(函数名),再跟一对圆括号,其中可以包括一些变量的名称,再以冒号结尾,结束这一行
        
         函数名:函数名只能包含字符串、下划线和数字且不能以数字开头。虽然函数名可以随便起,还是要尽量简短,并能表达函数功能
      
         # 必须注释:每一个函数都应该对功能和参数进行相应的说明,应该写在函数下面第一行。以增强代码的可读性。
    1 def say_hello():
    2 # 该块属于这一函数
    3  print('hello world')
    4 # 函数结束
    5 say_hello() # 调用函数
    6 say_hello() # 再次调用函数

    5.1 return关键字的用法

        return,即“返回”的意思,用于从函数中返回,也就是中断函数,可以选择在中断函数时从函数中返回一个值。
    作用:
    1,在函数中,遇到return结束函数。
    2,将值返回给函数的调用者。
     
     要研究返回值,还要知道返回值有几种情况:分别是没有返回值、返回一个值、返回多个值

    5.1.1 没有返回值:

      每一个函数都在其末尾隐含了一句  return None,不写return的情况下,会默认返回一个None:
    #函数定义
    def mylen():
        """计算s1的长度"""       
        s1 = "hello world"
        length = 0
        for i in s1:
            length = length+1
        print(length)    
    
    #函数调用
    str_len = mylen()     #11
    #因为没有返回值,此时的str_len为None
    print('str_len : %s'% str_len)

    5.1.2 return可用来结束整个函数 (看着好像是函数里面有return的时候,调用函数的时候才需要打印的)

      如果 return 语句没有搭配任何一个值则代表着 返回 None 。 None 在 Python 中一个特殊的类型,代表着虚无。

      举个例子, 它用于指示一个变量没有值,如果有值则它的值便是 None(虚无) 。

      每一个函数都在其末尾隐含了一句  return None  ,除非你写了你自己的  return  语句。

      这里我们要说一下return的其他用法,就是一旦遇到return,结束整个函数。

    def ret_demo():
        print(111)
        return         #注意,因为有return,这里只会返回‘111’,不会在进行下面的运算
        print(222)
    
    ret = ret_demo()
    print(ret)

     5.1.3返回一个值(该值是什么,直接返回给函数的调用者)

    #函数定义
    def mylen():
        """计算s1的长度"""
        s1 = "hello world"
        length = 0
        for i in s1:
            length = length+1       # 只会返回’11‘
        return length
    
    #函数调用
    str_len = mylen()
    print('str_len : %s'%str_len)

    5.1.4 返回多个值 (将多个值返回到一个元祖里面,返回给函数的调用者)

    def ret_demo1():
        '''返回多个值'''
        return 1,2,3,4          # 记住return后面多个值不需要括号的,另外返回的值都是元祖,而非字符串
    
    def ret_demo2(): '''返回多个任意类型的值''' return 1,['a','b'],3,4 ret1 = ret_demo1() print(ret1) ret2 = ret_demo2() print(ret2)

     5.1.5 多个返回值的接收:

    def ret_demo2():
        return 1,['a','b'],3,4
    
        #返回多个值,用一个变量接收
    ret2 = ret_demo2() print(ret2) #用多个值接收返回值:返回几个值,就用几个变量接收
    a,b,c,d = ret_demo2() print(a,b,c,d) ---(1, ['a', 'b'], 3, 4) #返回的是元祖类型 ---1 ['a', 'b'] 3 4

     5.2 函数参数

    形式参数(parameter) :函数定义过程中小括号里面的参数
    实际参数(argument) : 函数调用过程中传递进去的参数
    站在实参角度:
    1.按照位置传参
    def mymax(x,y):
        #此时x=10,y=20
        the_max = x if x > y else y
        return the_max
    
    ma = mymax(10,20)
    print(ma)
    
    
    2.按照关键字传参(函数调用过程中通过参数名制定需要赋值的参数)
    def mymax(x,y):
        #此时x = 20,y = 10
        print(x,y)
        the_max = x if x > y else y
        return the_max                                                    
                                                      #  对于一个形参只能赋值一次
    ma = mymax(y = 10,x = 20)
    print(ma)
    
    
    3.位置,关键字形式混着用
    def mymax(x,y):
        #此时x = 10,y = 20
        print(x,y)
        the_max = x if x > y else y
        return the_max
    
    ma = mymax(10,y = 20)          # 位置参数必须在关键字参数的前面
    print(ma)
    View Code

     站在形参角度:

    def lens(x):    # x即形参
        count = 0
        for j in x:
            count += 1
        return count
    x = 'dwdfefvwf'
    print(len(x))    # 此时传入的x为实际参数,相当于 'dwdfefvwf'
    View Code

    将变化较小的值设为默认参数:

    def stu_info(name,sex = "male"):
        """打印学生信息函数,由于班中大部分学生都是男生,
        所以设置默认参数sex的默认值为'male'
        """
        print(name,sex)          # 这结果有意思
    
    
    stu_info('alex')
    stu_info('eva','female')
    
    ---alex male
    ---eva female
    def defult_param(a,l = []):
        l.append(a)
        print(l)           # 这里的默认参数可变,有点像动态传递,a得到结果后又传递到了列表里面
    
    defult_param('alex')
    defult_param('egon')
    
    ---['alex']
    ---['alex', 'egon']
    通过在函数定义时附加一个赋值运算符( = )来为参数指定默认参数值
     默认参数应该是常数,即不可变
    def say(message, times=1):       #  只有那些位于参数列表末尾的参数才能被赋予默认参数值
            print(message * times)
    say('Hello')
    say('World', 5)
    
    ---Hello
    ---WorldWorldWorldWorldWorld

     关键字传参:

    如果你有一些具有许多参数的函数,而你又希望只对其中的一些进行指定,那么你可以通过命名它们来给这些参数赋值——这就是关键字参数(Keyword Arguments)
    优点:
    一,不再需要考虑参数的顺序,函数的使用将更加容易。
    二,可以只对那些我们希望赋予的参数以赋值,只要其它的参数都具有默认参数值。
    易错点:
    切记:默认参数必须要在可变参数的后面,否则会报错
    def func(a, b=5, c=10):
        print('a is', a, 'and b is', b, 'and c is', c)
    
    func(3, 7)
    func(25, c=24)
    func(c=50, a=100)
    
    ---a is 3 and b is 7 and c is 10
    ---a is 25 and b is 5 and c is 24
    ---a is 100 and b is 5 and c is 50

     5.3 可变参数(收集参数)

    *args在行形参中对应关系:

       位置参数,*args, 默认参数

    def func(a,b,c,*args,d = 2):
        print(a,b,c,args,d)
    
    func('s','w','d',5,8,21,3,15,'f')
    
    ---s w d (5, 8, 21, 3, 15, 'f') 2   # d = 2没有被覆盖,能打印出来
    
    
    
    def func(a,b,c,d = 2,*args):
        print(a,b,c,args,d)
    
    func('s','w','d',5,8,21,3,15,'f')  
    ---s w d (8, 21, 3, 15, 'f') 5     # d现在是5,打印结果在最后
    
    
    如果d = 2放在形参前面,则会报错

    **kwargs在形参中对应关系:

    最终顺序:位置参数,*args,默认参数,**kwargs
    def func(a,b,c,d,*args,e='',**kwargs):
        print(a,b,c,args,e,kwargs)  # 这里没有打印d值
    
    func(1,2,3,4,5,6,7,v=3,m=7,h=9,e='')  #d对应4
    ---1 2 3 (5, 6, 7) 女 {'v': 3, 'm': 7, 'h': 9}

    关于*args以及**kwargs的魔法应用

    def func(*args):
        print(args)
    l1 = [1,2,30]
    l2 = [1,2,33,21,45,66]
    tu = (1,2,3)
    
    func(1,2,30,1,2,33,'das',2,5,66)     ---(1, 2, 30, 1, 2, 33, 'das', 2, 5, 66)
    func(*'qweqrfdsaf')          ---('q', 'w', 'e', 'q', 'r', 'f', 'd', 's', 'a', 'f')
    func(*{'name':'alex',"age":12})   ---('name', 'age')
    func(*l1,*l2)                  ---(1, 2, 30, 1, 2, 33, 21, 45, 66)
    def func(**kwargs):
        print(kwargs)
    
    dic1 = {'name1':'alex','age1':46}
    dic2 = {'name':'老男孩','age':56}
    func(**dic1,**dic2)  ---{'name1': 'alex', 'age1': 46, 'name': '老男孩', 'age': 56}

    从上面例子可以看出:

      针对*,打散(list,tuple,str,dict(键),将元素一一添加到args

      针对**,打散所有字典,并将所有键值对放到一个kwargs

    def total(a=5, *numbers, **phonebook):
        print('a', a)
    
        #遍历元组中的所有项目
        for single_item in numbers:
            print('single_item', single_item)
    
        #遍历字典中的所有项目
        for first_part, second_part in phonebook.items():
            print(first_part,second_part)
    
    print(total(10,1,2,3,Jack=1123,John=2231,Inge=1560))
    
    ---a 10
    ---single_item 1
    ---single_item 2
    ---single_item 3
    ---Inge 1560                         
    ---John 2231
    ---Jack 1123
    ---None

     如果有搜集参数,后面还有其他参数,则建议使用默认参数:

    def test(*params, exp = 8):
        print ("参数长度是:", len(params),exp)
        print ("第二个参数是:",params[1])
    
    test(1,"cedf",74,415,6)
    
    ---参数长度是: 5 8
    ---第二个参数是: cedf

    5.4局部变量与全局变量

    命名空间的分类
      1)、全局命名空间( Global):每个模块加载执行时创建的,记录了模块中定义的变量,包括模块中定义的函数、类、其他导入的模块、模块级的变量与常量。
      2)、局部命名空间(Local):每个函数所拥有的命名空间,记录了函数中定义的所有变量,包括函数的入参、内部定义的局部变量。
      3)、python内置命名空间(Built-in):任何模块均可以访问,放着内置的函数和异常(比如:input,print,str,list,tuple...)。
     
    空间加载顺序
         Built-in(程序运行前进行加载)   >    Global(程序运行中:从上到下加载)    >   Local(程序运行中:调用时才加载)
    取值顺序
      在局部调用:局部命名空间-->全局命名空间-->内置命名空间
      在全局调用:全局命名空间-->内置命名空间
    综上所述,在寻找变量时,从小范围,一层一层到大范围去找寻。
    # 在全局是无法查看全局的,但是通过局部可以查看全局
    max=1 def f1(): max=2 def f2(): max=3 print(max) f2() f1() print(max)
     
    变量作用域
            对于函数而言,函数内的名字只是在函数运行时才会被创建,在函数运行之前或者运行之后根本不存在。函数运行结束时,所有名字都不存在。
    两个常用的内置函数
      locals() 和globals(),它们提供了基于字典的访问局部和全局变量的方式。
      1)、locals():函数会以字典类型返回当前位置的全部局部变量。
      2)、globals():函数会以字典类型返回当前位置的全部全局变量。
    #在函数局部作用域内
    name = 'wusir'
    def func():
        name = 'alex'
        print(globals())
        print(locals())     #{'name': 'alex'}
    func()
    #输出结果:
    {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__':
    <_frozen_importlib_external.SourceFileLoader object at 0x000002397E843FD0>, '__spec__': None, '__annotations__': {},
    '__builtins__': <module 'builtins' (built-in)>, '__file__': 'd:/python10/day10/homework.py', '__cached__': None, 'name': 'wusir',
    'func': <function func at 0x000002397CA62E18>}
    {'name': 'alex'}
    关键字(global 与 nonlocal)的作用
    global的作用
      1)、声明一个全局变量
      2)、在局部作用域想要对全局作用域的全局变量进行修改时,需要用到 global
    def func():
        global a
        a = 2               #用以声明a是一个全局变量
        print(a)     
    
    func()     #2                 
    print(a) #2      #从这个结果可以看出来a现在属于全局变量
    
    #输出结果
    2 2

    对可变数据类型(list,dict,set)可以直接引用不用通过global:

    li = [1,2,3]
    dic = {'a':'b'}
    def change():
        li.append('a')
        dic['q'] = 'g'
        print(dic)          #{'a': 'b', 'q': 'g'}
        print(li)              #[1, 2, 3, 'a']
    change()
    print(li)              #[1, 2, 3, 'a']
    print(dic)              #{'a': 'b', 'q': 'g'}
     nonlocal的作用
      1)、不能修改全局变量
      2)、在局部作用域中,对父级作用域(或者更外层作用域非全局作用域)的变量进行引用和修改,并且引用到哪层,从那层及以下此变量全部发生改变
    def add_b():
        b = 42
        def do_global():
            b = 10
            print(b)   #10
            def dd_nonlocal():
                nonlocal b
                b = b + 20
                print(b)   #30 
            dd_nonlocal()
            print(b) #30 
         do_global()
         print(b) #42
    add_b()
    #输出结果
    10 30 30 42

     函数的嵌套使用:

    def fun1():
        print('fun1()正在被调用')
        def fun2():                                  #注意缩进
            print('fun2()正在被调用')           
        fun2()
    
    fun1()
    
    ---fun1()正在被调用
       fun2()正在被调用
    
    def fun1():
        print(111)
    
    def fun2():
        print(222)
        fun1()
    fun2()
    #输出结果
    222
    111
     函数的作用域链:小范围作用域可以使用大范围的变量,但是反之不行,它是单向的。
    print(111)          #执行顺序--1
    def fun2():
        print(222)      #执行顺序--3
        def fun3():
            print(666)  #执行顺序--5
        print(444)      #执行顺序--4
        fun3()
        print(888)      #执行顺序--6
    print(333)          #执行顺序--2
    fun2()
    print(555)          #执行顺序--7   #函数看着有点绕,仔细分析缩进及自上而下的调用过程
    
    #输出结果
    111 333 222 444 666 888 555

    相关作业:

    2、写函数,检查获取传入列表或元组对象的所有奇数位索引对应的元素,并将其作为新列表返回给调用者。

    def key(s):
        a = s[1::2]
        return a
    
    print(key([1, 5, 8, 8, 9, 11, 11]))
    print(key(('d', 'a', 'e', 'e')))

    3、写函数,判断用户传入的对象(字符串、列表、元组)长度是否大于5。

    def stuff(x):
        return '大于5' if len(x) > 5 else '小于5'
    
    print(stuff(('w', 'd', 'w', 'l' 'e')))
    print(stuff([15,54,5,3,15,35]))
    print(stuff('dewfwegw'))

    4、写函数,检查传入列表的长度,如果大于2,那么仅保留前两个长度的内容,并将新内容返回给调用者。

    def stuff(x):
        a = x[:2] if len(x) > 2 else x
        return a  # 和上面这一步可以合并
    print(stuff([15,41,56,4,56,4,1,5]))
    
    
    def stuff(x):
        return x[:2]
    print(stuff([15,41,56,4,56,4,1,5]))

    5、写函数,计算传入字符串中【数字】、【字母】、【空格] 以及 【其他】的个数,并返回结果。

    # 一般遇到计算当中某个元素出现次数,下面的编程思想可得记住了
    def stuff(x):
        num = 0
        alpha = 0
        space = 0
        other = 0
        for i in x:
            if i.isdigit():
                num += 1
            elif i.isalpha():
                alpha += 1
            elif i.isspace():
                space += 1
            else:
                other += 1
        print('num:{}个
    alpha:{}个
    space:{}个
    other:{}个'.
              format(num, alpha, space, other))
    
    stuff('dwwf few#@%6 564def 156we')
    
    def func(stuff):
        a = {'num': 0, 'alpha': 0, 'space': 0, 'other': 0}
        for element in stuff:
            if element.isdigit():
                a['num'] += 1
            elif element.isalpha():
                a['alpha'] += 1
            elif element.isspace():
                a['space'] += 1
            else:
                a['other'] += 1
        return '数字%d,字母%d,空格%d,其他%d' % (a['num'],
                    a['alpha'], a['space'], a['other'])
    
    print(func('fdsafd  1232432@#$%^fdf123   哈佛撒旦'))

    7、写函数,检查传入字典的每一个value的长度,如果大于2,那么仅保留前两个长度的内容,并将新内容返回给调用者。

       dic = {"k1": "v1v1", "k2": [11,22,33,44]}

       PS:字典中的value只能是字符串或列表

    def dics(dic):
        for k in dic:
            if len(dic[k]) > 2:
                dic[k] = dic[k][:2]
            else:
                dic[k] = dic[k]
        return dic    # 注意这个缩进位置
    
    print(dics({"k1": "v1v1", "k2": [11,22,33,44]}))
    
    
    def dics(dic):
        for k in dic:
            dic[k] = dic[k][:2]
        return dic
    
    print(dics({"k1": "v1v1", "k2": [11,22,33,44]}))

    8、写函数,接收两个数字参数,返回比较大的那个数字。

    def max_num(a, b):
        return a if a > b else b
    
    print(max_num(3, 5))

    9、写函数,用户传入修改的文件名,与要修改的内容,执行函数,完成整个文件的批量修改操作(进阶)。

    # 这个对原文件全部给清空了,然后输入新内容了。
    # 如果题目要求只是追加的话就不好了.那么需要在创建一个文件
    from os import rename
    def load_in(content, file_name):
        with open('a.txt', mode='w', encoding='gbk') as f:
            f.write(content)
        rename('a.txt', file_name)   # 这个缩进注意啦,麻痹的研究了好久原来这里错了
    
    load_in('吃葡萄不吐葡萄皮', 'bb.txt')

    10、写一个函数完成三次登陆功能,再写一个函数完成注册功能(进阶)

    # 用户注册
    li = []
    def register():
        username = input('请输入你的注册名:').strip()
        with open('register_msg.txt', encoding='gbk') as f:
            for line in f:
                names = line.strip().split()
                li.append(names[0])
        if username in li:
            print('你所注册的用户名已存在,请重新输入')
            return register()
        else:
            password = input('请输入你的注册密码:').strip()
            with open('register_msg.txt', encoding='gbk', mode='a') as f1:
                f1.write('
    {}	{}'.format(username, password))
                print('注册成功')
    
    register()
    
    
    # 用户登陆
    def func():  # 用户选择登陆还是注册函数
        choice = input('选择登陆/0还是注册/1:').strip()
        if choice == '1':
            register()       # 执行注册函数
        elif choice == '0':  # 执行登陆
            times = 0
            while times < 3:
                times += 1
                def fun1():  # 登陆函数
                    username = input('请输入你的用户名:').strip()
                    password = input('请输入密码:').strip()
                    with open('register_msg.txt', encoding='gbk') as f:
                        for line in f:   # 打开文件,读取每行
                            li = line.strip().split()   # 对每行切割,得到列表
                            if username == li[0] and password == li[1]:    # 判断用户名是否在文件内
                                print('登陆成功')
                                while True:  # 登陆成功后,继续选择登陆注册或者退出
                                    choice = input('请选择登陆还是注册/1还是退出/2:').strip()
                                    if choice == '1':
                                        return func()  # 返回,继续执行上面函数
                                    elif choice == '2':
                                        exit()
                                    else:
                                        print('你输入的有误,请重新输入')
                        else:
                            print('你的输入有误')
                fun1()   # 执行fun1登陆函数
                if times == 3:
                    print('你输入的次数已用完')
                    exit()
    
        else:
            print('你输入的包含非法字符,重新输入')
    func()   # 调用登陆or注册函数
     
  • 相关阅读:
    ccr1
    与非CCR代码互操作
    ccr test
    CCR
    tpl + ccr
    TPL
    利用 Rational ClearCase ClearMake 构建高性能的企业级构建环境
    Android错误:Re-installation failed due to different application signatures
    C 单例模式
    C 工厂模式 还有其他的模式
  • 原文地址:https://www.cnblogs.com/LearningOnline/p/8457443.html
Copyright © 2020-2023  润新知