Python学习之函数(二)

1.函数(变量)作用域

Python 中,程序的变量并不是在哪个位置都可以访问的,访问权限决定于这个变量是在哪里赋值的。

变量的作用域决定了在哪一部分程序可以访问哪个特定的变量名称。Python的作用域一共有4种,分别是:

  • L (Local) 局部作用域
  • E (Enclosing) 闭包函数外的函数中
  • G (Global) 全局作用域
  • B (Built-in) 内建作用域

以 L –> E –> G –>B 的规则查找,即:在局部找不到,便会去局部外的局部找(例如闭包),再找不到就会去全局找,再者去内建中找。

x = int(2.9)  # 内建作用域
 
test1 = 0  # 全局作用域
def outer():
    test2 = 1  # 闭包函数外的函数中
    def inner():
       test3 = 2  # 局部作用域

Python 中只有模块(module),类(class)以及函数(def、lambda)才会引入新的作用域,其它的代码块(如 if/elif/else/、try/except、for/while等)是不会引入新的作用域的,也就是说这些语句内定义的变量,外部也可以访问,如下代码:

>>> if True:
...  msg = 'I am from Run'
... 
>>> msg
'I am from Run'
>>> 

实例中 msg 变量定义在 if 语句块中,但外部还是可以访问的。

如果将 msg 定义在函数中,则它就是局部变量,外部不能访问:

>>> def test():
...     msg_inner = 'I am from Runoob'
... 
>>> msg_inner
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'msg_inner' is not defined
>>> 

从报错的信息上看,说明了 msg_inner 未定义,无法使用,因为它是局部变量,只有在函数内可以使用。

2.匿名函数

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

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

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

lambda 函数的语法只包含一个语句,如下:

lambda [arg1 [,arg2,.....argn]]:expression
1.普通函数:
def calc(x):
    return x+1

res=calc(10)
print(res)          ==》         11

print(calc)         ==》         <function calc at 0x00000015026A3E18>


2.匿名函数:
print(lambda x:x+1)      ==》       # <function <lambda> at 0x0000008CC1233E18>

func=lambda x:x+1
print(func(10))          ==》         11           

3. 函数式编程

编程的方法论:面向对象;函数式; 面向对象

函数式编程特性:

不可变数据 ;第一类对象;  尾调用优化(尾递归)

# 把函数当做参数传给另外一个函数
def foo(n):         #n=bar
    print(n)

def bar(name):
    print('my name is %s' %name)


foo(bar)           # 返回bar的地址<function bar at 0x000000DDDE7D4158>
foo(bar())        #缺少参数报错

foo(bar('alex'))   ==>my name is alex
                                None   {注:foo(bar)没有return所以返回None}

4.高阶函数:1.函数接收的参数是一个函数名 2.返回值中包含函数

5.尾调用:在函数的最后一步调用另外一个函数(最后一行不一定是函数的最后一步)

6.map函数

array=[1,3,4,71,2]

ret=[]
for i in array:
    ret.append(i**2)
print(ret)                   ==》[1, 9, 16, 5041, 4]

#如果我们有一万个列表,那么你只能把上面的逻辑定义成函数
def map_test(array):
    ret=[]
    for i in array:
        ret.append(i**2)
    return ret

print(map_test(array))            ==》[1, 9, 16, 5041, 4]

#如果我们的需求变了,不是把列表中每个元素都平方,还有加1,减一,那么可以这样
def add_num(x):
    return x+1
def map_test(func,array):
    ret=[]
    for i in array:
        ret.append(func(i))
    return ret

print(map_test(add_num,array))     ==》[2, 4, 5, 72, 3]
#可以使用匿名函数
print(map_test(lambda x:x-1,array))      ==》[0, 2, 3, 70, 1]


#上面就是map函数的功能,map得到的结果是可迭代对象
print(map(lambda x:x-1,range(5)))   ==》<map object at 0x0000000001D75550>
num_l=[1,2,10,5,3,7]

def map_test(func,array):             #func=lambda x:x+1    arrary=[1,2,10,5,3,7]
    ret=[]
    for i in array:
        res=func(i) #add_one(i)
        ret.append(res)
    return ret

print(map_test(lambda x:x+1,num_l))           ==》[2, 3, 11, 6, 4, 8]

res=map(lambda x:x+1,num_l)
print('内置函数map,处理结果',res)               ==》内置函数map,处理结果 <map object at 0x0000000002730CC0>


#注:map(--,--)  第二个参数不一定必须是列表,可迭代即可,函数精简时第一个参数用匿名函数格式比较好

msg='rongxj'
print(list(map(lambda x:x.upper(),msg)))      ==》['R', 'O', 'N', 'G', 'X', 'J']                #函数式编程通常只用一行代码书写简单但易读性差

7.filter函数 

#电影院聚集了一群看电影bb的傻逼,让我们找出他们
movie_people=['alex','wupeiqi','yuanhao','sb_alex','sb_wupeiqi','sb_yuanhao']

def tell_sb(x):
    return x.startswith('sb')


def filter_test(func,array):
    ret=[]
    for i in array:
        if func(i):
            ret.append(i)
    return ret

print(filter_test(tell_sb,movie_people))       ==》['sb_alex', 'sb_wupeiqi', 'sb_yuanhao']


#函数filter,返回可迭代对象
print(filter(lambda x:x.startswith('sb'),movie_people))      ==》<filter object at 0x00000000021EE160>

res=filter(lambda x:not x.startswith('sb'),movie_people)
print(list(res))                    ==》['alex', 'wupeiqi', 'yuanhao']

res=filter(lambda x: x.startswith('sb'),movie_people)
print(list(res))                     ==》['sb_alex', 'sb_wupeiqi', 'sb_yuanhao']

8.reduce函数

列表数相加:
num_l=[1,2,3,100]
res=0
for num in num_l:
    res+=num

print(res)                               ==》106
列表数相加(函数方式):
num_l=[1,2,3,100]
def reduce_test(array):
    res=0
    for num in array:
        res+=num
    return res

print(reduce_test(num_l))        ==》106

#列表数相乘:
num_l=[1,2,3,100]
def reduce_test(func,array):
    res=array.pop(0)
    for num in array:
        res=func(res,num)
    return res

print(reduce_test(lambda x,y:x*y,num_l))        ==》600
#在100的基础上乘以列表的值:
num_l=[1,2,3,100]
def reduce_test(func,array,init=None):
    if init is None:
        res=array.pop(0)
    else:
        res=init
    for num in array:
        res=func(res,num)
    return res

print(reduce_test(lambda x,y:x*y,num_l,100))     ==》60000

#reduce函数
from functools import reduce                     #需导入此模块
num_l=[1,2,3,100]
print(reduce(lambda x,y:x+y,num_l,1))               ==》107
print(reduce(lambda x,y:x+y,num_l))                  ==》106 
小结三种函数:

map原有基础上加工数据,处理序列中的每个元素,得到的结果是一个‘列表’,该‘列表’元素个数及位置与原来一样

filter筛选列表值,遍历序列中的每个元素,判断每个元素得到布尔值,如果是True则留下

reduce合并数据,得到最终结果;处理一个序列,然后把序列进行合并操作

#reduce用来计算1到100的和
from functools import reduce
print(reduce(lambda x,y:x+y,range(100),100))     ==》5050     #后面的100是给一个初始值
print(reduce(lambda x,y:x+y,range(1,101)))       ==》5050

  

 

  

  

 

posted @ 2018-07-13 17:01  一只小妖  阅读(99)  评论(0)    收藏  举报