zoukankan      html  css  js  c++  java
  • 四、函数

    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(路径)添加搜索目录

  • 相关阅读:
    火狐插件火狐黑客插件将Firefox变成黑客工具的七个插件
    memcache安装环境:WINDOWS 7
    PHP正则表达式
    968. 监控二叉树 力扣(困难) dfs 官方说DP
    375. 猜数字大小 II 力扣(中等) 区间动态规划、记忆化搜索
    629. K个逆序对数组 力扣(困难) 区间动态规划
    剑指 Offer 51. 数组中的逆序对 力扣(困难) 巧用归并排序算法
    488. 祖玛游戏 力扣(困难) dfs
    16. 最接近的三数之和 力扣(中等) 双指针
    319. 灯泡开关 力扣(中等) 数论
  • 原文地址:https://www.cnblogs.com/liqiongming/p/10045711.html
Copyright © 2011-2022 走看看