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

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. typescript - 2.数据类型

    typescript中为了使编写的代码更规范,更有利于维护,增加了类型校验,在typescript中主要给我们提供了以下数据类型 布尔类型(boolean) 数字类型(number) 字符串类型(st ...

  2. vmware装centos7 无法上网

    现象 使用ip address看不到ip地址 ping www.baidu.com无法ping通 解决方式: 1.设置网卡 vi /etc/sysconfig/network-scripts/ifcf ...

  3. Docker搭建ES集群

    Spring Boot连接ES,spring-boot-starter-data-elasticsearch. 必须为集群方式!否则报错! 报错: None of the configured nod ...

  4. [报错处理]Python Requests - No connection adapters

    出错信息很清楚:Python请求 - 没有连接适配器. 你得把网络协议加进入网址: http://192.168.1.61:8080/api/call 没有 http:// 请求不知道如何连接远程. ...

  5. matlab学习笔记8 基本绘图命令-图形窗口简介

    一起来学matlab-matlab学习笔记8 基本绘图命令_1 图形窗口简介 觉得有用的话,欢迎一起讨论相互学习~Follow Me 参考书籍 <matlab 程序设计与综合应用>张德丰等 ...

  6. PAT 甲级 1080 Graduate Admission (30 分) (简单,结构体排序模拟)

    1080 Graduate Admission (30 分)   It is said that in 2011, there are about 100 graduate schools ready ...

  7. LeetCode_443. String Compression

    443. String Compression Easy Given an array of characters, compress it in-place. The length after co ...

  8. 编写vscode插件

    一.参考学习 https://www.cnblogs.com/liuxianan/p/vscode-plugin-publish.html https://code.visualstudio.com/ ...

  9. exports module.exports export export default之间的关系

    exports 和module.exports是CommonJS模块规范 export export default是ES6模块的规范,两者完全是不同的概念. node应用由模块组成,采用的是Comm ...

  10. [编程开发]STB image读取学习

    为了便于学习图像处理并研究图像算法, 俺写了一个适合初学者学习的小小框架. 麻雀虽小五脏俱全. 采用的加解码库:stb_image 官方:http://nothings.org/ stb_image. ...