Python-Basis-8th 函数的创建 函数的参数 函数的返回值 函数的作用域 高阶函数  递归函数 内置函数

周三,晴,记录生活分享点滴

参考博客1:https://www.cnblogs.com/yuanchenqi/articles/5828233.html

参考博客2:https://www.cnblogs.com/alex3714/articles/5740985.html

参考网站3:https://www.runoob.com/python3/python3-namespace-scope.html

Python版本:3.5

定义

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

特性

1. 减少重复代码

2. 方便修改,使程序变的可扩展

3. 保持代码一致性,使程序变得易维护

语法定义

def sayhi():#函数名
    print("Hello, I'm nobody!")
 
sayhi() #调用函数

函数的参数

形参、实参

形参:变量只有在被调用时才分配内存单元,在调用结束时,即刻释放所分配的内存单元。因此,形参只在函数内部有效。函数调用结束返回主调用函数后则不能再使用该形参变量

实参:可以是常量、变量、表达式、函数等,无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形参。因此应预先用赋值,输入等办法使参数获得确定值

小结:形参是模子,实参是例子

Python-Basis-8th
函数的创建
函数的参数
函数的返回值
函数的作用域
高阶函数 
递归函数
内置函数

位置参数

参数传入函数的顺序不能被改变,即name对应chung,age对应23

def f(name,age):
 
    print('I am %s,I am %d'%(name,age))
 
f('Chung',23)
f('Zack',30)

关键字参数

正常情况下,给函数传参数要按顺序,不想按顺序就可以用关键参数,只需指定参数名即可,但记住一个要求就是...(看下面)

def f(name,age):
 
    print('I am %s,I am %d'%(name,age))
 
# f(16,'alvin') #报错
f(age=16,name='chung')

在定义参数时,即第一行,关键参数必须放在位置参数之后

def f(name, age, sex='male'):
#def f(sex='male',name, age ):  # 报错:非默认参数跟随默认参数
    print('I am %s,I am %d, a %s' % (name, age, sex))

f('chung',23 )

默认参数

参数在调用时不指定,就是默认参数,指定了的话,就用指定的值。

其中默认参数是占一个位置的,例如下面的male为默认参数,在brother打印的时候,会有出现三组数据占三个位置。

def print_info(name, age, sex='male'):
    print('Name:%s' % name)
    print('age:%s' % age)
    print('Sex:%s' % sex)
    return

print_info('brother', 23)  #没有指定性别,默认参数为男,即male
# Name:brother
# age:23
# Sex:male
print_info('sister', 18, 'female')  #指定性别,默认参数失效,即female
# Name:sister
# age:22
# Sex:female

非固定/不定长参数

若你的函数在定义时不确定用户想传入多少个参数,就可以使用非固定/不定长参数。

无命名参数在左边,有命名参数放右边

*arge 参数变元组

def stu_register(name,age,*args): # *args 会把多传入的参数变成一个元组形式
    print(name,age,args)
 
stu_register("chung",23)
#输出
#chung 23 () #后面这个()就是args,只是因为没传值,所以为空
 
stu_register("Jack",32,"CN","Python")
#输出
# Jack 32 ('CN', 'Python')

**kwargs 参数变字典

def stu_register(name, age, *args, **kwargs):  # **kwargs 会把多传入的参数变成一个dict形式
    print(name, age, args, kwargs)

stu_register("chung", 23)
# 输出
# chung 23 () {}  # 后面这个{}就是kwargs,只是因为没传值,所以为空

stu_register("Jack", 32, "CN", "Python", sex="Male", province="ShanDong")
# 输出
# Jack 32 ('CN', 'Python') {'province': 'ShanDong', 'sex': 'Male'}

单独输出元组或字典格式

def f(*args):
    print(args) 
f(*[1,2,5])  # (1, 2, 5)
 
def f(**kwargs):
    print(kwargs)
f(**{'name':'alex'})  # {'name': 'alex'}

函数的返回值

要想获取函数的执行结果,就可以用return语句把结果返回

注意:

  1. 函数在执行过程中只要遇到return语句,就会停止执行并返回结果,so 也可以理解为 return 语句代表着函数的结束
  2. 如果未在函数中指定return,那这个函数的返回值为None  
  3. return多个对象,解释器会把这多个对象组装成一个元组作为一个一个整体结果输出。
def foo():
    return 1, 'chung', [2, 3, 4]

    print('hello')  # 证实第一点,return代表函数结束,无法输出运行print('hello')

print(foo())  # (1, 'chung', [2, 3, 4])  # 证实第三点,无论return内容是什么格式,都将以元组的格式返回

  

函数的作用域

作用域的介绍

python中的作用域分4种情况,从里到外依次是:

L:local,局部作用域,即函数中定义的变量;(当前)

E:enclosing,嵌套的父级函数的局部作用域,即包含此函数的上级函数的局部作用域,但不是全局的;(外部)

G:global,全局变量,就是模块级别定义的变量;(全局)

B:built-in,系统固定模块里面的变量,比如int, bytearray等。(内置)

搜索变量的优先级顺序依次是:作用域局部>外层作用域>当前模块中的全局>python内置作用域,也就是 L > E > G > B

Python-Basis-8th
函数的创建
函数的参数
函数的返回值
函数的作用域
高阶函数 
递归函数
内置函数

g_count = 0  # 全局作用域
def outer():
    o_count = 1  # 闭包函数外的函数中
    def inner():
        i_count = 2  # 局部作用域 

全局变量和局部变量

定义在函数内部的变量拥有一个局部作用域,定义在函数外的拥有全局作用域。

局部变量只能在其被声明的函数内部访问,而全局变量可以在整个程序范围内访问。

调用函数时,所有在函数内声明的变量名称都将被加入到作用域中。

total = 0  # 这是一个全局变量

# 可写函数说明
def sum(arg1, arg2):
    # 返回2个参数的和
    total = arg1 + arg2  # total在这里是局部变量.
    print("函数内是局部变量 : ", total)
    return total

# 调用sum函数
sum(10, 20)
print("函数外是全局变量 : ", total)

# 函数内是局部变量 :  30
# 函数外是全局变量 :  0

global 和 nonlocal关键字

global

当修改的变量是在全局作用域(global作用域)上的,就要使用global先声明一下

global关键字声明的变量必须在全局作用域上,不能嵌套作用域上

count = 10
def outer():
    global count
    print(count)  # 如果没有global声明,提示错误:局部变量“count”在赋值之前被引用,表示如果没有global,此时count为局部变量
    count = 100
    print(count)
outer()
#10
#100

nonlocal

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

def outer():
    count = 10
    def inner():
        nonlocal count
        count = 20  # 通过 nonlocal 将 10 改成 20
        print(count)
    inner()
    print(count)
outer()
#20
#20

小结

1. 变量查找顺序:LEGB,作用域局部>外层作用域>当前模块中的全局>python内置作用域;

2. 只有模块、类、及函数才能引入新作用域;

3. 对于一个变量,内部作用域先声明就会覆盖外部变量,不声明直接使用,就会使用外部作用域的变量;

4. 内部作用域要修改外部作用域变量的值时,全局变量要使用global关键字,嵌套作用域变量要使用nonlocal关键字。nonlocal是python3新增的关键字,有了这个 关键字,就能完美的实现闭包了。 

 

高阶函数 

函数名可以进行赋值

函数名可以作为函数参数,还可以作为函数的返回值

def f(n):
    return n*n
    
def foo(a, b, func):  # 因为print中含有f函数,所以foo中的func里面的运行规则是 f 

    ret = func(a)+func(b)
    return ret

print(foo(1, 2, f))

# 返回结果为 5 

递归函数

特性

1. 可以调用自身的函数

2. 有一个结束条件

3. 可以用递归函数解决的也都可以用循环解决

4. 递归函数的效率在大多情况下偏低

阶乘

循环

#阶乘计算用循环的方式来写

def factorial(n):
    result = n
    for i in range(1, n):
        result *= i

    return result  # 24

print(factorial(4))

递归

# 阶乘计算用递归的方式来写

def factorial(n):
    if n == 1:
        return 1
    return n * factorial(n - 1)  # 24

print(factorial(4))

斐波那契数列

循环

# 斐波那契   循环

def fibo(n):
    before = 0
    after = 1
    for i in range(n - 1):
        ret = before + after
        before = after
        after = ret

    return ret  # 2

print(fibo(3))

递归

# 斐波那契   递归

def fibo_new(n):  # n可以为零,数列有[0]

    if n <= 1:
        return n
    return (fibo_new(n - 1) + fibo_new(n - 2))  # 2

print(fibo_new(3))

  

内置函数

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()

重要的内置函数

filter(function, sequence)

对sequence中的item依次执行function(item),将执行结果为True的item做成一个filter object的迭代器返回。可以看作是过滤函数。

str = ['a', 'b','c', 'd']
 
def fun1(s):
    if s != 'a':
        return s
 
ret = filter(fun1, str)
 
print(list(ret))# ret是一个迭代器对象

map(function, sequence) 

对sequence中的item依次执行function(item),将执行结果组成一个map object迭代器返回.

str = [1, 2,'a', 'b']
 
def fun2(s):
 
    return s + "alvin"
 
ret = map(fun2, str)
 
print(ret)      #  map object的迭代器
print(list(ret))#  ['aalvin', 'balvin', 'calvin', 'dalvin']

map也支持多个sequence,这就要求function也支持相应数量的参数输入:

ef add(x,y):
    return x+y
print (list(map(add, range(10), range(10))))##[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

reduce(function, sequence, starting_value)

对sequence中的item顺序迭代调用function,如果有starting_value,还可以作为初始值调用

from functools import reduce
 
def add1(x,y):
    return x + y
 
print (reduce(add1, range(1, 101)))## 4950 (注:1+2+...+99)
 
print (reduce(add1, range(1, 101), 20))## 4970 (注:1+2+...+99+20)

lambda

匿名函数的命名规则,用lamdba 关键字标识,冒号(:)左侧表示函数接收的参数(a,b) ,冒号(:)右侧表示函数的返回值(a+b)。

因为lamdba在创建时不需要命名,所以叫匿名函数

#普通函数
def add(a,b):
    return a + b
print add(2,3)  # 5

#匿名函数
add = lambda a,b : a + b
print add(2,3)  # 5