函数,返回值,参数,空间,作用域,函数名的运用,新版格式化输出。

函数,返回值,参数,空间,作用域,函数名的运用,新版格式化输出。

  1. 函数的优势:

    1. 减少代码的重复性
    2. 代码可读性高
    3. 将功能进行封装
  2. 函数的结构及调用:

    def fun():
    	print(10)
    fun()
    ###
    #def:定义函数关键字
    
    #func:函数名,跟定义变量一样(函数名只能包含字符串、下划线和数字且不能以数字开头)
    
    #():传递参数
    
    #: 语句结束
    
    #函数体:缩进。函数中尽量不要出现 print
    
    #fun():函数名()进行调用,多次调用就是执行多次,可以循环调用。
    
  3. 函数的返回值:return

    def meet():
        print('打开tantan')
        print('左滑一下')
        return
        print('右滑一下')
        print('找美女')
        print('悄悄话....')
        print('约....走起...')
    meet()
    return: 在函数中遇到return直接结束函数。
    
    def meet():
        print('打开tantan')
        print('左滑一下')
        print('右滑一下')
        print('找美女')
        print('悄悄话....')
        print('约....走起...')
        # return '妹子一枚'
        return '妹子', 123, [22, 33]
    ret= meet()
    # ret,ret1,ret2 = meet()
    print(ret,type(ret))
    # return 返回多个元素 是以元组的形式返回给函数的执行者。
    
    #返回值总结:
    #	return:返回一个内容(内容本身),可以返回多个值
    #		   返回多个内容,以元组的形式返回
    #		   return终止函数,(切记不能终止循环)
    #		   return下方的代码不执行
    #		   return不写返回值或者空内容就返回None,或者没有return也返回None
    #		   return 将内容返回给了函数的调用
    
  4. 函数的参数:

    1. 形参:写在函数声明的位置的变量叫形参

      1. 位置参数:位置参数其实与实参角度的位置参数是一样的,从左至右,一一对应
      2. 默认参数:函数声明的时候,可以给出函数参数的默认值. 默认值参数一般是这个参数使用率较高
      3. (位置,默认) 混合参数:默认参数一定在位置参数后面。
      4. 优先级 位置 > 默认参数
    2. 实参:在函数调用的时候给函数传递的值

      1. 位置参数:从左至右,实参与形参一一对应。
      2. 关键字参数:不需要记住每个参数的位置. 只要记住每个参数的名字就可以了。
      3. (位置,关键字)混合参数:关键字参数一定在位置参数后面。
      4. 优先级 位置 > 关键字参数
    3. 形参,实参的第三种:动态参数*,**

      1. 动态接受位置参数*args:

        1. args,args就是一个普通的形参,但是如果你在args前面加一个*,那么就拥有了特殊的意义。

        2. 函数定义时,*代表聚合。他将所有的位置参数聚合成一个元组,赋值给了args。

          #写一个函数:计算传入函数的所有数字的和
          def fun(*args)
          	count = 0 
          	for i in args:
                  count + = i
              return count
          print(fun(1,2,3,77,88,99,23,78,99))
          
        3. 函数执行时,代表打散,再赋值给形参*动态参数聚合。

          def fun1(*args)
          	count = 0
          	for i in args:
          		count += i
          	return count
          print(fun1(*[1,2,3,4,5,6],*(9,8,7,6,5,4,3)))
          

        2.动态接收关键字参数**kwargs:

        1. 函数定义时,**代表聚合。他将所有的关键值参数聚合成一个字典,赋值给了args。

          def func(**kwargs):
              print(kwargs)
          func(name='ale',age=73,sex='laddyboy')
          
        2. 函数执行时,**代表打散,将再赋值动态万能参数聚合

          def func(**kwargs)
          	print(kwargs)
          func(**{'a':13},**{'b':19}#{'a':13,'b':19}
          
        3. ​ *处理剩下的元素

          1. *除了在函数中可以这样打散,聚合外,函数外还可以灵活的运用:

            #1.元组,以及列表可以分别拆包赋值
            a,b=(1,2)
            print(a, b) # 1 2
            #其实还可以这么用:
            a,*b = (1, 2, 3, 4,)
            print(a, b) # 1 [2, 3, 4]
            
            *rest,a,b = range(5)
            print(rest, a, b) # [0, 1, 2] 3 4
            
            print([1, 2, *[3, 4, 5]]) # [1, 2, 3, 4, 5]
            
        4. 形参的第四种参数:仅限关键字参数

          1. 位置要放在*args后面,kwargs前面(如果有kwargs),也就是默认参数的位置,它与默认参数的前后顺序无所谓

            # 这样传参是错误的,因为仅限关键字参数c只接受关键字参数
            def func(a,b,*args,c):
            print(a,b) # 1 2
            print(args) # (4, 5)
            # func(1, 2, 3, 4, 5)
            # 这样就正确了:
            def func(a,b,*args,c):
            print(a,b) # 1 2
            print(args) # (3, 4)
            print(5)
            func(1, 2, 3, 4, c=5)
            
        5. 形参的顺序

          1. 位置参数 > *args >默认参数(关键字参数)>**kwargs
          # 这样位置参数a,b始终接收不到实参了,因为args全部接受完了
          def func(*args,a,b,sex='男'):
          print(args)
          print(a,b)
          func(1, 2, 3, 4, 5)
          
          #实参的第三个参数始终都会将sex覆盖掉
          def func(a,b,sex='男',*args,):
          print(args) # (4, 5)
          print(sex) # 3
          print(a,b) # 1 2
          func(1, 2, 3, 4, 5)
          
          #**kwargs 位置
          def func(a,b,*args,sex= '男',**kwargs,):
              print(a,b)
              print(sex)
              print(args)
              print(kwargs)
          # func(1,2,3,4,5,6,7,sex='女',name='Alex',age=80)
          

5.名称空间:

  1. 在python解释器开始执行之后, 就会在内存中开辟一个空间, 每当遇到一个变量的时候, 就把变量名和值之间的关系记录下来, 但是当遇到函数定义的时候, 解释器只是把函数名读入内存, 表示这个函数存在了, 至于函数内部的变量和逻辑, 解释器是不关心的. 也就是说一开始的时候函数只是加载进来, 仅此而已, 只有当函数被调用和访问的时候, 解释器才会根据函数内部声明的变量来进行开辟变量的内部空间. 随着函数执行完毕, 这些函数内部变量占用的空间也会随着函数执行完毕而被清空.
  2. 内置名称空间:存放的是内置函数的特殊变量。
  3. 全局名称空间:只存放名字于值(内存地址)的关系
  4. 临时名称空间:运行中开辟的临时的空间叫做局部命名空间也叫做临时名称空间。
  5. 加载顺序:
    1. 内置>>全局>>局部(临时)
  6. 取值顺序:(就近原则LEGB)
    1. 局部>>全局>>内置

6.作用域:

  1. 作用域就是作用范围, 按照生效范围来看分为全局作用域和局部作用域

    1. 全局作用域: 包含内置命名空间和全局命名空间. 在整个文件的任何位置都可以使用(遵循 从上到下逐⾏执行).

    2. 局部作用域: 在函数内部可以使用.

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

      #在全局作用域下打印,则他们获取的都是全局作用域的所有的内容。
      a = 2
      b = 3
      print(globals())
      print(locals())
      
      # 在局部作用域中打印。
      a = 2
      b = 3
      def foo():
          c = 3
          print(globals()) # 和上面一样,还是全局作用域的内容
          print(locals()) # {'c': 3}
      foo()
      

    4.局部作用域可以引用全局作用域的变量

    #  局部作用域可以引用全局作用域的变量,全局作用域不能引用局部作用域
    # date = '周五'
    # def func():
    #     a = 666
    #     print(date)
    # print(a)
    # func()
    # print(a)
    

    5.局部作用域不能改变全局变量。

    count = 1
    def func():
    	count += 2
    	print(count)
    func()  # local variable 'count' referenced before assignment
    # 局部作用域不能改变全局作用域的变量,当python解释器读取到局部作用域时,发现了你对一个变量进行修改的操作,
    # 解释器会认为你在局部已经定义过这个局部变量了,他就从局部找这个局部变量,报错了。
    

7.函数的嵌套(高阶函数):不调用不执行

	# 例1:
def func1():
    print('in func1')
    print(3)
def func2():
    print('in func2')
    print(4)
func1() #'in func1'
		#3
print(1)#1
func2()#'in func2'
		#4
print(2)#2

# 例2:
def func1():
    print('in func1')
    print(3)
def func2():
    print('in func2')
    func1()
    print(4)
print(1) #1
func2()  #'in func2'
		 #'in func1'
    	 #3
         #4
print(2) #2
# 例3:
def fun2(): 
    print(2) 
    def fun3(): 
        print(6) 
    print(4) 
    fun3() 
    print(8)
print(3) #3
fun2()	#2
		#4
    	#6
        #8
print(5) #5

8.关键字global,nonlocal

  1. golobal作用。

    1. 声明一个全局变量。
    2. 在局部作用域想要对全局作用域的全局变量进行修改时,需要用到 global(限于字符串,数字)。
  2. 局部作用域对全局作用域的变量(此变量只能是不可变的数据类型)只能进行引用,如果需要改变需要golobal声明变量 并修改:

    count = 1
    def search():
        global count
        count = 2
    search()
    print(count)
    
  3. 利用global在局部作用域也可以声明一个全局变量。

    def func():
        global a
        a = 3
    func()
    print(a)
    
  4. nonlocal局部作用域如果想对父级作用域的变量进行改变时,需要用到nonlocal

    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()
    
  5. global nonlocal

    1. 默认参数的陷阱:

      def func(name,**kwargs)
      	print(name)
      	print(kwargs)
      fun('xiaoming',sex='男')
      ###陷阱值针对于默认参数是可变的数据类型
      def func(name,alist=[]):
      	alist.append(name)
      	return alist
      
      ret1 = func('alex')
      print(ret1,id(ret1))  # ['alex']
      ret2 = func('太白金星')
      print(ret2,id(ret2))  # [’alex',太白金星']
      
      # 如果你的默认参数指向的是可变的数据类型,那么你无论调用多少次这个默认参数,都是同一个。
      def func(a, list=[]):
          list.append(a)
          return list
      print(func(10,)) #[10]
      print(func(20,[])) #[20] 
      print(func(100,))  #[10,100]
      l1 = []
      l1.append(10)
      print(l1)#[10]
      l2 = []
      l2.append(20)#[20]
      print(l2)#
      l1.append(100)
      print(l1)#[10,100]
      
      def func(a, list= []):
          list.append(a)
          return list
      ret1 = func(10,)  # ret = [10,]
      ret2 = func(20,[])  # [20,]
      ret3 = func(100,)  # ret3 = [10,100]
      print(ret1)  # [10,]  [10,100]
      print(ret2)  # 20,]  [20,]
      print(ret3)  # [10,100]  [10,100]
      
    2. 局部作用域的坑

      #在函数中,如果定义一个变量,但是不是在定义变量之前对其引用,解释器认为,语法错误。
      a = 10
      def func():
      	print(a)
      	a = 30 
      print(func())
      
      
      #golobal:在局部作用域声明一个全局变量。
      name = 'xiaoming'
      def func():
          golobal name
          name = "小红"
          return name
      print(func())#小红
      print(name)#小红
      ###
      count = 1
      def func():
          # print(count)
          global count
          count += 1
      print(count)
      func()
      print(count)
      ###########
      nonlocal:
      #1.不能修改全局变量,只能修改局部作用域的父级变量的值:
      count = 1
      def func():
          nonlocal count
          count += 1
      func()
      #2. 局部作用域:内层函数对外层函数的局部变量进行修改。
      def wrapper():
          count = 1
          def inner():
              nonlocal count
              count += 1
          print(count)
          inner()
          print(count)
      wrapper()
      
  6. 函数名的运用

    1. 函数名的定义和变量的定义几乎一致,在变量的角度,函数名其实就是一个变量,具有变量的功能:可以赋值;但是作为函数名他也有特殊的功能就是加上()就会执行对应的函数。

    2. 函数的内存地址

      def func1():
          pass
      
      def func2():
          pass
      
      print(id(func2)#function func2 at 0x000002765C13E550
      print(id(func1)#function func1 at 0x000002765C13E3A0>
      
    3. 函数名可以赋值给其他变量

      
      def func():        
          print("呵呵")   
      print(func)
      a = func  # 把函数当成一个变量赋值给另一个变量
      a() # 函数调用 func()
      
      
      
    4. 函数名可以当作容器类的元素

      def func1():
          print("in func1: 嘻嘻")
      def func2():
          print("in func2: 哈哈")
      def func3():
          print("in func3: 咯咯")
      def func4():
          print("in func4: 吱吱")
      lst = [func1, func2, func3, func4]
      for i in lst:
          i()
      

      5.函数名可以当作函数的参数

      def func1():
          print('in func1')
      
      def func2(f):
          print('in func2')
          f()
      
      func2(func1)
      
    5. 函数名可以作为函数的返回值

      def func1():
          print('in func1')
      
      def func2(f):
          print('in func2')
          return f
      
      ret = func2(func1)
      ret()  # ret, f, func1 都是指向的func1这个函数的内存地址
      
  7. f-string格式化输出

    1. 结构就是F(f)+ str的形式,在字符串中想替换的位置用{}展位,与format类似,但是用在字符串后面写入替换的内容。

      #旧版格式化输出:
      #msg = '我叫%s,今年%s' %(name,age)
      #msg = '我叫{},今年{},format(name,age)'
      
      name = '金星'
      age = 18
      sex = '男'
      msg = F'姓名:{name},性别:{age},年龄:{sex}'  # 大写字母也可以
      msg = f'姓名:{name},性别:{age},年龄:{sex}'  
      print(msg)
      '''
      姓名:金星,性别:18,年龄:男
      '''
      
    2. 任意表达式

      print(f'{3*21}')  # 63
      ***
      name = 'barry'
      print(f"全部大写:{name.upper()}")
      ****字典:
      dic = {'name':'alex','age': 73}
      # msg = f'我叫{dic["name"]},今年{dic["age"]}'
      # print(msg)
      *****列表:
      a =[1,2,3,4,5]
      print(f'最小数{a[0],最大数{a[-1]})#1,5
      ##计算最终结果
      count = 7
      print(f'最终结果:{count**2}')
      ###转换成大写
      name = 'barry'
      msg = f'我的名字是{name.upper()}'
      print(msg)
      ****
      ###插入表达式
      def sum_a_b(a,b):
          return a + b
      a = 1
      b = 2
      print('求和的结果为' + f'{sum_a_b(a,b)}')#    
           
      #多行f
      name = 'barry'
      age = 18
      ajd = 'handsome'
      speaker = f'Hi {name}.'\
                f'You are {age} years old.'\
                f'You are a {ajd} guy!'
      print(speaker)
            
      #####
      # ! , : { } ;这些标点不能出现在{} 这里面。
      
posted @ 2021-12-07 15:53  啊铨的博客  阅读(68)  评论(0)    收藏  举报