函数
函数的定义
def 函数名(参数):
pass
函数的参数可以有也可以没有,定义函数时的参数叫形参
,调用函数时的参数叫做实参
传参有三种形式
①必备参数(有几个形参就转入几个实参)
def prin(mystr):
return mystr
result = prin("SuXin")
print(result)
在调用函数的时候,必备参数必须传入
②默认参数(如果不给某个形参传入实参,则使用定义时的参数)
def func(a='suxin'):
print(a)
func(1)
print('*'*40)
func(1,1)
#以上代码运行之后不难看出,当没有实参传入的时候,输出的是默认的,而传入新的实参之后使用新的参数
在函数调用的时候,默认参数可以不传入值,不传入值的时候,会使用默认的参数
③不定长参数(适用于不知道应该传入几个参数)
def func(a,*args,**kwargs):
print(a)
print(args)
print(kwargs)
func(1,2,3,4)
在函数调用的时候,不定长参数可以不传入,也可以传入任意长度。
其中定义的时候,元组形式可以放到最前边,字典形式只能放到最后边
当传入一个字典的时候,不要忘记
**
简单内置函数
内置对象查看: dir(__builtins__)
>>> dir(__builtins__)
['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException', 'BlockingIOError', 'BrokenPipeError', 'BufferError', 'BytesWarning', 'ChildProcessError', 'ConnectionAbortedError', 'ConnectionError', 'ConnectionRefusedError', 'ConnectionResetError', 'DeprecationWarning', 'EOFError', 'Ellipsis', 'EnvironmentError', 'Exception', 'False', 'FileExistsError', 'FileNotFoundError', 'FloatingPointError', 'FutureWarning', 'GeneratorExit', 'IOError', 'ImportError', 'ImportWarning', 'IndentationError', 'IndexError', 'InterruptedError', 'IsADirectoryError', 'KeyError', 'KeyboardInterrupt', 'LookupError', 'MemoryError', 'ModuleNotFoundError', 'NameError', 'None', 'NotADirectoryError', 'NotImplemented', 'NotImplementedError', 'OSError', 'OverflowError', 'PendingDeprecationWarning', 'PermissionError', 'ProcessLookupError', 'RecursionError', 'ReferenceError', 'ResourceWarning', 'RuntimeError', 'RuntimeWarning', 'StopAsyncIteration', 'StopIteration', 'SyntaxError', 'SyntaxWarning', 'SystemError', 'SystemExit', 'TabError', 'TimeoutError', 'True', 'TypeError', 'UnboundLocalError', 'UnicodeDecodeError', 'UnicodeEncodeError', 'UnicodeError', 'UnicodeTranslateError', 'UnicodeWarning', 'UserWarning', 'ValueError', 'Warning', 'WindowsError', 'ZeroDivisionError', '__build_class__', '__debug__', '__doc__', '__import__', '__loader__', '__name__', '__package__', '__spec__', 'abs', 'all', 'any', 'ascii', 'bin', 'bool', 'bytearray', 'bytes', 'callable', 'chr', 'classmethod', 'compile', 'complex', 'copyright', 'credits', 'delattr', 'dict', 'dir', 'divmod', 'enumerate', 'eval', 'exec', 'exit', 'filter', 'float', 'format', 'frozenset', 'getattr', 'globals', 'hasattr', 'hash', 'help', 'hex', 'id', 'input', 'int', 'isinstance', 'issubclass', 'iter', 'len', 'license', 'list', 'locals', 'map', 'max', 'memoryview', 'min', 'next', 'object', 'oct', 'open', 'ord', 'pow', 'print', 'property', 'quit', 'range', 'repr', 'reversed', 'round', 'set', 'setattr', 'slice', 'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple', 'type', 'vars', 'zip']
常见函数
- 求长度
len()
- 求最小值
min()
- 求最大值
max()
- 排序(不会改变列表元素的排列)
sorted()
#正向排序reversed()
#反向排序 - 求和
sum()
进制转换函数
- 转换为二进制
bin()
- 转换为八进制
oct()
- 字符转ASCI
I ord()
- ASCII转字符
chr()
高级内置函数
enumerate() #返回一个可以枚举的对象
exec() #执行字符串或者complie方法编译过的字符串
eval() #取出字符串中的内容,将字符串str当成有效的表达式来求指并返回计算结果
filter() #过滤器
map() #对于参数iterable中的每个元素都应用function函数,并将结果作为列表返回
zip() #将对象逐一配对
1.enumerate
#获取列表里面的某个元素的下标
mylist = ['python','java','c++']
for index,value in enumerate(mylist):
if value == 'java':
print('java的下标是:',index)
2.exec
exec('a=2')
发现python并没有报错,说明它是可以赋值的函数,而eva
l则会报错
3.eval
>>> a = '22+33'
>>> print(eval(a))
55
不难发现,这里传入的是一个字符串,当eval之后,变成了一个可执行语句
4.filter
>>> def my_filter(num):
if num > 5:
return True
else:
return False
>>> a = [1,2,3,45,55,234,2,4]
>>> b = filter(my_filter,a)
>>> list(b)
[45, 55, 234]
传入的参数有两个,第一个my_filter
参数就是过滤的规则,第二个是要过滤的对象
5.map
>>> a = [1,2,3,45,55,234,2,4]
>>> def my_map(num):
return num * 10
>>> print(list(map(my_map,a)))
[10, 20, 30, 450, 550, 2340, 20, 40]
6.zip
>>> a = ['python','java','c++']
>>> b = ['Chancey','Suxin','Mary']
>>> print(list(zip(a,b)))
[('python', 'Chancey'), ('java', 'Suxin'), ('c++', 'Mary')]
匿名函数
lamba
所有的函数名都是一个变量,包含了一段代码
写一个简单的过滤函数
mylist = [122,1,2,3,123,43,35,555]
def my_filter(mylist):
if mylist > 100:
return True
else:
return False
reslut = list(filter(my_filter,mylist))
print(reslut)
非常简单的逻辑,实现列表里大于100的元素输出,不再赘述
现在使用lamba来实现上边的过滤函数的功能
result = list(filter(lambda x : x > 100, mylist))
print(result)
lamba中第一个x是传入的参数,冒号后边的 x > 100 是表达式,lamba会自动return回一个结果
规定语法 lamba 参数 : 表达式 不可改变
# 输出当前系统时间和传入的提示字符
import datetime
def f(message):
nowTime = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
return '现在时间为%s,当前时间点提示:%s' % (nowTime, message)
print(f("改起床了!!!"))
# 使用匿名函数改写
import datetime
nowMessage = lambda message : '现在时间为%s,当前时间点提示:%s' % (datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'), message)
print(nowTime('改起床了!!!'))
应用场景
- 简单函数:简单的函数,可以不用使用def定义一个函数,使用匿名函数即可
- 函数调用:类似于filter、map等函数里面,可以使用匿名函数来处理
- 提高开发效率:合理使用能够让代码更加简洁
闭包
写一个简单的嵌套函数
def fun_A():
def fun_B():
print('内层函数')
当fun_B()
的时候就会报错
如何调用内层函数呢?
法一
def fun_A():
def fun_B():
print('内层函数')
fun_B()
result = fun_A()
调用fun_A
的时候,打印出来了 ‘内层函数’ ,这也就是内层的 fun_B 被成功调用
法二
def fun_A():
def fun_B():
print('内层函数')
return fun_B
result = fun_A()
result()
可以看到,在外层函数里面返回内层函数,这时只需要调用一次 fun_A 之后就能多次调用 func_B
这就是闭包,使用return
的方式将里面的函数返回出来
- 闭包是函数里面嵌套函数,外层函数返回里层函数,这种情况称之为闭包
- 闭包是概念,不是某种函数类型,和递归的概念类似,就是种特殊的函数调用
- 闭包可以得到外层函数的局部变量,是函数内部和函数外部沟通的桥梁
注意:这是返回整个函数,而不是返回内层函数结果
函数作用域
定义一个简单的函数
my_num = 520
def my_func():
print(my_num)
my_func()
执行之后,发现并没有报错,现在尝试在函数里面修改数值
my_num = 520
def my_func():
my_num = my_num + 1
print(my_num)
my_func()
执行报错:UnboundLocalError: local variable 'my_num' referenced before assignment
某道云翻译:UnboundLocalError:赋值前引用的局部变量“my_num”
意思就是函数里面的 my_num 并没有定义,那么,在函数里面给该变量重新赋值成250
my_num = 520
def my_func():
my_num = 250
print(my_num)
my_func()
print(my_num)
执行之后,分别打印出了250和520,
这就说
- 在函数里面定义的变量只能在函数里面使用
- 外边的变量不能在函数里面修改
- 外部不能访问内部的变量,而内部可以访问外部变量
global
假如,经理非要在函数里修改外边的值,就可以这样写
my_num = 520
def my_func():
global my_num #声明全局变量
my_num = 250
print(my_num)
my_func()
print(my_num)
执行后打印出来两个250,成功修改
这就是声明之后,变量可以函数内部被修改
nonlocal
只在嵌套函数中使用,用来在内层函数中修改外层函数中的值
def my_func():
my_num = 520
def inisde_func():
nonlocal my_num
my_num = 250
print(my_num)
inisde_func()
print(my_num)
my_func()
这里声明之后还是同一个变量,只不过被修改了
总结:
- 函数内部:函数内部的变量,作用域只在函数内部,函数内部不可以直接更改函数外部的变量
- global:在函数嵌套函数的情况下,同样也有函数作用域的问题,但是python3中提供了方便,只需要使用nonlocal就可以在里层函数内部修改外部函数变量
- nonlocal:函数内部如果需要改变全局变量,就需要使用global修饰变量
递归函数
def my_func():
print('Chancey is very cool !')
my_func()
my_func()
代码逻辑非常简单,首先输出 Chancey is very cool ! ,然后调用本身,形成一个死循环,发生溢出。
递归中可以函数自身调用自身,但是使用时类似于条件循环一样,要有递归的终止条件。
阶乘
def factorial(n):
if n == 1:
return 1
return factorial(n - 1) * n
print(factorial(5))
如果过程繁琐,将会栈溢出,慎用!
递归的应用
- 使用递归时,常常可以让代码更加简洁
- 递归会占用比较多的内存,当递归次数比较多时,性能就会降低,因此不建议多使用递归