zoukankan      html  css  js  c++  java
  • day04_雷神_函数

    day04


    1.函数

    1.1函数传参

    函数定义的时候是形参;函数执行的时候是实参

    实参:
    位置参数、关键字参数、混合参数

    位置参数:位置一一对应

    关键字参数: 可以位置不对应

    混合参数:关键字参数要在位置参数之后

    示例:(三元运算)
    def func(a,b): return a if a > b else 666
    ret = func(1,2)
    print(ret)  
    

    形参:位置参数、默认参数、动态参数

    位置参数: 一一对应

    默认参数:在位置参数后边,也是一个关键字的定义

    动态参数: *args 函数定义的时候聚合,生成一个元祖数据;函数执行的的时候打散元祖数据,形成位置参数。
    **kwargs 函数定义的时候聚合,将关键字参数聚合成一个字典数据,函数执行的时候打散这个字典数据,形成关键字参数。

    def func(*args,**kwargs):
        print(args)
        print(kwargs)
    func((1,2,3,4,),1,2,3,4)
    结果:
    ((1, 2, 3, 4), 1, 2, 3, 4)
    {}
    
    func(name= 'alex',age = '18')
    结果:
    ()
    {'name': 'alex', 'age': '18'}
    
    func(**{'name':'alex','age':'18'})
    结果:和上边关键字参数一样,区别是用**需要是字典格式
    ()
    {'name': 'alex', 'age': '18'}
    

    形参的顺序: 位置参数、*args、默认参数、**kwargs

    位置参数在最开始;默认参数如果在*args的前边,就不会起作用

    示例:
    def f(a,b,*args,sex = 'man'):
    	print(a,b,sex,args)
    f(1,2,3,4,5,6)
    结果:
    1 2 man (3, 4, 5, 6)
    
    def f(a,b,sex = 'man',*args):
    	print(a,b,sex,args)
    f(1,2,3,4,5,6)
    结果:
    1 2 3 (4, 5, 6)
    

    **kwargs就是接受的实参中的关键字参数,如果在默认参数前边,默认参数就接收不到,直接报错。

    正确示例:
    def func2(a,b,*args,sex='man',**kwargs):
    print(a,b)
    print(sex)
    print(args)
    print(kwargs)
    
    func2(1,2,3,55,66,age=12,sex='女',name='alex')
    结果:
    1 2
    女
    (3, 55, 66)
    {'age': 12, 'name': 'alex'}  kwargs会跳过默认参数,接受剩下的关键字参数
    

    1.2 函数名的应用

    • 1.打印函数名

    • 函数名表示函数的内存地址
      print(func1) function func1 at 0x000000000258F9D8>

    • 2.可以作容器类数据的元素

    • 示例:
      def func1():
      print(111)
      def func2():
      print(222)
      def func3():
      print(333)
      l1 = [func1, func2, func3]
      for i in l1:
      i()

    • 3.可以作为函数的参数

    • 4.可以作为函数的返回值

    • def func1():
      return 111
      def func2(x): # x = func1
      print(222)
      return x
      ret = func2(func1) # func1作为这个函数执行体得返回值,赋值给ret,ret()表示执行
      print(ret())
      print(ret)

      结果:
      222
      111
      <function func1 at 0x000001B4D91D1E18>

    像这样得函数名,又叫第一类对象。

    1.3闭包

    内层函数对外层函数非全局变量得引用,就叫做闭包。

    可以通过: 函数.__closure__来判断是不是闭包

    示例:
    name = 'alex'
    def  func1(x):  (相当于x = name,后边引用得是变量x)
    	def inner():
    	    print(x)
    	inner()
    print(inner.__closure__)  在inner()之后print。
    func1(name)
    
    结果:
    返回None不是闭包,一个带cell值得东西就是闭包。
    alex
    (<cell at 0x0000023CC8CC6588: str object at 0x0000023CC8C8B340>,)
    

    又一个机制:闭包得内容会留在内存中,不会随着函数得结束而释放,一段时间不用才会清空,可以在爬虫用。正常得函数,函数结束之后,他得临时名称空间就会结束。

    示例:
    from urllib.request import urlopen
    
    def index():
    	url = "http://www.xiaohua100.cn/index.html"
    	def get():
    		return urlopen(url).read()
    	return get
    
    xiaohua = index()  # get
    content = xiaohua()
    content1 = xiaohua()
    content2 = xiaohua()   这个内容可以反复使用
    print(content.decode())  默认解码是utf-8的方式,等于content.decode('utf-8')
    

    编码

    a = "中国"
    a1 = a.encode("utf-8")  """ encode是字符串改变为byte字节数据类型,byte类型用utf-得编码,字符串之前是unicode得编码"""
    print(a1,type(a1),type(a))
    
    结果:
    b'xe4xb8xadxe5x9bxbd' <class 'bytes'> <class 'str'>
    

    1.4 装饰器

    经典装饰器

    def wrapper(f):  """在这里相当于f = func1"""
        def inner():
            """ 函数执行之前的操作"""
            ret = f()
            """ 函数执行之后的操作"""
    		return ret """把执行函数得返回值返回给inner(),即已经改了名字得func1()"""
        return inner
    
    @wrapper   
    def func1():  """在这里相当于执行func1 = wrapper(func1)"""
        print("111")
    	return OK
    
    print(func1()) print,打印出上边得返回值ret。
    

    2. 名称空间、作用域、取值顺序

    名称空间

    名称空间分为: 内置名称空间、全局名称空间、局部名称空间

    加载顺序: 打开程序,首先加载内置名称空间,程序执行,一行一行读代码,
    先加载全局名称空间,遇到函数,在把函数加载到内存里,此时不关心函数体,遇到函数执行者,才开始加载

    函数中的变量只能在函数内部使用,并且会随着函数执行完毕,这块内存中的所有内容也会被清空。

    作用域

    全局作用域:包含内置名称空间、全局名称空间,在整个文件的任意位置都能被引用、全局有效
    
    局部作用域:局部名称空间,只能在局部范围内生效
    

    取值顺序:

    单向不可逆,从在找寻变量时,从小范围,一层一层到大范围去找寻。

     在局部调用:局部命名空间->全局命名空间->内置命名空间
    
     在全局调用:全局命名空间->内置命名空间
    

    3. 内置函数 globals()、locals()

    globals()

    返回一个字典,字典里面的内容是全局作用域的内容。
    

    locals()

    返回一个字典,当前位置 的所有变量。
    
    示例:
    def func1():
        name1 = 'oldboy'
        age = 10000
        print(locals())  #这是当前位置
        def func2():
            name2 = 'wusir'
            age2 = 25
            print(globals())
            print(locals())   #只能返回name2,这是当前位置。
        func2()
    func1()
    

    4. 关键字 global、nonlocal

    global

    1. 引用并且改变一个全局变量
    2. 在局部作用域声明一个全局变量
    示例:
    count = 1
    def func1():
        global count
        count = count + 1
        count = count + 100
        print(count)
    func1()
    print(count)
    print(globals())
    
    
    def func1():
        global name
        name = 'alex'
        print(name)
    func1()
    print(name)
    

    nonlocal

    1, 不能操作全局变量
    2. 在哪一层引用得,就从该层开始全部改变。

    示例:
    def func1():
        count = 1
        def inner():   """ inner开始引用nonlocal,后边得层都开始改变了"""
            nonlocal count
            count = count + 3
            # print(count)
            # def inner2():
            #    pass
        inner()
        print(count)
    func1()
    
    # 取值:引用而不是改变
    # 取值是从小到大取值 LEGB
    # 想改变上层空间的变量 要用到global nonlocal
    

    对于可变得数据类型,list、dic、set等,要改变他们,不需要global、nonlocal。

    函数里得默认参数如果是一个可变数据类型,它在内存里得位置永远是一个。

    示例:
    def extendList(val,list=[]):
        list.append(val)
        return list
    list1 = extendList(10)
    print('list1=%s'%list1)  # [10,]
    list2 = extendList(123,[])
    print('list2=%s'%list2)  # [123,]
    list3 = extendList('a')
    print('list3=%s'%list3)  #[10,'a']
    
    print('list1=%s'%list1)
    print('list2=%s'%list2)
    print('list3=%s'%list3)
    

    练习题

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

    dic = [1,2,3,4,5,6]
    def check():
        dic1 = dic[1::2]
        return dic1
    print(check())
    
    1. 写函数,判断用户传入的对象(字符串、列表、元组)长度是否大于5。大于退出,小于继续输入。
    示例:
    flag = True
    while flag:
        a = input("input:")
        def func():
            global flag
            b = len(a)
            print(b,type(b))  #8 <class 'int'>
            if b > 5:
                print("长度大于5!")
                flag = False
            else:
                pass
        func()
    
    1. 写函数,检查传入列表的长度,如果大于2,那么仅保留前两个长度的内容,并将新内容返回给调用者。
    li = [1,2,3,4,5,6]
    def check():
        if len(li) > 2:
            li1 = li[:2]  #字符串切片[起始索引:结束索引+1:步长],顾首不顾尾,所以结束索引+1
            print(li1)
    check()
    
    1. 写函数,计算传入字符串中【数字】、【字母】、【空格] 以及 【其他】的个数,并返回结果。
    def str_number(str_num):
        count = 0
        count2 = 0
        count3 = 0
        count4 = 0
        for i in str_num:
            if i.isdigit() == True:
                count += 1
            elif i.isalpha() == True:
                count2 += 1
            elif i.isspace() == True:
                count3 += 1
            else:
                count4 += 1
        print("数字有%d个"%count)
        print("字母有%d个"%count2)
        print("空隔有%d个" % count3)
        print("其它有%d个" % count4)
        # return
    
    str_num = input("输入:")
    str_number(str_num)
    

    写函数,检查传入字典的每一个value的长度,如果大于2,那么仅保留前两个长度的内容,并将新内容返回给调用者。
    dic = {"k1": "v1v1", "k2": [11,22,33,44]}
    PS:字典中的value只能是字符串或列表

    def a4(arg):
        ret = {}
        for key,value in arg.items():
            if len(value) > 2:
                ret[key] = value[0:2]
            else:
                ret[key] = value
        return  ret
    
    dic = {"k1": "v1v1", "k2": [11, 22, 33, 44],"k3":"12"}
    r = a4(dic)
    print(r)
    

    练习:

    li = [1,2,3,4,5,6]
    def func1(*args):
        print(args)
    func1(li)
    结果:
    ([1, 2, 3, 4, 5, 6],)    列表可以这样
    
    
    dic = {"k1": "v1v1", "k2": [11, 22, 33, 44],"k3":"12"}
    def func1(f):
        for k,v in dic.items():  直接f代表了传入的字典。
            print(k,v)
    func1(dic)
    结果:
    k1 v1v1
    k2 [11, 22, 33, 44]
    k3 12
    
    dic = {"k1": "v1v1", "k2": [11, 22, 33, 44],"k3":"12"}
    def func1(**kwargs):
        print(kwargs)
    # func1(dic)    #报错func1() takes 0 positional arguments but 1 was given
    # func1()  #返回{}
    func1(k1= "v1v1")  #返回{'k1': 'v1v1'}   字典用**kwargs必须使用关键字参数,要具体化。
    My name is 侯冰雷 ~~欢迎转载 ~~欢迎关注 ~~欢迎留言
  • 相关阅读:
    broncho a1 hack指南-准备硬件
    嵌入式GUI ftk0.1发布
    ASP.net页面防刷新
    C#反射入门教程(转)
    万物生萨顶顶
    [转载内容]C# win程序中主窗体菜单的权限控制
    VB.net技巧更新(一)
    XML与dataset里相互读取操作
    操作EXCEL代码(c#完全版)
    [转载内容]动态创建菜单,menustrip,根据权限显示菜单,控制菜单可用,反射,给窗体传值,反射对象传值,public static Object CreateInstance ( Type type, params Object[] args )
  • 原文地址:https://www.cnblogs.com/houbinglei/p/9268808.html
Copyright © 2011-2022 走看看