Python——函数&作用域
我们前面学的都是面向过程式的编程(代码从上到下写,并运行),而函数式编程是将繁杂的代码通过整理特性进行规整。像图书馆一样,将小说、教学、外文等书籍进行分类。让编程人员或看代码人员很容易的查看该段代码的特性。并且可以重复的利用该段代码进行相同的操作、像图书馆书是公用的一样,谁都可以去看,这样又能便于观察又能重复使用,是日后主要使用的技术。
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——函数&作用域的更多相关文章
- Python函数作用域的查找顺序
函数作用域的LEGB顺序 1.什么是LEGB? L:local 函数内部作用域 E:enclosing 函数内部与内嵌函数之间 G:global 全局作用域 B:build-in 内置作用域 2.它们 ...
- python函数作用域,嵌套函数,闭包
函数作用域 ...
- python函数作用域LEGB
我们的在学习Python函数的时候,经常会遇到很多定义域的问题,全部变量,内部变量,内部嵌入的函数,等等,Python是如何查找的呢?以及Python又是按照什么顺序来查找的呢?这里做一个顺序的说明 ...
- python函数作用域
python中函数作用域 在python中,一个函数就是一个作用域 name = 'xiaoyafei' def change_name(): name = '肖亚飞' print('在change_ ...
- python函数作用域,闭包,装饰器
第一:函数作用域: L:local 函数内部作用域 E:enclosing 函数内部与内嵌函数之间(闭包) G:global 全局作用域 B:build_in ...
- 07.python函数作用域global、nonlocal、LEGB
函数作用域 作用域 一个标识符的课件范围,这就是标识符的作用域,一般常说的是变量的作用域 def foo(): x = 100 print(x) # 可以访问到吗 上例中x不可以访问到,会抛出异 ...
- Python函数作用域和匿名函数
匿名函数的定义 全局变量和局部变量的概念 global(全局变量)和 nonlocal(局部变量) 闭包.递归.回调 匿名函数 匿名函数 lambda 语法规则:lambda 参数 : 表达式 ...
- python函数 -- 作用域,异常处理
1.def语句和参数 python定义函数的关键词为def,格式如下: def 函数名([变元],[变元],....) #保存在变元中的值,在函数返回后该变元就会被销毁了. 2.返回 ...
- python函数-作用域
可以把作用域”看成是变量的容器.当作用域被销毁时,所有保存在该作用 域内的变量的值就被丢弃了,只有一个全局作用域,它是在程序开始时创建的.如 果程序终止,全局作用域就被销毁,它的所有变量就被丢弃了. ...
随机推荐
- 时间工具类DateUtil
import java.sql.Timestamp; import java.text.ParseException; import java.text.SimpleDateFormat; impor ...
- Shell获取字符串长度的多种方法总结
摘自:https://www.jb51.net/article/121290.htm 前言 我们在日常工作中,对于求字符串操作在shell脚本中很常用,实现的方法有很多种,下面就来给大家归纳.汇总了求 ...
- node.js使用markdown-it批量转md内容为html
代码如下: var fs = require('fs'); var MarkdownIt = require('markdown-it'), md = new MarkdownIt(); /* pag ...
- css几个优先级测试和!important
css样式不加!important情况下的有默认优先级 ,用!important提高优先级,最常见的css样式选择器的优先级测试.之前博文里也用到了提升优先级的方法: 测试结果:加了!importan ...
- react 模板备份
/** * Created by hldev on 17-6-14. * 上市公司详情展示界面 */ import React, {Component} from "react"; ...
- 【视频开发】【计算机视觉】doppia编译之三:编译安装opencv库
这里我介绍2种方法 (1)利用别人写好的脚本编译,相对来说省力一点 上Github下载别人写好的脚本文件,网址 https://github.com/jayrambhia/Install-OpenC ...
- Redis 主从配置密码以及哨兵
目录: Redis 主从介绍 哨兵机制 Redis 主从配置 环境 安装 启动服务 检查主从状态 测试数据同步 默认是读写分离的 Redis Sentinel 配置 主Redis宕机测试 配置多个哨兵 ...
- 机试指南第二章-经典入门-Hash的应用自解
Hash的应用: Hash即散列,不像数据结构与算法中讲的各种Hash方法和冲突处理等过多的阐述,以下主要介绍Hash在机试试题解答中的作用. 例2.5 统计同成绩学生人数 Hash解法AC代码:(一 ...
- maven设置阿里云仓库
到maven安装目录的conf下setting.xml文件 找到mirrors标签中添加 <mirror> <id>nexus-aliyun</id> <mi ...
- [转帖]armel、armhf和arm64
armel.armhf和arm64 转帖 1 这些名词是什么的缩写 1.1 armel 是arm eabi little endian的缩写.eabi是软浮点二进制接口,这里的e是embeded,是对 ...