什么是函数

函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段。

函数的定义与调用

  1. def my_len():
  2. s = 'hello world'
  3. length = 0
  4. for i in s:
  5. length = length + 1
  6. print(length)
  7. my_len()

Python
Copy

  1. 定义:def 关键词开头,空格之后接函数名称和圆括号(),最后还有一个":"
  2.    def 是固定的,不能变,他就是定义函数的关键字。
  3.    空格 为了将def关键字和函数名分开,必须空(四声),当然你可以空2格、3格或者你想空多少都行,但正常人还是空1格。
  4.    函数名:函数名只能包含字符串、下划线和数字且不能以数字开头。虽然函数名可以随便起,但我们给函数起名字还是要尽量简短,并能表达函数功能
  5.    括号:是必须加的,先别问为啥要有括号,总之加上括号就对了!
  6. 注释:每一个函数都应该对功能和参数进行相应的说明,应该写在函数下面第一行。以增强代码的可读性。
  7. 调用:就是 函数名() 要记得加上括号。

函数的返回值

  1. def my_len():
  2. s = 'hello world'
  3. length = 0
  4. for i in s:
  5. length = length + 1
  6. return length
  7. str_len = my_len()
  8. print(str_len)

Python
Copy
return 关键字的作用

  • return 是一个关键字,这个词翻译过来就是“返回”,所以我们管写在 return 后面的值叫“返回值”。
  • 不写 return 的情况下,会默认返回一个 None
  • 一旦遇到 return,结束整个函数。
  • 返回的多个值会被组织成元组被返回,也可以用多个值来接收
    1. def ret_demo():
    2. return 1,2,'a',['hello','world']
    3. ret = ret_demo()
    4. print(ret)
    Python
    Copy

    函数的参数

    带参数的函数
    1. def my_len(s):
    2. length = 0
    3. for i in s:
    4. length += 1
    5. return length
    6. ret = my_len('hello world!')
    7. print(ret)
    Python
    Copy
    实际的要交给函数的内容,简称实参。
    在定义函数的时候它只是一个形式,表示这里有一个参数,简称形参。 
  1. 按照位置传值:位置参数

    1. def maxnumber(x,y):
    2. the_max = x if x > y else y
    3. return the_max
    4. ret = maxnumber(10,20)
    5. print(ret)

    Python
    Copy

  2. 按照关键字传值:关键字参数。

    1. def maxnumber(x,y):
    2. the_max = x if x > y else y
    3. return the_max
    4. ret = maxnumber(y = 10,x = 20)
    5. print(ret)

    Python
    Copy

  3. 位置、关键字形式混着用:混合传参。

    1. def maxnumber(x,y):
    2. the_max = x if x > y else y
    3. return the_max
    4. ret = maxnumber(10,y = 20)
    5. print(ret)

    Python
    Copy
    位置参数必须在关键字参数的前面
    对于一个形参只能赋值一次

  4. 默认参数。

    1. def stu_info(name,age = 18):
    2. print(name,age)
    3. stu_info('aaron')
    4. stu_info('song',50)

    Python
    Copy

  5. 默认参数是一个可变数据类型

    1. def demo(a,l = []):
    2. l.append(a)
    3. print(l)
    4. demo('abc')
    5. demo('123')

    Python
    Copy

  6. 动态参数

    1. def demo(*args,**kwargs):
    2. print(args,type(args))
    3. print(kwargs,type(kwargs))
    4. demo('aaron',1,3,[1,3,2,2],{'a':123,'b':321},country='china',b=1)
    5. #动态参数,也叫不定长传参,就是你需要传给函数的参数很多,不定个数,那这种情况下,你就用*args,**kwargs接收,args是元祖形式,接收除去键值对以外的所有参数,kwargs接收的只是键值对的参数,并保存在字典中。

    Python
    Copy

    命名空间和作用域

    代码在运行伊始,创建的存储“变量名与值的关系”的空间叫做全局命名空间;
    在函数的运行中开辟的临时的空间叫做局部命名空间。
    命名空间一共分为三种:

  • 全局命名空间
  • 局部命名空间
  • 内置命名空间

取值顺序:

  • 在局部调用:局部命名空间 -> 全局命名空间 -> 内置命名空间
  • 在全局调用:全局命名空间 -> 内置命名空间

作用域

  • 全局作用域:包含内置名称空间、全局名称空间,在整个文件的任意位置都能被引用、全局有效
  • 局部作用域:局部名称空间,只能在局部范围内生效

globals 和 locals 方法

  1. print(globals())
  2. print(locals())
  3. def func():
  4. a = 12
  5. b = 20
  6. print(globals())
  7. print(locals())
  8. func()

Python
Copy
global

  1. 声明一个全局变量。
  2. 在局部作用域想要对全局作用域的全局变量进行修改时,需要用到 global(限于字符串,数字)。

    1. def func():
    2. global a
    3. a = 3
    4. func()
    5. print(a)
    6. count = 1
    7. def search():
    8. global count
    9. count = 2
    10. search()
    11. print(count)

    Python
    Copy
    对可变数据类型(list,dict,set)可以直接引用不用通过 global

    1. li = [1,2,3]
    2. dic = {'name':'aaron'}
    3. def change():
    4. li.append(4)
    5. dic['age'] = 18
    6. print(dic)
    7. print(li)
    8. change()
    9. print(dic)
    10. print(li)

    Python
    Copy
    nonlocal

  3. 不能修改全局变量。

  4. 在局部作用域中,对父级作用域(或者更外层作用域非全局作用域)的变量进行引用和修改,并且引用的哪层,从那层及以下此变量全部发生改变。

    1. def add_b():
    2. b = 1
    3. def do_global():
    4. b = 10
    5. print(b)
    6. def dd_nolocal():
    7. nonlocal b # 应用了上一层的变量b
    8. b = b + 20
    9. print(b) # 发生了改变
    10. dd_nolocal() # 调用函数,导致do_global的命名空间b也改变了
    11. print(b)
    12. do_global()
    13. print(b)
    14. add_b() # 最上面一层没有变化

    Python
    Copy

    函数的嵌套和作用域链

    1. def mymax(x,y):
    2. m = x if x > y else y
    3. return m
    4. def maxx(a,b,c,d):
    5. res1 = mymax(a,b)
    6. res2 = mymax(res1,c)
    7. res3 = mymax(res2,d)
    8. return res3
    9. ret = maxx(23,453,12,-13)
    10. print(ret)

    Python
    Copy

    1. def f1():
    2. print("in f1")
    3. def f2():
    4. print("in f2")
    5. f2()
    6. f1()

    Python
    Copy

    函数名的本质

    函数名本质上就是函数的内存地址

  5. 可以被引用

    1. def func():
    2. print('in func')
    3. f = func
    4. print(f)
    5. f()

    Python
    Copy

  6. 可以被当作容器类型的元素

    1. def f1():
    2. print('f1')
    3. def f2():
    4. print('f2')
    5. def f3():
    6. print('f3')
    7. l = [f1,f2,f3]
    8. d = {'f1':f1,'f2':f2,'f3':f3}
    9. #调用
    10. l[0]()
    11. d['f2']()

    Python
    Copy

  7. 可以当作函数的参数和返回值

    1. def f1():
    2. print('f1')
    3. def func(argv):
    4. argv()
    5. return argv
    6. f = func(f1)
    7. f()

    Python
    Copy

    闭包

    1. def func():
    2. name = 'aaron'
    3. def inner():
    4. print(name)
    5. return inner
    6. f = func()
    7. f()

    Python
    Copy
    内部函数包含对外部作用域而非全剧作用域变量的引用,该内部函数称为闭包函数
    判断闭包函数的方法 closure

    1. def func():
    2. name = 'aaron'
    3. def inner():
    4. print(name)
    5. print(inner.__closure__)
    6. return inner
    7. f = func()
    8. f()
    9. # 最后运行的结果里面有cell就是闭包
    10. name = 'aaron'
    11. def func():
    12. def inner():
    13. print(name)
    14. print(inner.__closure__)
    15. return inner
    16. f = func()
    17. f()
    18. # 输出结果为None,说明不是闭包

    Python
    Copy

    1. def wrapper():
    2. money = 1000
    3. def func():
    4. name = 'apple'
    5. def inner():
    6. print(name,money)
    7. return inner
    8. return func
    9. f = wrapper()
    10. i = f()
    11. i()

    Python
    Copy

    1. def func(a,b):
    2. def inner(x):
    3. return a*x + b
    4. return inner
    5. func1 = func(4,5)
    6. func2 = func(7,8)
    7. print(func1(5),func2(6))

    Python
    Copy

    1. from urllib.request import urlopen
    2. def func():
    3. content = urlopen('http://myip.ipip.net').read()
    4. def get_content():
    5. return content
    6. return get_content
    7. code = func()
    8. content = code()
    9. print(content.decode('utf-8'))
    10. content2 = code()
    11. print(content2.decode('utf-8'))