函数即变量,函数名可以赋值
函数如果要有返回值的话,就写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就没有被重新初始化