函数

  函数在编程语言中就是完成特定功能的一个词句组(代码块),这组语句可以作为一个单位使用,并且给它取一个名字。可以通过函数名在程序的不同地方多次执行(这叫函数的调用)。函数在编程语言中有基本分为:预定义函数,自定义函数。预定义函数可以直接使用,而自定义函数顾名思义需要我们自己定义函数。

为什么要使用函数

  在编程中使用函数主要有两个优点:

  1、降低编程难度:通常将一个复杂的大问题分解成一系列的小问题,然后将小问题划分成更小的问题,当问题细化为足够简单时,我们就可以分而治之,各个小问题解决了,大问题就迎刃而解了。

  2、代码重用:避免重复劳作,提供效率

函数的基本使用

  在Python中,定义一个函数要使用def语句,依次写出函数名、括号、括号中的参数和冒号:,然后,在缩进块中编写函数体,函数的返回值用return语句返回。

  我们以自定义一个求绝对值的函数为例:

  1. def jueduizhi(x):
  2. if x >= 0:
  3. return x
  4. else:
  5. return -x

  函数体内部的语句在执行时,一旦执行到return时,函数就执行完毕,并将结果返回。因此,函数内部通过条件判断和循环可以实现非常复杂的逻辑。

  如果没有return语句,函数执行完毕后也会返回结果,只是结果为Nonereturn None可以简写为return

  调用函数,那么只需要使用函数名加括号,就能执行,但如果函数定义了参数,那么必须在执行的时候传递参数给函授,否则会报异常!

  1. jueduizhi(-10)

函数的参数

函数的参数按照定义和传递的情况时分为形式参数和实际参数。
  1、形式参数:在定义函数时,函数名后面括号中的变量名称叫做形式参数,或者成为形参。
  2、实际参数:在调用函数时,函数名后面括号中的变量名称叫做实际参数,或者成为实参。
  PS:命名规则:两个单词的话,第二个单词大写,看起来比较清楚。
而形参又分为:位置参数,关键字参数,可变位置参数,可变关键字参数,命名关键字参数

默认参数

  def func(arg = 'value'),表示如果arg没有传值,那么它默认等于values,如果对某个参数设定了默须放在参数列表中的最后。
  特点:调用参数的时候非默认传递,可以根据默认值来预先编写函数逻辑
  注意:默认参数最好指向不变的对象
  对默认参数进行赋值的时候,可以用位置参数进行赋值,也可以用关键则参数进行赋值

可变参数(参数组)

  *args:表示参数可能是多个的,函数内部使用元祖tuple来存储这些参数

可变关键字参数

  **kargs:也表示参数是多个的,只是函数内部使用dict来存储这些参数,适用于var = value(关键字)的方式传值!
 
  主要区别:
    1、*args接受的是N个位置参数,用元祖存储
    2、**kwargs接受的是N个关键字参数,用字典存储
    注意:
      1、当函数接受可变参数的时候,如果我们刚好有一个list 或者tuple,可以直接在前面加上*,把元素变成可变参数进行传递
      2、如果已有字典要传递给函数的话,可以在传递的时候加上**,把字典的key,value变成关键字参数进行传递
      3、三个参数的位置不能调换,若同时存在arg,*argv,**kargv,必须先给arg赋值(除非它有默认值),然后才能给*argv和**kargv赋值。

命名关键字参数

  我们可以指定命名关键字参数进行传递,如果传如的关键字参数没有包含命名关键字参数,那么将会报错。
  如果函数有可变参数,那么可以在后面直接定义命名关键字参数,如果函数只有位置参数,那么命名关键字参数之前就需要添加*,来隔开,表示后面的为命名关键字参数
  1. def func(name,age,*,city,job):
  2. print(name,age,city,job)
  3. >>> func('daxin',22,city='beijing',job='linux')
  4. daxin 22 beijing linux
  这里可以指定命名关键字的默认值

函数的返回值

  return var,在函数的内部把某个结果进行返回,return之后直接跳出函数。
  返回值数量=0,即return(或者不写return语句),返回的数据为None。
  返回值数量=1,返回object(一个对象)。
  返回值数量>1,返回tuple(一个元组)。
  1. return的方式取得proc下的进程号
  2.  
  3. #!/usr/bin/env python
  4.  
  5. import os
  6.  
  7. PidFile = os.listdir('/proc')
  8.  
  9. def isPid(pid):
  10. if pid.isdigit():
  11. return True
  12. return False
  13.  
  14. for i in PidFile:
  15. if isPid(i):
  16. print i,

  注意:在函数中我们一般不会对结果进行打印,而是使用return把结果返回给调用它的地方。

函数的变量

函数的变量分为局部变量和全局变量,Python中的任何变量都有自己特定的作用域:

  1、在函数中定义的变量一般只能在该函数内部使用,这些只在程序的特定部分使用的变量叫做局部变量
  2、在一个文件顶部定义的变量可以供文件中任何函数调用,这些为整个程序所使用的变量叫做全局变量
调用规则
  1、全局变量可以在函数内部调用,但是不能修改,如果修改需要在函数内部使用 global x 来声明
  2、局部变量不能再函数外部生效,函数执行完毕自动销毁,但在函数内部可以使用global x 来声明局部变量达到全局使用的目的

三元运算符和匿名函数

正常情况下如果想要判断两个数字的大小,需要如下代码:
  1. if 1 > 3:
  2. print 'lt'
  3. else:
  4. print 'gt'
运用三元运算符:(三目运算符)
  1. print 'lt' if 1>3 else 'gt'

解读:

  如果 1大于3,那么返回lt,否则返回gt。这样写起来既简单,逼格又高。

匿名函数

  Python中的匿名函数一般指lambad,lambda 函数是一种快速定义单行的最小函数,可以用在任何需要函数的地方
  1. # 常规版本:
  2. def fun(x,y)
  3. return x*y
  4.  
  5. # lambda版本:
  6. r = lambda x,y:x*y
  7. print(r(1,2))
基本格式:
  1. lambda 参数列表:[表达式]

由于lambda返回的是函数对象(构建的是一个函数对象),所以可以定义一个变量去接收  

匿名函数优点:
  1、使用Python写一些脚本时,使用lambda可以省去定义函数的过程,让代码更加精简。
  2、对于一些抽象的,不会被别的地方再重复使用的函数,有时候函数起个名字也是个难题,使用lambda不需要考虑命名的问题
  3、使用lambda在某些时候然后代码更容易理解
  1. # 搭配reduce的应用
  2. # reduce(fun,list)
  3. # reduce依次把list中的数字赋值给fun进行计算
  4. # 注意fun必须是连个数字间的运算,list必须是整型数字
  5.  
  6. # 例:求1到100的累加
  7. reduce (lambda x,y:x + y,xrange(1,101)
  8.  
  9. # 应用:
  10. ret = (lambda x,y:x+y)(2,3)
  11. print(ret)
一般用在函数逻辑比较简单,在程序内基本不会重复调用的函数,节省代码量。

Python内置函数

  内建函数,Python内置的函数(build in function),不需要引用其他包,一般成为BIF.
  1. abs() # 计算绝对值,abs(-10),接收number,返回一个number
  2.  
  3. max() # 求序列的的最大值(可迭代的),同时也可以比较一些数字
  4.  
  5. min() # 求序列的最小值(可迭代的),同时也可以比较一些数字
  6.  
  7. len() # 求序列的长度,(字典也可以,求index的个数)
  8.  
  9. divmod(x,y) # 求x,y的商和余数,存放在元组中
  10.  
  11. pow(x,y,z) # 求x的y次方,如果有第三个参数,那么把前面的结果和第三个参数求余
  12.  
  13. round(number) # 用来四折五入,后面可以跟精度(先把number编程浮点数,然后看保留几位)把12.45转换成float,那么就不是12.45了,而可能是12.4999999了
  14.  
  15. callable() # 判断一个对象是否是可调用的,比如函数,类都是可以调用的,但是变量无法调用
  16.  
  17. type() # 查看对象的类型
  18.  
  19. isinstance(对象,类型) # 判断一个对象是否是给定类型。类型可以是多个,只要是其中1个即可(类型1,类型2)
  20.  
  21. cmpx,y # 比较两个对象的大小,x大于y返回1,x等于y返回-1,x小于y返回-1,字符串也可以比较,是按单个字符的大小开始比对。
  22.  
  23. str() # 可以把任何数据转换成字符串(字典,元组,也会直接输出)
  24.  
  25. hex(10) # 把10进制转换为8进制
  26.  
  27. eval() # 把字符串当做一个有效的表达式来求值
  28. # eval('1+2') 返回3
  29. # eval("[1,2,3]") 返回[1,2,3]
  30.  
  31. oct() # 把10进制转换为8进制
  32.  
  33. chr(i) # i的范围是0~255,求i对应的acsii码值
  34.  
  35. ord(i # i的范围是ascii的值,求对应的值
  36.  
  37. filter(函数或空,序列) # 用来过滤,把序列的每一个元素,交给函数来处理。如果为None,则什么也不做,直接输出(序列),如果有函数,那么只有函数的返回值为True才打印序列中的元素
  38. 例子:
  39. def even(n):
  40. if n % 2 == 0:
  41. return True
  42. filter(even,xrange(10))
  43. [0, 2, 4, 6, 8]
  44. 高级写法:
  45. filter(lambda x: x%2 ==0,xrange(10)
  46.  
  47. zip(seq1seq2,seqN...) # 把seq1和seq2组合成1个大的列表,每个序列取1个组成元组,存放在整合后的列表中,如果序列的长度不同,那么就以最小的序列的长度为基准。
  48.  
  49. map(func,seq1,seq2) # 返回也是一个列表,func可以是一个函数也可以是个None,如果为None,那么返回的列表长度以当前最长列表为基准,依旧是依次去每个列表中去取,只不过没有的,用none补充
  50. 例子:
  51. l1 = [1, 2, 3]
  52. l2 = ['a', 'b', 'c', 'd']
  53. l3 = ['I', 'II', 'III', 'IV', 'V', 'VI']
  54. map(None,l1,l2,l3)
  55. [(1, 'a', 'I'),
  56. (2, 'b', 'II'),
  57. (3, 'c', 'III'),
  58. (None, 'd', 'IV'),
  59. (None, None, 'V'),
  60. (None, None, 'VI')]
  61. # 如果函数位上是一个函数,那么如果只有1列表,那么就需要这个函数定义1个参数,然后每次把列表中的1个元素交给函数进行处理,并打印,或者保存在迭代器中去
  62. # 如果需要处理两个序列,那么函数就必须定义2个参数,去接受这两个序列的元素。
  63. # 高级应用:
  64. map(lambda x,y:x+y,l1,l4)
  65.  
  66. reduce(func,seq) # 只能定义1个序列,然后传递给func进行处理。(lambda函数求累加)

函数高级

主要说明一些函数的高级用法

函数对象   

函数是第一类对象,可以当作数据进行传递,具有如下特点
1、可以被引用

  1. def func():
  2. print('from func')
  3.  
  4. f = func #把函数地址当作变量一样进行传递
  5. f()

2、可以当作参数传递

  1. def func():
  2. print('from func')
  3.  
  4. def wapper(func):
  5. print('from wapper',func)
  6.  
  7. wapper(func) #把函数的地址作为变量传递给另一个函数

注意:把函数作为参数传入,这样的函数称为高阶函数.

3、返回值可以是函数

  1. def func():
  2. print('from func')
  3.  
  4. def wapper(func):
  5. return func
  6.  
  7. f = wapper(func) #把函数的内存地址传递,并返回,用f接收那么f就等于func的内存地址,那么加上括号就可以运行
  8.  
  9. f()

4、可以当作容器类型的元素

  1. def func():
  2. print('from func')
  3.  
  4. func_dict = {'func':func} #直接作为字典的值存储,那么调用函数就可以用 func_dict['func']() 直接进行调用了

函数嵌套

函数的嵌套主要分为嵌套调用,以及嵌套定义。

1、函数的嵌套调用

  1. def max2(a,b): #判断两个变量的最大值
  2. return a if a > b else b
  3.  
  4. def max4(a,b,c,d): #判断四个变量的最大值
  5. res1 = max2(a,b) #函数的嵌套调用
  6. res2 = max2(res1,c)
  7. res3 = max(res2,d)
  8. print(res3)
  9.  
  10. max4(10,100,21,99)

2、函数的嵌套定义

  1. def func1():
  2. print('from func1')
  3. def func2():
  4. print('from func2')
  5. def func3():
  6. print('from func3')
  7. func3() # 只有在func2中才能调用内部定义的函数func3
  8. func2()
  9.  
  10. func1()

注意:在函数的内部定义函数,所以内部函数的作用于就在外部函数内,在其他地方就无法进行调用

列表生成式

通过简洁的语法可以生成一个列表,或者对一组元素进行过滤,还可以对元素进行转换处理的式子。

  1. # 语法格式: [ exp for val in collection if condition ]
  2.  
  3. [ i for i in range(1,11) if i % 2 == 0 ]
  4.  
  5. # 列表生成式打印 1-10 中的偶数
  1. def func():
  2. a = []
  3. for i in range(1,11):
  4. if i % 2 == 0 :
  5. a.append(i)
  6. return a
  7.  
  8. print(func())

普通的方法获取1-10中的偶数

  通过列表生成式,我们可以直接创建一个列表,但是收到内存限制,列表容量肯定是有限的,而且创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前几个元素,那后面绝大多数元素占用的空间都白白浪费了。

  所以,如果列表元素是可以按照某周算法推算出来,那我们是否可以在循环过程中不断的推算处后续的元素呢?这样就不必创建完整的list,从而节省大量的空间,在Python中,这种一边循环一边计算的机制,成为生成器(generator)。

生成器

  要创建一个generator,有很多种方法,第一种方法是把一个列表生成器的[],换成(),就创建了一个生成器。
  生成器是一次生成一个值的特殊类函数,简单来说如果在函数的执行过程中使用yield关键字,那么这个函数就变成了一个生成器,yield语句会把需要的值返回给调用生成器的地方,然后退出函数,下一次调用生成器的时候又从上一次中断的地方开始执行,而生成器内的所有变量参数都会被保存下来,供下一次使用。 
  1. # 修改列表生成式,创建生成器
  2. a = ( i for i in range(1,11) if i % 2 == 0 )
  3.  
  4. # 使用yield关键字创建 生成器
  5. def func():
  6.  
  7. for i in range(1,11):
  8. if i % 2 == 0 :
  9. yield i

 包含yield语句的函数会被Python解释器翻译为生成器。当函数被调用时,返回的是一个生成器对象,这个对象支持迭代器借口,每当遇到yield关键字的时候,你可以理解成函数的return语句,yield后面的值,就是返回的值,但不是想一般的函数在return后退出函数,生成器函数在生成值后会自动刮起并记录当前执行的状态,在函数恢复时会从上一次yield语句的后面继续执行后面的语句,直到遇到下一个yield语句。

区别:

  • 一个直接返回了表达式的结果列表,而另一个是一个对象,该对象包含了对表达式结果的计算引用,通过循环可以直接输出。
  • 生成器不会一次性列出所有的数据,当你用到的时候,在列出来,更加节约内存。
  • 如果想要列出所有的数据,可以使用for循环,或者直接使用list(),来创建。

迭代器

重复的过程为迭代,每次重复既一次迭代,并且每次迭代的结果是下一次迭代的初始值,为什么要用迭代器? 使没有索引的数据类型,依然能够通过循环,迭代去获取数据的方式.

可迭代对象

可迭代的对象,具有 __iter__ 方法的对象,而执行 __iter__ 方法,那么对象就变成了迭代器。迭代器没有索引,只能通过 __next__ 方法来获取元素,每执行一次,获取一个元素,当迭代器被获取完毕,__next__ 会抛出异常:StopIteration,表示没有值了
例子:
  迭代一个字典,对于字典进行迭代,那么默认只能获取字典的key,但是可以通过其他方法来获取字典的value

  1. dic = {'a':1,'b':2,'c':3}
  2. d = dic.__iter__()
  3. while True:
  4. try:
  5. key = d.__next__() #获取字典的key
  6. print(dic[key]) #通过key获取value
  7. except StopIteration:
  8. break

扩展:
  1)既然一个对象的长度可以用len,或者用对象的 __len__()方法,其实执行len(对象),其实就是在执行对象的 __len__ 方法
  2)那么把一个对象转换为迭代器,不仅仅可以用对象的 __iter__(),也可以使用iter(对象),来进行转换
  3)获取迭代器的元素,不仅仅可以用 __next__(),也可以用next(对象)

迭代器的特点

1、如何判断对象是可迭代对象,还是迭代器对象  

  1. from collections import Iterable,iterator
  2. print(isinstance('abc',Iterable))
  3.  
  4. # collections里面放着python内置的扩展的数据类型
  5. # 通过导入特殊的数据类型来进行判断

2、可迭代的数据类型

只要对象含有__iter__方法,执行__iter__方法,可以得到迭代器对象,列表,元祖,字典,字符串,集合,文件描述符 (可以对可迭代对象执行__iter__方法来变成迭代器)

3、迭代器协议

  1)对象有__next__,__iter__方法称为迭代器
  2)对于迭代器对象来说,执行__iter__得到的结果,仍然是它本身。(for循环有关)

4、for循环原理

  1)遵循迭代器协议,执行对象的__iter__方法,然后利用__next__(next)去获取元素
  2)并且会帮我们捕捉异常,并且进行break
  3)所以for循环的对象必须具有__iter__方法(可迭代对象变成了迭代器,而迭代器执行__iter__还是迭代器)
  4)for循环又称为迭代循环

5、迭代器的优点和缺点

  优点:
    1)提供了一种不依赖下标的迭代方式(非序列对象可以被迭代)
    2)就迭代器本身来说,更节省内存(只有对迭代器进行next方法,才会读取下一个值)
  缺点:
    1)迭代器只能被迭代一次,既一次性的,不如序列类型灵活
    2)只能往后取值,不能往前倒退
    3)无法获取迭代器对象的长度

装饰器

  如果我们想在一个已经上了线的项目上的某个函数上添加一个功能,但是又不希望更改函数的源代码,这种在代码运行期间动态增加功能的方式,称之为“装饰器”(Decorator)。

  本质上,decorator就是一个返回函数的高阶函数。所以,我们要定义一个能打印函数运行时间的decorator。

  1. import time
  2.  
  3. def timer(func):
  4.  
  5. def wapper():
  6. start_time = time.time()
  7. res = func()
  8. end_time = time.time()
  9. return res,(end_time - start_time)
  10. return wapper
  11.  
  12. @timer # 在被装饰函数上添加 Python 特有的语法棒棒糖表示,装饰后面的函数
  13. def index():
  14.  
  15. time.sleep(3)
  16. return 'hello index'
  17.  
  18. print(index())

 @timer:表示 index = timer(index) , 其实就是把原来的index函数给偷偷替换了。 

这个时候会出现一个问题,我们都知道使用func.__name__会打印当前函数的名称,而虽然我们偷偷替换了index函数,但是在打印func.__name__的时候,还是会打印wapper,那是因为我们真正执行的是wapper函数,那么有些依赖函数签名的代码执行就会出错。

所以这里在wapper函数上添加Python内置装饰器,来继承该属性

  1. import time
  2. import functools # 需要引入代码包
  3.  
  4. def timer(func):
  5. @functools.wraps(func) # 继承函数的__name__等属性
  6. def wapper():
  7. start_time = time.time()
  8. res = func()
  9. end_time = time.time()
  10. return res,( end_time - start_time )
  11. return wapper
  12.  
  13. @timer
  14. def index():
  15.  
  16. time.sleep(3)
  17. return 'hello index'
  18.  
  19. print(index.__name__)

Python学习笔记 - day6 - 函数的更多相关文章

  1. Python学习笔记之函数

    这篇文章介绍有关 Python 函数中一些常被大家忽略的知识点,帮助大家更全面的掌握 Python 中函数的使用技巧 1.函数文档 给函数添加注释,可以在 def 语句后面添加独立字符串,这样的注释被 ...

  2. 小甲鱼:Python学习笔记003_函数

    >>> # 函数>>> def myFirstFunction(params1,params2...): print("这是我的第一个函数!") ...

  3. Python学习笔记系列——函数

    今年下半年的计划主要是Python和Mysql了,公司不方便看书和视频,就照着廖雪峰的Python网站开始看了.以下纯为个人笔记记录,若是想系统学习的小伙伴还是看这里的好一些,毕竟系统.https:/ ...

  4. Python学习笔记(五)函数和代码复用

    函数能提高应用的模块性,和代码的重复利用率.在很多高级语言中,都可以使用函数实现多种功能.在之前的学习中,相信你已经知道Python提供了许多内建函数,比如print().同样,你也可以自己创建函数, ...

  5. python学习笔记(4)--函数

    1.函数 函数是指将一组语句的集合通过一个名字封装起来.要想执行这个函数,只需调用其函数名即可. 函数的特性: 1.减少重复代码 2.使程序变的课扩展 3.使程序变得易维护 语法定义: def pri ...

  6. python学习笔记-Day6(3)

    代码书写原则: 1)不能重复写代码 2)写的代码要经常变更 编程模式概述 面向过程:根据业务逻辑从上到下写垒代码 函数式:将某功能代码封装到函数中,日后便无需重复编写,仅调用函数即可 面向对象:对函数 ...

  7. python学习笔记-Day6(2)

    xml处理模块 xml是实现不同语言或程序之间进行数据交换的协议,跟json差不多,但json使用起来更简单,不过,古时候,在json还没诞生的黑暗年代,大家只能选择用xml呀,至今很多传统公司如金融 ...

  8. Python学习笔记-Day3-python函数

    1.为什么要用函数? 提高代码重复利用率,减少代码冗余.封装模块化代码,便于调用 2.函数声明定义(注意:函数先声明后调用) 注意:函数的reture循环中的exit功能一样(函数不执行,终止) 函数 ...

  9. Python学习笔记11—函数

    建立第一个函数 /usr/bin/env Python #coding:utf-8 def add_function(a,b): c = a+b print c if __name__==" ...

随机推荐

  1. 每天一个Linux命令(12):su命令

    su命令用于切换当前用户身份到其他用户身份,变更时须输入所要变更的用户帐号与密码. 语法: su(选项)(参数) 选项: -c<指令>或--command=<指令>:执行完指定 ...

  2. Xshell6连接虚拟机(一)

    普通用户转换成管理员: 一.首先进入终端: 1.输入:    su   然后回车 2.若输入密码 则显示认证失败,说明还是普通管理员身份. (1)设置新密码:        sudo passwd r ...

  3. java设计模式之命令模式以及在java中作用

    命令模式属于对象的行为模式.命令模式又称为行动(Action)模式或交易(Transaction)模式. 命令模式把一个请求或者操作封装到一个对象中.命令模式允许系统使用不同的请求把客户端参数化,对请 ...

  4. 软件工程项目组Z.XML会议记录 2013/11/20

    软件工程项目组Z.XML会议记录 [例会时间]2013年11月20日星期三21:00-22:00 [例会形式]小组讨论 [例会地点]学生公寓3号楼会客厅 [例会主持]李孟 [会议记录]李孟 会议整体流 ...

  5. [译]如何根据条件从pandas DataFrame中删除不需要的行?

    问题来源:https://stackoverflow.com/questions/13851535/how-to-delete-rows-from-a-pandas-dataframe-based-o ...

  6. [转]Hexo博客添加访问统计 - 记录

    引入不蒜子 <script async src="//dn-lbstatics.qbox.me/busuanzi/2.3/busuanzi.pure.mini.js"> ...

  7. sql between and 边界问题

    1.不同的数据库对 BETWEEN...AND 操作符的处理方式是有差异的.需要自己测试 2.一般情况下.SQL Server中 between and是包括边界值的,not between不包括边界 ...

  8. mysql初始(6)

    随着mysql的运用不断加深,一些更复杂点的用法又需要总结起来. 1.将一个表中的数据插入到另一个表中: a.两张表字段相同,并且数据全部插入,命令如下:  INSERT INTO 目标表 SELEC ...

  9. chromium源码阅读

    linux下chromium的入口函数在文件:src/chrome/app/chrome_exe_main_aura.cc 中 int main(int argc, const char** argv ...

  10. Spring Data学习(一):初识

    目录 前言 添加Spring Data 配置pom.xml 配置数据库相关信息(application.properties) 配置数据库信息 配置自动根据实体类在数据库创建表 创建User.java ...