day4_函数的参数、全局变量、拆包和闭包

函数即变量,函数名可以赋值
函数如果要有返回值的话,就写return,函数里面遇到return,函数立即结束,函数不是必须有返回值的,如果不写return,默认返回None
全局变量是大家都可以用的变量,局部变量就是在函数内部定义的变量,在函数内部可以随便用,出了函数就不能用了,全局变量是list,用不用global声明,都可以直接修改,其他的类型(tuple,str,set,bool,dict,普通的变量赋值)如果要修改值必须用global声明,尽量不要用全局变量,全局变量容易被修改,代码如下

# s = [1, 2, 56, "list"]  # list不用global
# s = {'name': '小明'} # 字典要使用global
s = ('name', '小明', 3) # tuple要使用global
# s = 'hello' # str要使用global
# s = {22, 33} # 集合要使用global
# s = False # 布尔值要使用global
# s = 1 # 普通赋值要使用global


def change_value():
global s
# s.append("over") # list
# s = {'name': 'blue'} # 字典
s = ('大明', '好') # tuple
# s = 'red' # 字符串
# s = {1, 3} # 集合
# s = True # bool类型
# s = 2 # 普通变量赋值
return s


res = change_value()
print(res) # 打印出('大明', '好')
print(s) # 打印出('大明', '好')

函数的参数有四种方式,如果这四种参数一起用的话,顺序是位置参数、默认参数、可变参数、关键字参数
1、位置参数
位置参数,如add(x, y),x和y就是位置参数,位置参数是必传的,有几个位置参数在调用的时候就要传几个,否则就会报错,那如果有多个位置参数的话,记不住哪个位置传哪个了怎么办,可以使用位置参数的名字来指定调用,比如说上面的那个add函数也可以使用add(y=1, x=2)这样来调用,这种调用方式叫做关键字传参

def add(x, y):  # 函数名
return x + y # 函数体
print(add(2, 3)) # 调用的方法一
print(add(y=2, x=3)) # 调用的方法二

会打印出5

2、默认参数
默认参数就是在定义形参的时候,默认参数不是必填的,如果给默认参数传值的话,它就会使用你传入的值,如果使用默认值参数的话,必须放在位置参数后面定义

def user(name, sex='男'):  # sex就是默认参数
print('你的名字是 %s,你的性别是 %s' % (name, sex)) # 函数体

传参时user('哈哈'),会打印出你的名字是 哈哈,你的性别是男

3、可变参数
可变参数用*args来接收,后面想传多少个参数就传多少个,如果位置参数、默认值参数、可变参数一起使用的的话,可变参数必须在位置参数和默认值参数后面,可变参数也是非必传的,args是一个tuple,args这个名字随便叫,叫别的名字也行

def test(name, *args):
print('你的名字是:', name)
print('*args的值是:', args)
test('hello', 10086, '北京')

会打印出你的名字是: hello *args的值是(10086, '北京')  # args是一个tuple

4、关键字参数
关键字参数使用**kwargs来接收,这个名字也不固定,写成**aa也可以,关键字参数也可以和上面的三种一起来使用,如果要一起使用的话,关键字参数必须在最后面,使用关键字参数的话,是指函数在调用的时候,带上参数的名字去指定具体调用的是哪个参数,从而可以不用按照参数的顺序调用函数,关键字参数也是非必传的

def test(name, **kwargs):
print('你的名字是:', name)
print('**kwargs的值是:', kwargs)
test('hello', a=1, b=2)

会打印出你的名字是: hello **kwargs的值是{'a': 1, 'b': 2}  # kwargs是一个字典

def redis(ip, password, port=6379):
print('连接redis')
print(ip)
print(password)
print(port)
print('=' * 10)

# 用list
redis_info = ('127.0.0.1', '123456', 6378)
# redis_info = ['127.0.0.1', '123456', 6378]
redis(redis_info[0], redis_info[1], redis_info[2])
# redis(*redis_info)  # 这种方式叫拆包


# 用字典
redis_info2 = {'ip': '127.0.0.1', 'password': '123456', 'port': 6378}
redis(**redis_info2)

# 全局变量

count = 5


def my():
global count
count = 10
print(count)


my() # 打印出10
print(count) # 如果不写global count,打印出5,否则打印10

# 如果在一个内部函数里,对外部作用域(但不是在全局作用域的变量的引用)的变量的引用,内部函数就称为闭包,fun2就是一个闭包

def fun1(x):
def fun2(y): # 满足三点,第一是有内部函数,第二是内部函数引用了外部作用域(fun1)的变量x,第三外部函数的返回值必须是内部函数

return x * y
return fun2


res = fun1(5)(6)
print(res)

def fun1():
x = 5

def fun2():
x *= x
return x
return fun2()

print(fun1())

打印出UnboundLocalError: local variable 'x' referenced before assignment,意思是赋值之前引用了局部变量x
在fun2()把x当成了局部变量,所以x *= x就报错了,在嵌套的函数中,如果希望在内部函数修改外部函数的局部变量,使用nonlocal,让x不是局部变量,修改代码如下:

def fun1():
x = 5

def fun2():
nonlocal x
x *= x
return x
return fun2()


print(fun1())

打印出UnboundLocalError: local variable 'var' referenced before assignment,意思是变量var没有被定义就拿来使用,肯定错啦,解决办法有三种,一是注释var = 3,二是把var = 3放到print上面,三是在print上输入nonlocal var
这里outside()函数里有一个var变量,但要注意的是,内嵌函数inside()也有一个同名的变量,python为了保护变量的作用域,故将outside()的var变量屏蔽起来,因此此时是无法访问到外层的var变量的

def outside():
var = 5

def inside():
print(var)
var = 3
inside()


outside()

以下是闭包的一个例子,请你目测下会打印什么内容?

def fun1():
x = 5

def fun2():
nonlocal x
x += 1
return x
return fun2


a = fun1()
print(a()) # 打印6
print(a()) # 打印7
print(a()) # 打印8

当a=fun1()的时候,只要a变量没有被重新赋值,fun1()就没有被释放,也就是说局部变量x就没有被重新初始化

原文地址:https://www.cnblogs.com/laosun0204/p/7696346.html