python函数

一、函数初识

  •  函数的定义和调用: 对功能进行定义和封装,方便调用

    基本格式: 

        def  函数名(形参):

          函数体(代码块)

        函数名(实参)

  •  函数名: 函数名的命名规则和变量是一样的

定义一个简单的函数并调用它:

1 def app():
2     print("这只是在构建最基本的函数格式")
3     print("函数的功能并不只是打印内容")
4     print("函数的作用是封装功能,里面什么都能写")
5 
6 app()
  •  函数的返回值:

    return      执行完函数之后. 我们可以使用return来返回结果.当函数执行到return之后,结束此函数,不在继续执行     return 可以返回多个值,用元组表示

1 def app():
2     print("这只是在构建最基本的函数格式")
3     print("函数的功能并不只是打印内容")
4     print("函数的作用是封装功能,里面什么都能写")
5     return '基本格式', '封装功能'
6 print(app())
  •  关于返回值:

    如果return什么都不写 或者 干脆不写return .那么返回的就是None

    如果return后面写了一个值. 则调用者可以接收一个结果

    如果return后面写了多个结果, 则调用者可以接收一个tuple, 调用者可以直接解构成多个变量

 

  •  函数的参数:   函数在调用的时候指定具体的一个变量的值. 就是参数.

    形参:

      位置参数:  按照位置顺序给函数创建参数

1 def yue(fangshi, age):   # 形参
2     print("打开手机")
3     print("打开%s" % fangshi)
4     print("找一个漂亮的妹子")
5     print("年龄最好是%s" % age)
6     print("出来约一约")
7 
8 yue("探探", 38)
9 yue("陌陌", 26)

      默认值参数:  指定参数的值,如果传参是不输入值,则使用默认值

1 def regist(id, name, sex=""):
2     print("录入学生信息:id是%s, 名字是%s, 性别是:%s" % (id, name, sex))
3 
4 regist(1, "大阳哥")
5 regist(2, "徐卫星")
6 regist(3, "毛尖妹妹", "")

      位置参数和默认值参数混合使用: 可以把上面两种参数混合着使用. 也就是说在调用函数的时候即可以给出位置参数, 也可 以指定参数的默认值.

    实参:

      位置参数:  按照位置给形参赋值

      关键字参数:   按照名称给形参赋值

      混合参数:   先用位置参数, 再用关键字参数

1 def gn(name, age, address, id, sex, hobby):
2     print("人的名字叫%s, 年龄:%s, 地址:%s, id是:%s, 性别:%s, 爱好是:%s" % (name, age, address, id, sex, hobby))
3 gn("太白", 58, "保定", 1, "不详", "")    # 位置参数
4 gn(id=1, name="太白", address="保定", hobby="", age=58, sex="不详")  # 关键字(形参)参数
5 gn("太白", 58, "保定", id="3", sex="", hobby="不详")

 

 二、函数参数,命名空间和作用域

  • 函数传参 - 动态传参

    *args   动态传参   位置传参

def chi(*food):
    print("我要吃", food)
chi("包子", '馒头', '米饭', '小龙虾', '黄焖鸡', '酸菜鱼')

    示例:传入任意整数,求所有数的和

def num(*digit):
    sum = 0
    for i in digit:
        sum = sum + i
    return sum
print(num(1,2,3,4,5,6,7))

 

    **kwargs  动态传参   关键字传参

def app(**games):
    print(games)
app(free_game ='消消乐', dongzuo_game = "格斗之王", jingji_game = "王者荣耀", yizhi_game = '数独')

 

    当*args 和 **kwargs一起使用时,什么东西都能传入

def func(*args,**kwargs):
    print(args)
    print(kwargs)
func('哈士奇', '金毛', '萨摩', name='y',age=22,sex='nan')

   参数接收顺序: 位置参数  , *args  , 默认值参数  , **kwargs

 

  • 函数的命名空间和作用域

    • 命名空间

      内置命名空间:   存放python解释器为我们提供的名字, list, tuple, str, int这些都是内 置命名空间

      全局命名空间:   我们直接在py⽂件中, 函数外声明的变量都属于全局命名空间

      局部命名空间:   在函数中声明的变量会放在局部命名空间

      加载顺序:  内置命名空间  , 全局命名空间  , 局部命名空间

      取值顺序:  局部命名空间  , 全局命名空间  , 内置命名空间

 

    • 作用域

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

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

      作用域命名空间:

        全局作用域:  内置命名空间  +  全局命名空间

        局部作用域:   局部命名空间

      globals()    查看全局作用域中的名字

      locals()        查看局部作用域中的名字

 a = 10
def func():
    a = 40
    b = 20
    def abc():
       print("哈哈")
    print(a, b) # 这⾥使⽤的是局部作⽤域
    print(globals()) # 打印全局作⽤域中的内容
    print(locals()) # 打印局部作⽤域中的内容
func()

 

  • global  和  nonlocal

    • global   把全局变量拿到局部来用
    • nonlocal    把离他最近的一层的变量拿过来.不会找全局

   global  使用示例

1 a = 100
2 def func():
3     global a # 加了个global表示不再局部创建这个变量了. 而是直接使用全局的a
4     a = 28
5     print(a)
6 func()
7 print(a)

 

   nonlocal  使用示例

 1 a = 10
 2 def func1():
 3     a = 20
 4     def func2():
 5         nonlocal a
 6         a = 30
 7         print(a)
 8     func2()
 9     print(a)
10 func1()

 

三、函数名的应用(高阶函数),闭包,迭代器,生成器

  • 函数可以像变量一样使用

    1.函数名可以赋值给其他变量

    2.函数名可以当做函数的参数

    3.函数名可以作为函数的返回值

    4.函数名可以作为list元素

 赋值:

1 def func():
2     print("呵呵")
3 print(func)
4 a = func    # 把函数当成⼀个变量赋值给另⼀个变量
5 a()      # 函数调⽤ func()

做list元素:

 1 def func1():
 2     print("呵呵")
 3 def func2():
 4     print("呵呵")
 5 def func3():
 6     print("呵呵")
 7 def func4():
 8     print("呵呵")
 9 lst = [func1, func2, func3,func4]
10 for i in lst:
11     i()

 做返回值:

1 def func_1():
2     print("这里是函数1")
3     def func_2():
4         print("这里是函数2")
5     print("这里是函数1")
6     return func_2
7 fn = func_1()    # 执行函数1. 函数1返回的是函数2, 这时fn指向的就是上面函数2
8 fn()     # 执行上面返回的函数

 

  • 闭包

  闭包就是内层函数, 对外层函数(非全局)的变量的引用. 叫闭包

1 def func1():
2     name = "alex"
3     def func2():
4         print(name)  # 闭包
5     func2()
6 func1()

  我们可以使用__closure__来检测函数是否是闭包. 使用函数名.__closure__返回cell就是 闭包. 返回None就不是闭包

1 def func1():
2     name = "alex"
3     def func2():
4         print(name)  # 闭包
5     func2()
6     print(func2.__closure__) # (<cell at 0x10c2e20a8: str object at0x10c3fc650>,)
7 func1()

  闭包的特征:

    常驻内存

    安全

 

  • 迭代器

  可迭代对象:str ,list,dict,tuple,set,range           iterable(可迭代对象)       内部包含 __iter__() 函数

  迭代器:文件句柄   iterator(迭代器)    内部包含__iter__()  和  __next__() 函数

迭代器示例:

1 lst = ['','','','','','','']
2 
3 f = lst.__iter__()
4 while 1:
5     try:
6         name = f.__next__()
7         print(name)
8     except StopIteration:
9         break
  • 迭代器特征:
    • 节省内存
    • 惰性机制
    • 不能反复,只能向下执行

生成器

  • 生成器实质就是迭代器
  • 获取生成器的方式:
    • 通过生成器函数
    • 通过推导式实现生成器
    • 通过数据转换实现生成器

获取生成器函数 __next__():

 1 def func():
 2     print('假装我是一个功能')
 3     yield '然而并不是'
 4     print('假装我是小蝌蚪')
 5     yield '你看不见我'
 6     print('假装我是一阵风')
 7     yield '无影无形'
 8 
 9 s = func()
10 print(s.__next__())
11 print(s.__next__())
12 print(s.__next__())

 

节省内存的方法:

 1 def eggs():
 2     i = 1
 3     while i < 101:
 4         yield '鸡蛋%s' % i
 5         i += 1
 6 s = eggs()
 7 print(s.__next__())
 8 print(s.__next__())
 9 print(s.__next__())
10 print(s.__next__())

 

获取生成器函数 send():

 1 def eat():
 2     print("我吃什么啊")
 3     a = yield "馒头"
 4     print("a=",a)
 5     b = yield "⼤饼"
 6     print("b=",b)
 7     c = yield "⾲菜盒⼦"
 8     print("c=",c)
 9     yield "GAME OVER"
10 gen = eat() # 获取⽣成器
11 ret1 = gen.__next__()
12 print(ret1)
13 ret2 = gen.send("胡辣汤")
14 print(ret2)
15 ret3 = gen.send("狗粮")
16 print(ret3)
17 ret4 = gen.send("猫粮")
18 print(ret4)

 

列表推导式:

  [结果 for 变量 in 可迭代对象 if 条件]

1 # 获取1-100内能被3整除的数
2 lst = [i for i in range(1,101)  if i % 3 == 0]
3 print(lst)
1 # 寻找名字中带有两个e的人的名字
2 names = [['Tom', 'Billy', 'Jefferson' , 'Andrew' , 'Wesley' , 'Steven' ,'Joe'],['Alice', 'Jill' , 'Ana', 'Wendy', 'Jennifer', 'Sherry' , 'Eva']]
3 lst = [a for i in names for a in i  if a.count('e') == 2]
4 print(lst)

 

字典推导式:

  {结果 for 变量 in 可迭代对象 if 条件}  结果是键值对=》key:value

1 # 字典推导式
2 
3 list1 = ['', '', '', '', '', '', '']
4 list2 = ['','','','','6','', '']
5 
6 dic = {list1[i]:list2[i]  for i in range(len(list1))}
7 print(dic)

 

集合推导式:

  {结果 for 变量 in 可迭代对象 if 条件}  结果是 key

1 lst = [1, -1, 8, -8, 12]
2 # 绝对值去重
3 s = {abs(i) for i in lst}
4 print(s)

 

生成器表达式和列表推导式的区别:

  1.列表推导式比较耗内存. 一次性加载. 生成器表达式几乎不占用内存. 使用的时候才分 配和使用内存

  2.得到的值不一样. 列表推导式得到的是一个列表. 生成器表达式获取的是一个生成器

posted @ 2018-07-12 21:47  时光毁了少年梦  阅读(138)  评论(0编辑  收藏  举报