一、函数的定义

函数是第一类对象,即函数可以当作数据传递

#1 可以被引用
#2 可以当作参数传递
#3 返回值可以是函数
#3 可以当作容器类型的元素

1. 定义方式

def 函数名(参数1,参数2,参数3,...):
    '''注释'''
    函数体
    return 返回的值

2. 函数的返回值

  无return->None

  return1个值->返回1个值

  return 逗号分隔多个值->元组

二、函数的调用

1. 调用的方法

函数的调用:函数名加括号

  • 先找到名字
  • 根据名字调用代码

2. 先定义,再调用

函数即“变量”,“变量”必须先定义后引用。未定义而直接引用函数,就相当于在引用一个不存在的变量名
#测试一
def foo():
print('from foo')
bar()
foo() #报错 #测试二
def bar():
print('from bar')
def foo():
print('from foo')
bar()
foo() #正常 #测试三
def foo():
print('from foo')
bar() def bar():
print('from bar')
foo() #会报错吗? #结论:函数的使用,必须遵循原则:先定义,后调用
#我们在使用函数时,一定要明确地区分定义阶段和调用阶段 #定义阶段
def foo():
print('from foo')
bar()
def bar():
print('from bar')
#调用阶段
foo()

三、函数的参数

1. 位置参数

按照从左到右的顺序定义的参数

  位置形参:必选参数

  位置实参:按照位置给形参传值

2、关键字参数

按照key=value的形式定义的实参无需按照位置为形参传值 ,

注意的问题:

  1. 关键字实参必须在位置实参右面

  2. 对同一个形参不能重复传值

3、默认参数

形参在定义时就已经为其赋值可以传值也可以不传值,经常需要变得参数定义成位置形参,变化较小的参数定义成默认参数(形参)

注意的问题:

  1. 只在定义时赋值一次

  2. 默认参数的定义应该在位置形参右面

  3. 默认参数通常应该定义成不可变类型

4. 可变长参数

可变长指的是实参值的个数不固定, 而实参有按位置和按关键字两种形式定义,针对这两种形式的可变长,形参对应有两种解决方案来完整地存放它们,分别是*args,**kwargs

def test(x, *args, **kwargs):
print(x)
print(args)
print(kwargs)
test(1, *[2, 3, 4, 5], **{'y': 2, 'z': 3}) 运行结果:
1
(2, 3, 4, 5)
{'y': 2, 'z': 3}
def test(x, *args, **kwargs):
print(x)
print(args)
print(kwargs)
test(1, 2, 3, 4, 5, y=2, z=3) 运行结果:
1
(2, 3, 4, 5)
{'y': 2, 'z': 3}

四、全局变量和局部变量

顶头写的是全局变量

函数内部的是局部变量

global指定全局变量

nonlocal指定上一级的变量

name = "刚娘"
def weihou():
name = "陈卓"
def weiweihou():
global name # global,指定全局变量
name = "冷静" weiweihou()
print(name) print(name)
weihou()
print(name) # 刚娘
# 陈卓
# 冷静
name = "刚娘"
def weihou():
name = "陈卓"
def weiweihou():
nonlocal name # nonlocal,指定上一级变量,如果没有就继续往上直到找到为止
name = "冷静" weiweihou()
print(name) print(name)
weihou()
print(name) # 刚娘
# 冷静
# 刚娘

五、风湿理论(函数即变量)

# def foo():
# print('from foo')
# bar()
#
# foo()
# 报错 # def bar():
# print('from bar')
# def foo():
# print('from foo')
# bar()
#
# foo()
# 不报错 # def foo():
# print('from foo')
# bar()
#
# def bar():
# print('from bar')
# foo()
# 不报错 # def foo():
# print('from foo')
# bar()
#
# foo()
#
# def bar():
# print('from bar')
# 报错

六、递归

1. 定义

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

def calc(n):
print(n)
if n // 2 == 0:
return
return calc(n / 2)
calc(10) 10
5.0
2.5
1.25

递归函数的优点是定义简单,逻辑清晰。理论上,所有的递归函数都可以写成循环的方式,但循环的逻辑不如递归清晰。

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

七、函数的作用域

1. 作用域即范围

  - 全局范围(内置名称空间与全局名称空间属于该范围):全局存活,全局有效
    - 局部范围(局部名称空间属于该范围):临时存活,局部有效

2. 作用域关系是在函数定义阶段就已经固定的,与函数的调用位置无关

x=1
def f1():
def f2():
print(x)
return f2
x=100
def f3(func):
x=2
func()
x=10000
f3(f1())

3. 查看作用域:globals(),locals()

LEGB 代表名字查找顺序: locals -> enclosing function -> globals -> __builtins__
locals 是函数内的名字空间,包括局部变量和形参
enclosing 外部嵌套函数的名字空间(闭包中常见)
globals 全局变量,函数定义所在模块的名字空间
builtins 内置模块的名字空间

八、匿名函数

匿名函数lambda x: x * x实际上就是:

def f(x):
return x * x

关键字lambda表示匿名函数,冒号前面的x表示函数参数。

匿名函数有个限制,就是只能有一个表达式,不用写return,返回值就是该表达式的结果。

用匿名函数有个好处,因为函数没有名字,不必担心函数名冲突。此外,匿名函数也是一个函数对象,也可以把匿名函数赋值给一个变量,再利用变量来调用该函数:

>>> f = lambda x: x * x
>>> f
<function <lambda> at 0x101c6ef28>
>>> f(5)
25

同样,也可以把匿名函数作为返回值返回,比如:

def build(x, y):
return lambda: x * x + y * y

最新文章

  1. Visual Studio SetSite failed for package [JavaScriptWebExtensionsPackage] 错误解决方案一则
  2. UIView 的属性opaque详解
  3. c# -- 对象销毁和垃圾回收
  4. Laravel教程 三:视图变量传递和Blade
  5. ASP.NET实现弹出框真分页将复选框选择的数据存到数据库中(四)
  6. HD1049Climbing Worm
  7. java 方法调用绑定--《java编程思想》学习笔记
  8. 微软职位内部推荐-Principal Dev Manager for Windows Phone Shell
  9. 自定义UITableViewCell时, 使用autoLayout, 无法很好的做到屏幕适配
  10. java 利用java运行时的方法得到当前屏幕截图的方法(转)
  11. 团队 / Staff_VidaMiaTangoClub_新浪博客
  12. 搜集朋友写的几篇Android Elf相关的文档
  13. 安装apache报没有找到VCRUNTIME40.dll错误
  14. 纯代码实现wordpress文章隐藏内容评论可见
  15. json进阶(一)js读取解析JSON类型数据
  16. $mount方法是用来挂载我们的Vue.extend扩展的
  17. 《Linux 性能及调优指南》2.4 基准工具
  18. springboot中@EnableAsync与@Async注解使用
  19. UIVisualEffectView(高斯模糊效果)
  20. Dream------Hadoop--HDFS的设计

热门文章

  1. WorkFlow三:配BO对象,事件触发工作流
  2. kubernetes学习Service之headless和statefulSet结合
  3. 源码升级SUSE openssh
  4. lua 的匹配规则
  5. linux查看磁盘类型(是否SSD盘)
  6. 201871010131张兴盼《面向程序设计(java)》第四周学习总结
  7. django 修改 request 对象中的请求参数, 并重新赋值给 request 对象
  8. Jenkins集成allure测试报告
  9. NOIP 2013 火柴排队
  10. python基础之三:int、bool、str