zoukankan      html  css  js  c++  java
  • python 函数

    1 为什么使用函数

    在没有接触函数时,有时候需要将一个功能多次写,如果需要修改其中一个变量,则需要把所有实现该功能的代码一处一处改。不利于代码维护,代码量大了,组织结构也会很不清晰。
    所以总结不使用函数的确定:

    • 代码冗余(重复代码多)
    • 不利于维护(修改麻烦)
    • 可读性差(组织结构不清晰)

    函数的优点:

    • 解决代码重用问题
    • 统一维护
    • 程序的组织结构清晰,可读性强

    # 2 函数的定义

    函数种类:

    1. 内置函数:内置在python解释器的函数
    2. 自定义函数:
    def funtion_name(args):
        """描述信息"""  #可通过function_name.__doc__查看
        函数主体
        return
    

    自定义函数的种类

    • 空函数

      def abc():
          """描述信息"""
          pass
      

      空函数使用在布置程序大致框架时,不用具体实现函数的功能。

    • 有参函数

      def abc(args):
          """描述信息"""
          函数主体
          return xxx
      

      通常有参的函数,都是有返回值的。

    • 无参函数

      def abc():
          """描述信息"""
          函数主体
      

      通常有参的函数,都是有返回值的。


    # 3 函数调用 语句形式:函数名() 表达式形式:res=10*abc(1) 函数调用作为另一个函数的参数:print(abc()) 注意:我们调用一个不存在的函数 ```python func() #NameError: name 'func' is not defined #a=b #NameError: name 'b' is not defined ``` 这里返回的是,“NameError”,函数名未定义。所以,在python中,我们可以理解为**定义函数,就是定义变量名**。
    # 4 函数的返回值 python中函数的返回值可以是任意类型。 1. 没有return或return为空,返回的是None。 2. 可以返回多个函数值(本质是打包成一个元组) 3. 如果有多个return(语法上不会报错),但返回第一个遇到的return。

    注意:

    def my_min(x:int,y:int) ->int:
        pass
    
    print(my_min.__annotations__)   #{'x': <class 'int'>, 'y': <class 'int'>, 'return': <class 'int'>}
    

    该方法适合那些从c++,java转到Python的。


    # 5 函数的参数 定义函数时的参数,就是形式参数。 调用函数时的参数,就是实际参数。 函数调用时,会把实参绑定到形参,结束调用时,解除绑定。
    #形参、实参都是不可变
    def foo1(a):
        a=3
        print(a)
    x=1
    foo1(x)  #3
    print(x) #1
    

    foo1里面重新给a赋值不会影响x,为什么?我们可以这样理解,实参是本身存的一个变量的值,而形参存的是一个变量名(没有值)。当发起函数调用时,形参会绑定实参的值,如果在函数内给形参赋值,形参会绑定新的值。(可以和变量与变量的赋值类比)所以不会改变实参的值。

    #形参是可变类型
    def foo2(a,L=[]):
        L.append(a)
        print(L)
    
    foo2(1)   #[1]
    foo2(2)   #[1, 2]
    foo2(3)   #[1, 2, 3]
    

    当foo2加载到内存,L指向的是[],当每一次调用函数时,都是在向同一个[]附加数据。

    #改良版
    def foo2(a,L=None):
        if L is None:
            L=[]
        L.append(a)
        print(L)
    foo2(1)   #[1]
    foo2(2)   #[2]
    foo2(3)   #[3]
    
    #实参是可变类型
    def foo3 (L):
        L.append("abc")
        print("foo",L)
    
    li=[1,2,3]
    foo3(li)
    print(li)   #[1, 2, 3, 'abc']
    

    当把一个列表li当实参传到函数时,是将列表li的地址传给形参,所以形参所做的修改,都会影响实参。建议:不要使用可变对象作为实参。

    a=1
    def foo3(x=a):
        print(x)
    a=3
    foo3() #1
    

    这里要区别于java等编译型语言。python作为一门解释型语言,是一边解释一边执行的。当它执行到foo3(),形参x=1被写入内存的。当执行到a=3时,并不会影响x的值。

    6 函数的实参

    def func(a,b,c)
    

    实参传值的方式:

    1. 按位置传参:func(1,2,3)

    2. 按关键字传值:func(a=1,b=2,c=3)

    3. 混合传值:func(a=1,b=2,c=3)

      混合传值注意事项:

    • 按位置传值必须在按关键字传值之前
    • 一个形参只能接收一个传值,如:func(1,2,b=2)会报错,此时b接收了2个值

    7 函数的形参

    1. 位置参数:必须传值
    2. 默认参数:可传可不传,且必须放位置参数后面
      func(a,b=2)
    3. 可变参数 *args 可以理解为一堆位置参数
      先按位置传值,剩下的被*接收,打包成一个元组,再传给args
      #从形参的角度,形参带*
      def func(a,b,*args)
      func(1,2,3,4,5,6)
      result:
      a=1
      b=2
      args=(3,4,5,6)
      
      #从实参的角度,实参带* 
      def foo1(x,y,z):
          print(x)
          print(y)
          print(z)
      foo1(*(1,2,3)) #如果去掉*,会把整个元组赋值给x,此时y和z没有值会报错
      

        当实参遇到*(1,2,3),需要把它拆成1,2,3这样来看

    1. 关键字传值 **kwargs 按关键字传值多余的被**接收,打包成一个字典,传给kwargs

      #从形参的角度,形参带**
      def foo2(**kwargs):
          print(kwargs)
      foo2(a="aa",b="bb")
      
      #从实参的角度,实参带**
      def foo3(x,y,z=1):
          print(x)
          print(y)
          print(z)
      foo3(**{"x":"a","y":"b"})
      
    2. 命名关键字 *,args 用于指定必须以某些关键字来传值

       def foo4(*,x,y=2):
       print(x)
       print(y)
       foo4(x=1)
    

    命名关键字参数不能和可变参数混用

    形参的顺序:

    def func1(a,b=2,*args,**kwargs)
    
    def func2(a,b=2,*,c=3,**kwargs)
    

    8 nonlocal

    nonlocal关键字,只在python3才有。
    nonlocal 的作用就是将变量添加到上一层函数的局部命名空间中。

    def layer_1():
    
        count=1
    
        def layer_2():
    
            count=2
    
            def layer_3():
                
                nonlocal count
                count=3
                print(count)
                print(locals())
    
            layer_3()
            print(count)
            print(locals())
    
        layer_2()
        print(count)
        print(locals())
    
    layer_1()
    

    结果:

    3
    {'count': 3}
    3
    {'layer_3': <function layer_1.<locals>.layer_2.<locals>.layer_3 at 0x000002B39BF7BB70>, 'count': 3}
    1
    {'layer_2': <function layer_1.<locals>.layer_2 at 0x000002B39BF7BAE8>, 'count': 1}
    

    在第3层定义的nonlocal count,count=3影响到第2层count的结果,但第1层没有任何影响

  • 相关阅读:
    css 写一个三角形
    vue 知识汇总,中级阶段的。
    获取url参数封装的
    vue 知识点
    不换行css
    微信小程序的横向滚动
    git提交本地分支到远程分支
    linux shell head tail 用法简介
    PHP服务重启
    MongoDB用户创建
  • 原文地址:https://www.cnblogs.com/yangzhenwei123/p/6758893.html
Copyright © 2011-2022 走看看