一.函数:将重复执行的代码定义成函数,可以通过函数名重复调用
         减少代码的重复性,提高代码的重用性
   1.定义:(函数名不能是关键字)

1.1 def func(): # 函数基础框架
              print("first function")
      1.2 def func(): # 带返回值的函数
              print("first function with return value")
              value = 1   
              return value
      1.3 def func(args): # 带一个参数带返回值的函数
              print("the function has a {0}".format(args))
              value = 1
              return value
      1.4 def func(*args,**kwargs): # 任意个数参数带返回值的函数
              ...
              return vlaue


   2.函数返回值的种类:
     2.1 没有返回值--默认返回None,与只写一个return或者return None的情况是一样的,return可用作结束函数
         例如循环查找某对象,在循环未结束之前已经找到,则可用return结束函数,与break的
         结束循环不同,结束循环是指循环中break后的代码不再执行,结束函数,是函数内return
         后的所有代码均不执行,return可以返回任意数据类型,任意个数值,若返回多个值,以元组的形式返回
         返回值可以用多个变量接收,也可以用一个变量接收

def func1():
                 return 'a','b','c'
             res = func1();
             res1,res2,res3 = func1()
             print(res,res1,res2,res3) ==> ('a', 'b', 'c') a b c
             注:关于多个值接收,python中互换两个变量的值有最简单的写法
                 a = 1
                 b = 2
                 a,b = b,a
                 print(a,b) ==> 2 1


   3.函数参数:
     3.1 形参:
         写在函数定义时的参数称作“形参” -- def 函数名(形参)
          
     3.2 实参:
         函数调用时传入的参数称为“实参” -- 函数名(实参)
     3.3 没有参数 -- 定义时括号内不写任何内容
         一个参数 -- 定义时括号内写一个形参(定义一个变量),参数可以时基础数据类型,也可以时复杂数据结构

def func(name):
                 print(name)
             func('张三')
             nameLst = ['张三','李四','王五','陆六']
             func(nameLst)


         多个参数:
            关于实参:
              按位置传参:

def func(name,age,job):
                      print("{0},{1},{2}".format(name,age,job))
                  func('张三','18','厨师')
               按关键字传参:
                  func(job='厨师',age='18',name='张三')
               同时包含位置和关键字传参:先按位置传参,再按关键字传参
                  func(job='厨师','张三','18')  ==> SyntaxError: positional argument follows keyword argument
                  func('李四','25',job='和尚')
          关于形参:
             通用参数:def func(name,age,job):
             默认参数: 定义时位置参数在前,默认参数要放最后
                def func(name,age,job='剑客'):
                    print("{0},{1},{2}".format(name,age,job))
                func('张三','18')
                
             动态参数:
                动态位置参数:(传入的参数组成一个元组)
                   def func(*args):
                       for i in args:
                           print(args,i)
                   func(1,2,3,4,5,6)
                注:先定义位置参数,*args,默认参数
                
                动态关键字传参:(传入的参数组成一个字典)
                    def func(**kwargs):
                        for i in kwargs:
                            print(kwargs,i,kwargs[i])
                    func(name='张三',age=18,job='厨师')
                    
                任意参数:
                    def func(*args,**kwargs):
                        print(args,kwargs)     
                    func(1,2,3,4,name='张三',age=18,job='厨师')
                位置参数任意参数关键字与默认参数传参组合:
                    def func(a1,a2,*args,d1='默认值1',d2='默认值二',**kwargs):
                        print(a1,a2,args,kwargs,d1,d2,kwargs)
                    func('位置1','位置2','任意1','任意2',kw1='关键字1',kw2='关键字2')
                *args与**kwargs的另一种传参方式
                    def func(*args,**kwargs):
                       print(args,kwargs)
                    lst = [x for x in range(10)]
                    dic = {'name':'张三','age'18,'job':'厨师'}
                    func(*lst,**dic) ==> (0, 1, 2, 3, 4, 5, 6, 7, 8, 9) {'name': '张三', 'age': 18, 'job': '厨师'}
                默认参数陷阱:(默认参数传入的是可变数据类型)
                    def func(num,lst=[]):
                        lst.append(num)
                        print(lst)
                    func(1) ==> [1]
                    func(2) ==> [1,2]
                    func(3) ==> [1,2,3]
                    func(1,[]) ==> [1]
                    func(2,[]) ==> [2]
                    func(3,[]) ==> [3]


                   定义默认参数如果是可变数据类型,此数据类型在定义的时候(赋值操作/初始化)就已经开辟出了内存空间
                   所有的调用共享同一块内存