一、函数的基本知识

定义: 函数是指将一组语句的集合通过一个名字(函数名)封装起来,要想执行这个函数,只需调用其函数名即可

特性:

  1. 减少重复代码
  2. 使程序变的可扩展
  3. 使程序变得易维护

1.1函数定义规则:

  • 函数代码块以 def 关键词开头,后接函数标识符名称和圆括号 ()
  • 任何传入参数和自变量必须放在圆括号中间,圆括号之间可以用于定义参数。
  • 函数的第一行语句可以选择性地使用文档字符串—用于存放函数说明。
  • 函数内容以冒号起始,并且缩进。
  • return [表达式] 结束函数,选择性地返回一个值给调用方。不带表达式的return相当于返回 None。

1.2语法格式:

  1. def 函数名(参数列表):
  2. 函数体

1.3函数的参数:

  • 默认参数
  • 位置参数
  • 关键参数
  • 非固定参数  *args 和 **kwargs

默认参数:

调用函数时,如果没有传递参数,则会使用默认参数。

  1. #可写函数说明
  2. def printinfo( name, age = 35 ):
  3. "打印任何传入的字符串"
  4. print ("名字: ", name);
  5. print ("年龄: ", age);
  6. return;
  7.  
  8. #调用printinfo函数
  9. printinfo( age=50, name="runoob" );
  10. print ("------------------------")
  11. printinfo( name="runoob" );

默认参数实例

位置参数:

注意: 位置参数的顺序不可变。

关键字参数:

关键字参数和函数调用关系紧密,函数调用使用关键字参数来确定传入的参数值。

使用关键字参数允许函数调用时参数的顺序与声明时不一致,因为 Python 解释器能够用参数名匹配参数值。

  1. def printme( str ):
  2. "打印任何传入的字符串"
  3. print (str);
  4. return;
  5.  
  6. #调用printme函数
  7. printme( str = "菜鸟教程");

关键字参数实例1

关键字参数的使用不需要指定顺序

  1. #可写函数说明
  2. def printinfo( name, age ):
  3. "打印任何传入的字符串"
  4. print ("名字: ", name);
  5. print ("年龄: ", age);
  6. return;
  7.  
  8. #调用printinfo函数
  9. printinfo( age=50, name="runoob" );

关键字参数实例2

非固定参数:

非固定参数或者不定长参数,上述3种参数不同,声明时不会命名,基本语法:

  1. def functionname([formal_args,] *var_args_tuple ):
  2. "函数_文档字符串"
  3. function_suite
  4. return [expression]

加了星号(*)的变量名会存放所有未命名的变量参数。如果在函数调用时没有指定参数,它就是一个空元组。我们也可以不向函数传递未命名的变量。

  1. # 可写函数说明
  2. def printinfo( arg1, *vartuple ):
  3. "打印任何传入的参数"
  4. print ("输出: ")
  5. print (arg1)
  6. for var in vartuple:
  7. print (var)
  8. return;
  9.  
  10. # 调用printinfo 函数
  11. printinfo( 10 );
  12. printinfo( 70, 60, 50 );

不定长参数实例

需要注意:

  1. 关键参数必须放在位置参数之后。
  2. *args 会把多传入的位置参数变成一个元组(tuple)形式
  3. *kwargs 会把多传入的关键参数变成一个字典dict形式

1.4全局与局部变量:

在子程序中定义的变量称为局部变量,在程序的一开始定义的变量称为全局变量。
全局变量作用域是整个程序,局部变量作用域是定义该变量的子程序。
当全局变量与局部变量同名时:
在定义局部变量的子程序内,局部变量起作用;在其它地方全局变量起作用。
 
只要有点编程基础,全局和局部变量的概念就应该理解。就不过多赘述了....
需要注意的:
  • 对于数字和字符串来说在函数内部默认是不能更改全局变量的
  • 如果非要在函数内硬改全局变量,需要在函数内添加 global 函数名,具体见下面global实例1
  • 但是这种做法并不推荐
Tuple本身不可更改,所以除了数字类型、字符串类型、元组类型,列表和字典在函数内部调用是可以更改的,具体见实例2
  1. myname = "Rong"
  2.  
  3. def change_name():
  4. global myname #不推荐,不要用
  5. myname = "TanRong"
  6.  
  7. change_name()
  8. print(myname)

global实例1

  1. names_list = ["Jack","Tom","xiaohong"]
  2. info_dict = {"name": "Jack", "age":18, "sex":"女"}
  3.  
  4. def change_name():
  5. # global myname
  6. # myname = "TanRong"
  7. names_list[0] = "xiaoming"
  8. info_dict["age"] = 20
  9.  
  10. change_name()
  11. # print(myname)
  12. print(names_list)
  13. print(info_dict)
  14.  
  15. 输出:
  16. ['xiaoming', 'Tom', 'xiaohong']
  17. {'name': 'Jack', 'age': 20, 'sex': '女'}

实例2

1.5返回值:

  1. 函数在执行过程中只要遇到return语句,就会停止执行并返回结果,so 也可以理解为 return 语句代表着函数的结束
  2. 如果未在函数中指定return,那这个函数的返回值为None 

二、特殊函数

2.1递归函数:

在函数内部,可以调用其他函数。如果一个函数在内部调用自身本身,这个函数就是递归函数。

  1. def calc(n):
  2. print(n)
  3. if int(n/2) ==0:
  4. return n
  5. return calc(int(n/2))
  6.  
  7. calc(10)
  8.  
  9. 输出:
  10. 10
  11. 5
  12. 2
  13. 1

Python实例

递归特性:

1. 必须有一个明确的结束条件,, 默认深度好像是999

2. 每次进入更深一层递归时,问题规模相比上次递归都应有所减少

3. 递归效率不高,递归层次过多会导致栈溢出(在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出)

  1. data = [1, 3, 6, 7, 9, 12, 14, 16, 17, 18, 20, 21, 22, 23, 30, 32, 33, 35]
  2.  
  3. def binary_search(dataset,find_num):
  4. print(dataset)
  5.  
  6. if len(dataset) >1:
  7. mid = int(len(dataset)/2)
  8. if dataset[mid] == find_num: #find it
  9. print("找到数字",dataset[mid])
  10. elif dataset[mid] > find_num :# 找的数在mid左面
  11. print("\033[31;1m找的数在mid[%s]左面\033[0m" % dataset[mid])
  12. return binary_search(dataset[0:mid], find_num)
  13. else:# 找的数在mid右面
  14. print("\033[32;1m找的数在mid[%s]右面\033[0m" % dataset[mid])
  15. return binary_search(dataset[mid+1:],find_num)
  16. else:
  17. if dataset[0] == find_num: #find it
  18. print("找到数字啦",dataset[0])
  19. else:
  20. print("没的分了,要找的数字[%s]不在列表里" % find_num)
  21.  
  22. binary_search(data,66)

递归函数实际应用案例,二分查找

2.2嵌套函数:

顾名思义,函数内定义并调用函数

  1. name = "Tan"
  2. def change_name():
  3. name = "Tan2"
  4.  
  5. def change_name2():
  6. name = "Tan3"
  7. print("第3层打印", name)
  8.  
  9. change_name2() # 调用内层函数
  10. print("第2层打印", name)
  11.  
  12. change_name()
  13. print("最外层打印", name)

嵌套函数实例

修改嵌套作用域:

要修改嵌套作用域(enclosing 作用域,外层非全局作用域)中的变量则需要 nonlocal 关键字了

  1. def outer():
  2. myage = 118
  3.  
  4. def inner():
  5. nonlocal myage # nonlocal关键字声明
  6. myage = 126
  7. print(myage)
  8. inner()
  9. print(myage)
  10.  
  11. outer()
  12.  
  13. 输出:
  14. 126
  15. 126

nonlocal实例

2.3匿名函数:

python 使用 lambda 来创建匿名函数。

所谓匿名,意即不再使用 def 语句这样标准的形式定义一个函数。

  • lambda 只是一个表达式,函数体比 def 简单很多。
  • lambda的主体是一个表达式,而不是一个代码块。仅仅能在lambda表达式中封装有限的逻辑进去。
  • lambda 函数拥有自己的命名空间,且不能访问自己参数列表之外或全局命名空间里的参数。
  • 虽然lambda函数看起来只能写一行,却不等同于C或C++的内联函数,后者的目的是调用小函数时不占用栈内存从而增加运行效率。

语法如下:

  1. lambda [arg1 [,arg2,.....argn]]:expression
  1. sum = lambda a,b: a + b
  2. print(sum(30,50))

匿名函数实例1

  1. res = map(lambda x:x**2, [1,2,3,4,5])
  2. for i in res:
  3. print(i)
  4.  
  5. 输出:
  6. 1
  7. 4
  8. 9
  9. 16
  10. 25

匿名函数实例2

2.4高阶函数

变量可以指向函数,函数的参数能接收变量,那么一个函数就可以接收另一个函数作为参数,这种函数就称之为高阶函数。

  1. def add(x,y,f):
  2. return f(x) + f(y)
  3.  
  4. res = add(3,-6,abs)
  5. print(res)

高阶函数实例

2.5内置函数

Built-in Functions    
abs() dict() help() min() setattr()
all() dir() hex() next() slice()
any() divmod() id() object() sorted()
ascii() enumerate() input() oct() staticmethod()
bin() eval() int() open() str()
bool() exec() isinstance() ord() sum()
bytearray() filter() issubclass() pow() super()
bytes() float() iter() print() tuple()
callable() format() len() property() type()
chr() frozenset() list() range() vars()
classmethod() getattr() locals() repr() zip()
compile() globals() map() reversed() __import__()
complex() hasattr() max() round()  
delattr() hash() memoryview() set()  

详解:https://docs.python.org/3/library/functions.html?highlight=built#ascii

  1. #compile
  2. f = open("函数递归.py")
  3. data =compile(f.read(),'','exec')
  4. exec(data)
  5.  
  6. #print
  7. msg = "又回到最初的起点"
  8. f = open("tofile","w")
  9. print(msg,"记忆中你青涩的脸",sep="|",end="",file=f)
  10.  
  11. # #slice
  12. # a = range(20)
  13. # pattern = slice(3,8,2)
  14. # for i in a[pattern]: #等于a[3:8:2]
  15. # print(i)
  16. #
  17. #
  18.  
  19. #memoryview
  20. #usage:
  21. #>>> memoryview(b'abcd')
  22. #<memory at 0x104069648>
  23. #在进行切片并赋值数据时,不需要重新copy原列表数据,可以直接映射原数据内存,
  24. import time
  25. for n in (100000, 200000, 300000, 400000):
  26. data = b'x'*n
  27. start = time.time()
  28. b = data
  29. while b:
  30. b = b[1:]
  31. print('bytes', n, time.time()-start)
  32.  
  33. for n in (100000, 200000, 300000, 400000):
  34. data = b'x'*n
  35. start = time.time()
  36. b = memoryview(data)
  37. while b:
  38. b = b[1:]
  39. print('memoryview', n, time.time()-start)

内置函数实例

Python6 - 函数总结的更多相关文章

  1. 一起入门python6之函数

    今天我们来学习新的一篇吧,那便是“函数(function)”我们用def来定义一个函数,以案例说话.>>> def name(x):          #定义一个“name”的函数. ...

  2. 自学Python之路-Python基础+模块+面向对象+函数

    自学Python之路-Python基础+模块+面向对象+函数 自学Python之路[第一回]:初识Python    1.1 自学Python1.1-简介    1.2 自学Python1.2-环境的 ...

  3. 自学Python6.1-模块简介

    自学Python之路-Python基础+模块+面向对象自学Python之路-Python网络编程自学Python之路-Python并发编程+数据库+前端自学Python之路-django 自学Pyth ...

  4. 自学Python6.2-类、模块、包

    自学Python之路-Python基础+模块+面向对象自学Python之路-Python网络编程自学Python之路-Python并发编程+数据库+前端自学Python之路-django 自学Pyth ...

  5. 自学Python6.3-内置模块(1)

    自学Python之路-Python基础+模块+面向对象自学Python之路-Python网络编程自学Python之路-Python并发编程+数据库+前端自学Python之路-django 自学Pyth ...

  6. python全栈开发 生成器 :生成器函数,推导式及生成器表达式

    python 全栈开发 1.生成器函数 2.推导式 3.生成器表达式 一.生成器函数 1.生成器: 生成器的本质就是迭代器 (1)生成器的特点和迭代器一样.取值方式和迭代器一样(__next__(), ...

  7. Day 14 列表推导式、表达器、内置函数

    一. 列表推导式# l1 = []# for i in range(1,11):# l1.append(i)# print(l1)# #输出结果:[1, 2, 3, 4, 5, 6, 7, 8, 9, ...

  8. 巨蟒python全栈开发-第12天 生成器函数 各种推导式 yield from

    一.今日主要内容总览(重点) 1.生成器(目的:帮助我们创建对象) (1)生成器的本质就是迭代器 (2)一个一个的创建对象 (3)创建生成器的方式: 1.生成器函数 2.通过生成器表达式来获取生成器 ...

  9. python 基础篇 14 程程器表达式 内置函数

    昨日内容回顾    可迭代对象:        内部含有__iter__方法的就是可迭代对象.        可迭代对象不能取值,因为内部不含有__next__方法.     可迭代对象 ---> ...

随机推荐

  1. 洛谷 P2257 YY的GCD

    洛谷 P2257 YY的GCD \(solution:\) 这道题完全跟[POI2007]ZAP-Queries (莫比乌斯反演+整除分块) 用的一个套路. 我们可以列出答案就是要我们求: \(ans ...

  2. _vimrc(VimScript脚本语言学习)

    Windows下 syntax on "高亮 "缩进 set cindent "set cin set smartindent "set si set auto ...

  3. 微信小程序的页面渲染(if/for)

    下面,粗略的介绍一下微信小程序的条件渲染.列表渲染.数据绑定等,详细的内容大家可以去看微信小程序的API,在此只做简单描述,希望能帮助到大家 条件渲染 <!--wxml--> <vi ...

  4. PLSQL_day01

    declare begin  dbms_output.put_line('Hello world') end;

  5. JS window对象的top、parent、opener含义介绍

    1.top该变更永远指分割窗口最高层次的浏览器窗口.如果计划从分割窗口的最高层次开始执行命令,就可以用top变量. 2.openeropener用于在window.open的页面引用执行该window ...

  6. 使用密钥认证机制远程登录Linux

    密钥认证机制 创建存放key的文件 1)创建目录 /root/.ssh 并设置权限 [root@localhost ~]# mkdir /root/.ssh mkdir 命令用来创建目录,以后会详细介 ...

  7. Salt Document学习笔记1

    原文来自Salt Documentation,作者是 Thomas Hatch),我摘抄部分可能今后会用到或适合入门到精通的一些原文段落,简单翻译后发上来,便于查阅和研究 一.原理方面:The net ...

  8. 【转】assert预处理宏与预处理变量

    assert assert是一个预处理宏,由预处理器管理而非编译器管理,所以使用时都不用命名空间声明,如果你写成std::assert反而是错的.使用assert需要包含cassert或assert. ...

  9. svn数据库自动备份脚本

    创建一个存放备份数据的路径 mkdir /data/svnbak -p 采用shell脚本的方式实现自动备份 #vim backup.sh #!/bin/bash log="/data/sv ...

  10. discuz3.4:在Centos6.5中安装过程

    参考文章:https://www.cnblogs.com/hehongbin/articles/5741270.html https://www.cnblogs.com/mitang/p/552454 ...