我们前面学的都是面向过程式的编程(代码从上到下写,并运行),而函数式编程是将繁杂的代码通过整理特性进行规整。像图书馆一样,将小说、教学、外文等书籍进行分类。让编程人员或看代码人员很容易的查看该段代码的特性。并且可以重复的利用该段代码进行相同的操作、像图书馆书是公用的一样,谁都可以去看,这样又能便于观察又能重复使用,是日后主要使用的技术。

def test():         #设置一个函数名称
#test #注释函数作用
print('函数式编程') #函数程序处理逻辑
return 0 #定义返回值,如果没有定义将返回None
test() #调用

函数:

1. 可以在调用时,在括号内放入参数,里面有(位置参数,关键字参数,混合参数,默认参数,汇总参数)

2. 位置参数必须要在关键字参数前面。

位置参数:

将参数一一对应,并传入到函数中:

def func(a,b,c):
print(a,c,b)
func(1,2,3) #将1=>a,2=>b,3=>c

关键字参数:

将特定的参数以赋值形式对应起来。

def func(a,b,c):
print(a,c,b)
func(a=1,b=2,c=8)

混合参数(位置参数与关键字参数)

不能写在位置参数的前面:

def func(a,b,c):
print(a,c,b)
test(3,b=2,c=1) √
test(c=1,2) X

默认参数:
调用函数的时候,默认参数非必须传递。
如果再没有定义其他,就以默认的来。

在定义默认值时:不可变类型随便传,但可变类型需要注意:

def test(x,y=1):
print(y) test(2)

汇总参数:

1. *args:接收N个位置参数,转换成元组的形式。

def test1(x,*args):
  print(x)
  print(args)
test1(1,2,3,4,5,6) & test1(1,*[2,3,4,5,6]) #这里的*后面的列表是将列表内容提取并重新赋值给元组,以元组形式输出。

2. **kwargs:把N个关键字参数,转换成字典的方式。

def test1(x,**kwargs):
print(x)
print(kwargs)
# test1(1,name='3',age=20)
test1(2,name='xuan',age=9)
test1(1,**{'name':"xuan",'age':20}) #将字典内容提取,在重新赋值给函数内的kwargs
2
{'name': 'xuan', 'age': 9}
1
{'name': 'xuan', 'age': 20}

作用域:

在Python中,一个函数就是一个作用域,而所有的函数都挂靠在.py文件的总作用域中。

在这里写的代码分为:全局作用域和局部作用域

1. 全局作用域

  • 要使用全大写形式定义变量名称,为了将局部变量做标识。
  • 局部作用域全部挂靠在全局作用域内
NAME = 'a1'
def func():
name = 'a2'
print(name)
print(NAME)
func()

2. 局部作用域:

  • 局部作用域可以调用全局作用域。局部和局部,全局和局部不能调用。
  • 局部作用域之间无法调用,可以使用父作用域。
def change_name(name): #一个函数叫做一个作用域,
  print('before change',name)
  name='XB'
  print('after change',name) name = 'xb'
change_name(name)
print(name)

global:

在局部作用域中,进行全局作用域内容的查找,并可以修改。(只能修改可变类型,不可变类型为局部内重新赋值)

NAME = 'a1'
def func():
global NAME
NAME = 'bbb'
func()
print(NAME)

nonlocal:

在子局部作用域中,进行对父级局部作用域的内容查找不更改全局作用域内容,并可以修改。(同样修改可变类型,不可变类型为局部内重新赋值)

NAME = 'a1'
def func():
NAME = '111'
def func2():
nonlocal NAME
NAME = 'bbb'
func2()
print(NAME)
func()
print(NAME)

返回值:

在函数中使用return来进行函数这个子作用域的返回值的关键字。其中:

1. 默认如果没有return,但定义了取值变量的话,默认为None。

def papa():
print('111')
a = papa() #a就是None

2. 如果只有一个返回值,那么就返回相应的数值和数据类型。如果有多个返回值,那么将返回一个元组。

def papa():
dic = {'k1':'v1'}
return dic #将返回字典类型
return {'k1':'v1'},{'k1':'v1'},{'k1':'v1'} #将返回元组类型 a = papa()
print(a)

3. 返回值同样可以返回另一个函数的内存对象地址

def a():
print('111')
def papa():
return a #返回一个内存对象地址,返回后可以直接运行。
b = papa()
b()lam

lambda

用于表示简单的函数时,可以使用lambda来进行,其中需要注意的:

1. 只能用一行来表示lambda

2. 只能用参数传的值,而不能自己定义一个变量。

使用lambda默认就会有一个return。

a = lambda : 1+1   #将1+1的结果返回到a中。
print(a())

lambda可以搭配三元运算使用:

a = lambda : 1 if 1+1 == 2  else 2   #判断如果1+1等于2的话,那么返回1,否则返回2
print(a())

其他:

lis = lambda : [ i for i in range(10) if i%3 == 0 ]   #循环1-10,判断其中哪些为3整除,添加到列表中,生成一个lambda。
print(lis())

闭包:

闭包是嵌套在函数中的函数,而闭包必须是内层函数对外层函数的变量(非全局变量)的引用。

为函数创建一个区域(内部变量供自己使用)为以后执行提供数据。

#实例
li = []
def func(new_value):
li.append(new_value)
total = sum(li)
return total/len(li)
print(func(1000))
print(func(2000))
print(func(5000)) #那么问题来了,li是全局变量,我可以在全局随意更改。
li = []
def func(new_value):
li.append(new_value)
total = sum(li)
return total/len(li)
print(func(1000))
print(func(2000))
li.append(120301)
print(func(5000))
#得出来的结果就大不相同了。如何有解决办法,那就是把li放到函数的小作用域里。 def func(new_value):
li = []
li.append(new_value)
total = sum(li)
return total/len(li)
print(func(1000))
print(func(2000))
print(func(5000))
#这样一来,每次运行函数,就会新生成一个新的列表出来。那么值就没有变化了。接下来如何解决这个问题。闭包就来了。 def func():
li = []
def func1(new_value):
li.append(new_value)
total = sum(li)
return total/len(li)
return func1
func = func()
print(func(1000))
print(func(2000))
print(func(5000)) #这样一来,即不会出现全局模式更改的问题,也不会担心列表重新生成的问题。这就是比好。

其中,下面一块区域叫做闭包:

    li = []
def func1(new_value):
li.append(new_value)
total = sum(li)
return total/len(li)

我们可以通过查看函数内是否有自由变量来侧面证明是不是闭包。

def func():
li = []
def func1(new_value):
li.append(new_value)
total = sum(li)
return total/len(li)
return func1
func = func()
print(func.__code__.co_freevars) #查看函数的自由变量
#('li',)
print(func.__code__.co_varnames) #查看函数的局部变量
#('new_value', 'total')

函数需要注意的点:

1. 根据数据类型的不同,有些是有返回值的,有些是没有返回值的。

lis = []
def a():
return lis.append('111')
b = a()
print(b) #由于列表形式的添加是没有返回值的,所以返回的是None
lis = '123'
def a():
return lis + '321'
b = a()
print(b) #由于字符串是有返回值的,所以返回的是所需值

2. 需要判断是传入函数内存地址还是函数的return的值。

def func():
print('1111')
return 0
lis = [func,func,func] #这里传入的是函数的内存地址。不是执行结果。
for item in lis:
print(item) #打印的是内存地址
'''
<function func at 0x000001D8489B9550>
<function func at 0x000001D8489B9550>
<function func at 0x000001D8489B9550>
'''
def func():
return 0
lis = [func(),func(),func()] #这里传入的是运行完func的返回值
for item in lis:
print(item) #打印的是0
'''
0
0
0
'''

3. 闭包问题

def func(name):
v = lambda x:x+name
return v v1 = func('武沛齐')
v2 = func('alex')
v3 = v1('银角')
v4 = v2('金角')
print(v1,v2,v3,v4)
result = []
for i in range(10):
func = lambda : i # 注意:函数不执行,内部代码不会执行。
result.append(func) print(i)
print(result)
v1 = result[0]()
v2 = result[9]()
print(v1,v2)
def func(num):
def inner():
print(num)
return inner result = []
for i in range(10):
f = func(i)
result.append(f) print(i)
print(result)
v1 = result[0]()
v2 = result[9]()
print(v1,v2)

4. 实参与形参

传参的类型是否为可变类型,如果可变类型,那么实参也会一起改变,如果是不可变类型,那么就会重新创建一个方法内部变量。

###########传入不可变类型############
def func(a):
a += 1
print(id(a))
a = 7
func(a)
print(id(a))
print(a) #判断ID输出是否一样,a输出的结果?
############传入可变类型################### def func(a):
a[0] = 8
print(id(a))
a = [1,2,3]
func(a)
print(id(a))
print(a)
#判断ID输出是否一样,a输出的结果?

函数中的那些坑:

1. 函数中有定义一个空列表作为形参:

def a(b,lis=[])

问题:在没有传入新的列表当做实参时,将会使用定义好的空列表,那么将会导致多个没有定义的实参重复调用该空列表。这将导致数据内容不一致的问题。

def b(a,lis=[]):
for i in range(a):
lis.append(i*i)
print(lis)
b(3)
b(3)
b(3)
'''
[0, 1, 4]
[0, 1, 4, 0, 1, 4]
[0, 1, 4, 0, 1, 4, 0, 1, 4]
'''

可以传参时传入一个自己的空列表,那么就将使用自己传入的空列表。

def b(a,lis=[]):
for i in range(a):
lis.append(i*i)
print(lis)
b(3,[])
b(3,[])
b(3,[])
'''
[0, 1, 4]
[0, 1, 4]
[0, 1, 4]
'''

如何解决这类问题,要么就删除空列表,要么就进行判断。

def b(a,lis=[]):
if lis:
lis = []
for i in range(a):
lis.append(i*i)
print(lis)
b(3,[])
b(3,[])
b(3)
b(3)
b(3)
'''
[0, 1, 4]
[0, 1, 4]
[0, 1, 4]
'''

 

Python——函数&作用域的更多相关文章

  1. Python函数作用域的查找顺序

    函数作用域的LEGB顺序 1.什么是LEGB? L:local 函数内部作用域 E:enclosing 函数内部与内嵌函数之间 G:global 全局作用域 B:build-in 内置作用域 2.它们 ...

  2. python函数作用域,嵌套函数,闭包

    函数作用域                                                                                                ...

  3. python函数作用域LEGB

    我们的在学习Python函数的时候,经常会遇到很多定义域的问题,全部变量,内部变量,内部嵌入的函数,等等,Python是如何查找的呢?以及Python又是按照什么顺序来查找的呢?这里做一个顺序的说明 ...

  4. python函数作用域

    python中函数作用域 在python中,一个函数就是一个作用域 name = 'xiaoyafei' def change_name(): name = '肖亚飞' print('在change_ ...

  5. python函数作用域,闭包,装饰器

    第一:函数作用域: L:local 函数内部作用域 E:enclosing       函数内部与内嵌函数之间(闭包) G:global            全局作用域 B:build_in    ...

  6. 07.python函数作用域global、nonlocal、LEGB

    函数作用域 作用域 一个标识符的课件范围,这就是标识符的作用域,一般常说的是变量的作用域 def foo():    x = 100 print(x) # 可以访问到吗 上例中x不可以访问到,会抛出异 ...

  7. Python函数作用域和匿名函数

    匿名函数的定义 全局变量和局部变量的概念 global(全局变量)和 nonlocal(局部变量) 闭包.递归.回调 匿名函数 匿名函数  lambda 语法规则:lambda   参数 : 表达式 ...

  8. python函数 -- 作用域,异常处理

    1.def语句和参数 python定义函数的关键词为def,格式如下: def 函数名([变元],[变元],....)          #保存在变元中的值,在函数返回后该变元就会被销毁了. 2.返回 ...

  9. python函数-作用域

    可以把作用域”看成是变量的容器.当作用域被销毁时,所有保存在该作用 域内的变量的值就被丢弃了,只有一个全局作用域,它是在程序开始时创建的.如 果程序终止,全局作用域就被销毁,它的所有变量就被丢弃了. ...

随机推荐

  1. EOS测试链智能合约部署调用

    ETH与EOS两者智能合约进行简单的对比. 1.编译智能合约(合约编译成.wasm与.abi格式后即可部署到区块链) [root@C03-12U-26 testcontract]# cat testc ...

  2. laravel composer 使用阿里云镜像

    使用composer安装错误提示: 即: [Composer\Downloader\TransportException] The "https://packagist.laravel-ch ...

  3. WebAPI.请求(Request)的参数(Parameter)里包含特殊字符(#等)的正确处理方式 从客户端xx中检测到有潜在危险的Request.Form值

    事故现场 报错"从客户端 中检测到有潜在危险的Request.Form值" //后台代码 namespace Test { [RoutePrefix("TestClass ...

  4. EasyNVS摄像机公网全终端无插件网页摄像机直播管理服务运行出现“请求服务不存在或已停止”

    背景分析 了解我们产品线的小伙伴都知道,EasyNVR产品主要用于互联网安防直播,通过EasyNVR拉取摄像机的RTSP视频流,客户端通过访问EasyNVR服务端就可以实现音视频流分发.在此情况下会出 ...

  5. C++基础 (杂七杂八的汇总 )

    继承:继承就是新类从已有类那里得到已有的特性. 类的派生指的是从已有类产生新类的过程.原有的类成为基类或父类,产生的新类称为派生类或子类. 多态:将基类类型的指针或者引用指向派生类型的对象.多态通过虚 ...

  6. 手机端rem无限适配

    参考文档: http://blog.csdn.net/xwqqq/article/details/54862279 https://github.com/amfe/lib-flexible/tree/ ...

  7. [资料]ObjectARX 2020参考指南翻译中文版

    chm使用Google Chrome浏览器翻译,有些翻译不是很理想,因为2万5千多个html文件, 修正难度太大,所以只处理了一部分. 非常感谢 gzxl 辛苦肉眼修正一些翻译问题. 欢迎进入QQ群: ...

  8. 最新 梆梆安全java校招面经 (含整理过的面试题大全)

    从6月到10月,经过4个月努力和坚持,自己有幸拿到了网易雷火.京东.去哪儿.梆梆安全等10家互联网公司的校招Offer,因为某些自身原因最终选择了梆梆安全.6.7月主要是做系统复习.项目复盘.Leet ...

  9. [02]Go设计模式:原型模式(Prototype )

    目录 原型模式 一.简介 二.代码实现 三.参考资料: 原型模式 一.简介 原型模式(Prototype Pattern)是用于创建重复的对象,同时又能保证性能.这种类型的设计模式属于创建型模式,它提 ...

  10. 关于MySQL的内连接,外连接的总结

    首先创建两个数据库表,用户表u,账户表a 先看一下数据库表: u表: a表: 1. 内连接.    关键字:inner join SQL语句: select u.*,a.ID as aid,a.mon ...