四、函数

1、定义

函数是逻辑结构化与过程化的一种编程方法。   (☆ 函数 return 返回的值需用 print 打印出来。打印函数时,没有return默认返回None

(过程:没有返回值return的函数)

 1 def test(x):
 2     '''
 3 
 4     :param x:整形数字
 5     :return:返回计算结果
 6     '''
 7     y = 2*x+1
 8     return y
 9 a = test(1)
10 print(a)
11 
12 def:定义函数的关键字
13 test:函数名
14 ():内可定义形参
15 ''' ''':文档描述
16 y = 2*x+1:泛指代码块或程序处理的逻辑
17 return:定义返回值

 函数的好处:

  1. 代码重用
  2. 保持一致性,已维护
  3. 可扩展
 1 def test1():
 2     msg = 'test01'
 3     print(msg)
 4 
 5 def test2():
 6     msg = 'test02'
 7     print(msg)
 8     return {'name':'Jack'}
 9 
10 def test3():
11     msg = 'test03'
12     print(msg)
13     return 1,2,'a',['b'],{'name':'Jack'},None
14 
15 t1 = test1()
16 t2 = test2()
17 t3 = test3()
18 print(t1)
19 print(t2)
20 print(t3)
21 
22 输出:
23 test01
24 test02
25 test03
26 None
27 {'name': 'Jack'}
28 (1, 2, 'a', ['b'], {'name': 'Jack'}, None)
  • 返回值数 = 0:返回None
  • 返回值数 = 1:返回object
  • 返回指数 > 1:返回tuple

2、函数参数:

  1. 形参与实参,形参不占用内存空间,被调用时才占用。使用实参时注意对应的形参位置,位置参数需在关键字参数左边。
  2. 默认参数:
    1 例:
    2 def test(x,type='Jack'):
    3     print(x)
    4     print(type)
    5 test('Hello')
    6 
    7 输出:
    8 Hello
    9 Jack
  3. 参数组:**字典,*列表  ( 可加多个参数)
    1.   一个 * 表示遍历列表
       1 例:
       2 def test(x,*args):
       3     print(x)
       4     print(args)
       5 test(1,2,3,4,5)
       6 test(1,*(2,3,4,5))
       7 test(1,*{'name':'Jcak','age':18})
       8 
       9 输出:
      10 1
      11 (2, 3, 4, 5)
      12 1
      13 (2, 3, 4, 5)
      14 1
      15 ('name', 'age')
    2. 两个 ** 表字典,输入字典
       1 例:
       2 def test(x,**kwargs):
       3     print(x)
       4     print(kwargs)
       5 test(1,y=1,z= 2)
       6 test(1,**{'name':'Jcak','age':18})
       7 
       8 输出:
       9 1
      10 {'y': 1, 'z': 2}
      11 1
      12 {'name': 'Jcak', 'age': 18}
    3. 总:使用*args,**lwargs
       1 例:
       2 def test(x,*args,**kwargs):
       3     print(x)
       4     print(args)
       5     print(kwargs,kwargs.get('y'))
       6 test(1,1,2,3,4,y=1,z=2)
       7 test(1,*(1,2,3,4),**{'y':1,})
       8 
       9 输出:
      10 1
      11 (1, 2, 3, 4)
      12 {'y': 1, 'z': 2} 1
      13 1
      14 (1, 2, 3, 4)
      15 {'y': 1} 1

3、全局与局部变量:

  1. 全局变量不进行缩进,局部缩进。加 global 可重新赋值全局变量,有局部变量存在时,需写在局部变量前。
     1 例:
     2 name = 'Jack'    #全局
     3 def test():
     4     name = 'Alan'  #局部
     5     print(name)
     6 
     7 test()
     8 print(name)
     9 
    10 输出:
    11 Alan
    12 Jack
     1 例:
     2 name = 'Jack'
     3 def test():
     4     global name      #表示下面修改的name为全局变量
     5     name = 'Alan'
     6     print(name)
     7 
     8 test()
     9 print(name)
    10 
    11 输出:
    12 Alan
    13 Alan

     

  2. 全局变量用大写,局部变量用小写。
  3. 使用 nonlocal 指定上一层局部变量,不能指定全局变量
     1 例:
     2 name = 'Jack'
     3 def test1():
     4     name = 'Alan'
     5     def test2():
     6         nonlocal name    # nonlocal 指定上一层变量
     7         name = 'John'
     8     test2()
     9     print(name)
    10 print(name)
    11 test1()
    12 
    13 输出:
    14 Jack
    15 John

     

4、递归函数:

函数直接或间接调用函数本身,使用 return 终止

 1 例:
 2 def test(n):
 3     print(n)
 4     if int(n / 2) == 0:
 5         return n
 6     res = test(int(n / 2))
 7     return  res
 8 test(10)
 9 
10 输出:
11 10
12 5
13 2
14 1
  • 必须有一个明确的结束条件,不然会一直循环后报错
  • 每次进入更胜一成递归时,问题规模相比上一次有所减少
  • 递归效率不高,递归层次过多会导致栈溢出

5、函数作用域:

作用域不随调用位置的改变而改变

  1. return到一个函数时,返回其内存地址
     1 例:
     2 def test1():
     3     print('in the test1')
     4 def test2():
     5     print('in the test2')
     6     return test1
     7 
     8 res = test2()
     9 print(res)
    10 
    11 输出:
    12 in the test2
    13 <function test1 at 0x00000065FE5CC268>
    14 #返回 test1 函数的内存地址

     

  2. 加上()运行函数时,返回函数 test1 ()运行的值,没有 return 结果的默认输出None

     1 例:
     2 def test1():
     3     print('in the test1')
     4 def test2():
     5     print('in the test2')
     6     return test1
     7 
     8 res = test2()
     9 print(res())
    10 
    11 输出:
    12 in the test2
    13 in the test1
    14 None
     1 例:
     2 def aa():
     3     name = 'test1'
     4     def bb():
     5         name = 'test2'
     6         def cc():
     7             print(name)
     8         return cc
     9     return bb
    10 
    11 # bb = aa()
    12 # cc = bb()
    13 # print(cc)
    14 # cc()
    15 aa()()()
    16 
    17 输出:
    18 test2

     

6、函数式编程

函数式 = 编程语言定义的函数 + 数学意思的函数

函数式就是用编程语言去实现数学函数。这种函数内对象是永恒不变的,要么参数是函数,要么返回值是函数,没有for和while循环,所有循环由递归去实现,无变量的赋值(即不用变量去保存状态),无赋值即不改变。

面向过程:找到解决问题的入口,按照一个固定的流程去模拟解决问题的流程。

特点:

  • 不可变数据
  • 第一类对象
  • 尾调用优化(尾递归)

不可变:不用变量保存状态,不修该变量

 1 #非函数式
 2 a = 1
 3 #增加的测试函数
 4 def incr_test1():
 5     global a
 6     a += 1
 7     return a
 8 
 9 incr_test1()
10 print(a)
11 
12 #函数式
13 n = 1
14 def incr_test2(n):
15     return n+1
16 
17 print(incr_test2(2))
18 print(n)

 

第一类对象:函数即变量(满足以下两个点的函数称为高阶函数)

  1. 函数名可以当做参数传递给另一个函数
     1 例:
     2 def foo(n):
     3     print(n)
     4 
     5 def bar(name):
     6     print('my name is %s' %name)
     7 
     8 foo(bar('jack'))
     9 
    10 输出:
    11 my name is jack
    12 None    #默认return返回None,所以n=None

     

  2. 返回值可以是函数名(给返回的函数赋予一个值,运行后输出。可以return函数本身)
     1 例:
     2 def foo():
     3     print('from foo')
     4 
     5 def bar():
     6     print('from bar')
     7     return foo
     8 n = bar()
     9 n()
    10 
    11 输出:
    12 from bar
    13 from foo

     

 

尾调用:在函数最后一步调用另一个函数(最后一行不一定是函数的最后一步)

 1 #函数bar在foo内为尾调用
 2 
 3 def bar(n):
 4     return n
 5 def foo(x):
 6     return bar(x)
 7 
 8 #函数bar1和bar2在foo内均为尾调用,二者在if判断条件不同的情况下都有可能作为函数的最后一步
 9 def bar1(n):
10     return n
11 def bar2(n):
12     return n+1
13 def foo(x):
14     if type(x) is str:
15         return bar1(x)
16     elif type(x) is int:
17         return bar2(x)

非尾调用:

 1 #函数bar在foo内为非尾调用
 2 def bar(n):
 3     return n
 4 def foo(x):
 5     y = bar(x)
 6     return y
 7 
 8 #函数bar在foo内为非尾调用
 9 def bar(n):
10     return n
11 def f00(x):
12     return bar(x)+1
13     #res = bar(x)
14     #return res+1

 

  1. map函数:(结果为迭代器,只能处理一次,再次处理不显示)依次处理序列中的每个元素,得到的结果是一个‘列表’,该‘列表’元素个数及位置与原来一样(传入两个参数:1、函数   2、iterable(可迭代对象))
    def map(func,array)
     1 #不使用map函数
     2 num = [1,2,3,4,5]
     3 #lambda x:x+1   匿名函数
     4 def add_test(x):
     5     return x+1
     6 
     7 def map_test(array):
     8     ret = []
     9     for i in num:
    10         ret.append(i+1)
    11     return ret
    12 ret = map_test(num)
    13 print(ret)
    14 
    15 输出:
    16 [2, 3, 4, 5, 6]
     1 #使用内置函数map
     2 num = [1,2,3,4,5]
     3 def map(func,array):    #func:函数  array:可迭代对象
     4     ret = []
     5     for i in array:
     6         res = func(i)    #func(i)相当于执行某个函数
     7         ret.append(res)
     8     return ret
     9 
    10 print(map(lambda x:x+1,num))    # print(map(add_test,num))
    11 
    12 msg = 'jack'
    13 res = map(lambda x:x.upper(),msg)
    14 print(res)
    15 
    16 输出:
    17 [2, 3, 4, 5, 6]
    18 ['J', 'A', 'C', 'K']
  2. filter函数:如果布尔值为True,则返回函数运行的值。遍历列表中每个元素,判断每个元素得到的布尔值,如果是True则留下。 
    def filter(func,array)
     1 people = ['a_jack','a_alen','jhon']
     2 res = filter(lambda n:n.startswith('a'),people)
     3 print(list(res))
     4 # def filter(func,array):
     5 #     ret = []
     6 #     for n in array:
     7 #         if func(n):
     8 #             ret.append(n)
     9 #     return ret
    10 # print(filter(lambda n:n.startswith('a'),people))
    11 
    12 输出:
    13 ['a_jack', 'a_alen']
  3. reduce函数:把一个函数作用在一个序列上,函数本身必须接收两个参数,reduce把序列前两个数先代入函数计算后,再继续与序列下一个元素进行代入计算。
    def reduce(func,array,init=None)
     1 from functools import reduce
     2 num = [1,2,3,100]
     3 print(reduce(lambda x,y:x*y,num,2))
     4 # num = [1,2,3,100]
     5 # def reduce(func,array,init=None):
     6 #     if init is None:
     7 #         res = array.pop(0)
     8 #     else:
     9 #         res = init
    10 #     for i in array:
    11 #         res = func(res,i)
    12 #     return res
    13 # print(reduce(lambda x,y:x*y,num,2))
    14 
    15 输出:
    16 1200
    1 from functools import reduce
    2 print(reduce(lambda x,y:x+y,range(100),100))
    3 #print(reduce(lambda x,y:x+y,range(1,101),))
    4 num=[1,2,3,4]
    5 print(reduce(lambda x,y:x+y,num,))
    6 
    7 输出:
    8 5050
    9 10

 

  1. 返回函数:返回函数不要引用任何循环变量、或者后续会发生变化的变量。(一定要引用时需新建一个函数,在用其函数的参数来绑定循环的值)
    • 函数闭包:一个函数返回一个函数,其内部的局部变量被新函数引用,返回的函数需要调用时才执行。
       1 def fun():
       2     l = []
       3     def f(j):
       4         def g():
       5             return j*j
       6         return g()
       7     for i in range(1,4):
       8         l.append(f(i))
       9     return l
      10 f1,f2,f3 = fun()
      11 print(f1)
      12 print(fun())
      13 
      14 输出:
      15 1
      16 [1, 4, 9]
       1 #函数引用循环变量后,输出的值在函数调用时才执行,没有立即返回每一个 i 的值
       2 def count():
       3     l = []
       4     for i in range(1, 4):
       5         def f():
       6              return i*i
       7         l.append(f)
       8     return l
       9 f1, f2, f3 = count()
      10 print(f1(),f2(),f3())
      11 
      12 输出:
      13 9 9 9

       

  2. 匿名函数lambda(lambda 形参:处理流程),处理多个值时用括号如 lambda x,y,z:(x+1,y+1,z+1)一般不单独处理,返回值为该表达式的结果
     1 例:
     2 name = 'jack'  #name = 'jack_name'
     3 def change_name(x):
     4     return name + '_name'
     5 
     6 res = change_name(name)
     7 print(res)
     8 
     9 #使用lambda,输出结果一样
    10 a = lambda x:name+'_name'
    11 print(a(name))
    12 
    13 输出:
    14 jack_name
    15 jack_name

  3. 装饰器(decorator):调用一个以函数作为参数被返回的函数,用来增强某个新函数的功能又不改变这个新函数本身的定义。用 进行引用。 
     1 #导入functools模板
     2 import functools
     3 def g(func):        #func为一个函数名
     4     # @functools.wraps(func)  #将warpper.__name__返回的函数名等同于func的函数名
     5     def warpper():
     6         print('输出新函数 %s():' %func.__name__)
     7         return func()
     8     return warpper
     9 #引用g函数
    10 @g
    11 def now():
    12     return '你好'
    13 print(now())
    14 
    15 输出:
    16 输出新函数 now():
    17 你好
     1 #带参数的装饰器
     2 import functools
     3 def g(text):
     4     def f(func):
     5         @functools.wraps(func)
     6         def wrapper():
     7             print('参数内容:%s,函数:%s():' %(text,func.__name__))
     8             return func()
     9         return wrapper
    10     return f
    11 #引用装饰器
    12 @g('你好Python')
    13 def now():
    14     return '你好'
    15 print(now())
    16 
    17 输出:
    18 参数内容:你好Python,函数:now():
    19 你好

     

  4. 偏函数(Partial function): 使用 functools.partial()把函数的参数固定,返回一个新函数。可接受函数参数,*arg,**kw三个参数
    1 import functools
    2 int2 = functools.partial(int,base=16)   #固定base的值
    3 print(int2('12345'))
    4 arg = functools.partial(max,10) # *arg=(10,2,7,3)再进行比较
    5 print(arg(2,7,3))
    6 
    7 输出:
    8 74565
    9 10

     

7、内置函数

  1. abs():取绝对值
    1 print(abs(-1))
    2 
    3 输出:
    4 1
  2. all():序列中所有元素为真时返回True,单个可迭代对象为空时,也返回True;0,[ ],None为False
    1 print(all(['1','2',0]))
    2 print(all(''))
    3 
    4 输出:
    5 False
    6 True
  3. any():序列中有一个为真时返回True。
  4. bool():0,‘ ’,None为False,其它为真
  5. byte():编码与解码。用什么编码就用什么解码,默认使用 utf-8 解码。
     1 name = '你好'
     2 print(bytes(name,encoding='utf-8'))
     3 print(bytes(name,encoding='utf-8').decode('utf-8'))
     4 print(bytes(name,encoding='gbk'))
     5 print(bytes(name,encoding='gbk').decode('gbk'))
     6 # print(bytes(name,encoding='ascii'))  ascii不能编码中文
     7 
     8 输出:
     9 b'\xe4\xbd\xa0\xe5\xa5\xbd'        #utf-8:三个字节表一个中文
    10 你好
    11 b'\xc4\xe3\xba\xc3'        #gbk:两个字节表一个中文
    12 你好
  6. dir():打印某一个对象下面有哪些方法。help():打印某一对象下的方法该如何使用
  7. divmod():打印商跟余数。(可用于分页功能,10表示总共有多少条记录,3表示一页有多少记录,得出结果分3页,不为0时在多分一页。)
    1 print(divmod(10,3))
    2 
    3 输出:
    4 (3, 1)
  8. eval():提取字符串中的数据结构,也可运算字符串中的表达式。
    1 dic = {'name':'jack'}
    2 dic_str = str(dic)      #此处转换成字符串,无法再进行索引取值
    3 dic_str = eval(dic_str)     #使用eval转换后,可恢复字符串中的数据结构
    4 print(dic_str['name'])
    5 
    6 输出:
    7 jack
  9. frozenset():生成新的不可变集合,不能进行索引
    1 a = frozenset('jack')
    2 b = frozenset(range(10))
    3 print(a)
    4 print(b)
    5 
    6 输出:
    7 frozenset({'k', 'j', 'a', 'c'})
    8 frozenset({0, 1, 2, 3, 4, 5, 6, 7, 8, 9})
  10. hash():可用来判断数据有没有被改动过。如果改动,数据的哈希值会发生改变
    1 name = 'jack'
    2 print(hash(name))
    3 name = 'alen'
    4 print(hash(name))
    5 
    6 输出:
    7 -1093188409928294597
    8 7045170762214928410
  11. bin():十转二进制;hex():转十六进制;oct():转八进制
  12. isinstance():判断数据类型
    1 print(isinstance(1,int))
    2 print(isinstance([1,2,3],list))
    3 print(isinstance(1,dict))
    4 
    5 输出:
    6 True
    7 True
    8 False
  13. zip():将两个序列一一对应组成元组放在列表中。
    1 print(list(zip(['a','b','c'],'123')))
    2 p = {'name':'jack','age':18}
    3 print(list(zip(p.keys(),p.values())))
    4 
    5 输出:
    6 [('a', '1'), ('b', '2'), ('c', '3')]
    7 [('name', 'jack'), ('age', 18)]
  14. max():比较后取最大值  min():取最小值
    1. 处理的是一个可迭代对象,相当于一个for循环取出每个元素进行比较,不同类型不能比较。结合zip使用,字典默认比较keys。
    2. 从第一位开始每个元素依次比较,有一个分出大小后面的不再进行比较。

      1 dic = {'age1':'10','age2':'30','age3':'20'}    #a、g、e一个个进行比较
      2 print(max(zip(dic)))
      3 print(max(zip(dic.keys(),dic.values())))
      4 
      5 输出:
      6 ('age3',)
      7 ('age3', '20')
       1 #比较列表中的字典
       2 people = [
       3     {'name':'jack','age':19},
       4     {'name':'alen','age':25},
       5     {'name':'jhon','age':20}
       6 ]
       7 print(max(people,key=lambda dic:dic['age']))
       8 # res = []
       9 # for item in people:
      10 #     res.append(item['age'])
      11 # print(res)
      12 # print(max(res))
      13 
      14 输出:
      15 {'name': 'alen', 'age': 25}
  15. pow():求出平方与余数
    1 print(pow(3,3))     #3**3
    2 print(pow(3,3,2))       #3**3%2
    3 
    4 输出:
    5 27
    6 1
  16. reversed():反转序列,但不保存
  17. round():四舍五入
  18. slice():切片
    slice(start,stop,step)    #开始,结束,步长
    1 l = 'hello'
    2 s1 = slice(3,5) #赋值一个切片
    3 s2 = slice(1,4,2)
    4 print(l[s1],l[s2])
    5 
    6 输出:
    7 lo el
  19. sorted():从小到大进行排序,加 key 对元素进行修改,reverse=True 时为反向排序。(高阶函数)
    1 l1 = ['jack','Apple','zero']
    2 l2 = [2,4,-3,-1]
    3 print(sorted(l1,key=str.lower))
    4 print(sorted(l2,key=abs,reverse=True))
    5 #l2的值绝对值后进行比较排序
    6 
    7 输出:
    8 ['Apple', 'jack', 'zero']
    9 [4, -3, 2, -1]

 

 8、模块(Module)

一个 .py 文件称为模块。是一组Python代码的集合,可以使用其他模块,也可以被其他模块使用。

包(Package):按目录来组织模块的方法,选择一个顶层包,下面目录为模块名(避免模块名与其他人冲突,使用 顶层包名.模块名)每一个包目录下面都必须有一个__init__.py的文件,也是一个模块,模块名就是上层目录名

好处:

  1. 提高代码可维护性
  2. 避免函数名与变量名冲突
  • 命名时不要使用中文、特殊字符
  • 模块名不要和系统模块名冲突
  • 在Python交互环境执行(import 模块名),若成功则说明系统存在此模块。

【类似_xxx__xxx这样的函数或变量为非公开的函数(private),外部不需要引用的函数定义成private,外部需要引用的函数才定义为public。可以在满足某种条件时(如if条件成立的情况下)再调用非公开函数。】

 

安装第三方模块:

  1. 使用pip安装
    pip install Pillow    #Pillow为模块名

     

  2. Anaconda官网 下载GUI安装包

搜索模块:默认情况下,Python解释器会搜索当前目录、所有已安装的内置模块和第三方模块,搜索路径存放在sys模块的path变量中(sys.path),可用sys.path.append(路径)添加搜索目录

posted @ 2018-12-07 17:15  F·灬小人物  阅读(220)  评论(0编辑  收藏  举报