函数

函数的定义

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()
  • 字符转ASCII 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并没有报错,说明它是可以赋值的函数,而eval则会报错

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))

如果过程繁琐,将会栈溢出,慎用!

递归的应用

  • 使用递归时,常常可以让代码更加简洁
  • 递归会占用比较多的内存,当递归次数比较多时,性能就会降低,因此不建议多使用递归
posted @ 2018-09-07 14:32  ChanceySolo  阅读(201)  评论(0编辑  收藏  举报