• 四、函数


    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'xe4xbdxa0xe5xa5xbd'        #utf-8:三个字节表一个中文
      10 你好
      11 b'xc4xe3xbaxc3'        #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(路径)添加搜索目录

  • 相关阅读:
    MyEclipse 2015 SVN 安装
    PL/SQL中查询Oracle大数(17位以上)时显示科学计数法的解决方法
    Oracle密码过期the password has expired
    解决telnet无法连接 Connection refused
    提示-bash: telnet: command not found的解决方法
    ORACLE WITH AS 用法
    Oracle创建Database Link
    oracle操作字符串:拼接、替换、截取、查找、长度、判断
    Java Web 清除缓存
    mount 命令用法
  • 原文地址:https://www.cnblogs.com/liqiongming/p/10045711.html
Copyright © 2020-2023  润新知