函数

一、函数的作用

1、减少重复代码

2、方便修改,可扩展性

3、保持代码的一致性

二、函数的命名

1、函数命名表现出其作用,以下划线或者字母开头,不能以数字开头

2、区分大小写

3、不能是保留字

三、形参、实参

1、必需的参数须以正确的顺序传入函数,调用时的数量必须和声明时一样

2、关键字参数,即传入的时候把形参放在前边,传入实参值eg: def f(a,b)  调用 f(a='1',b=2)

3、默认参数值,传入默认参数的值必须在没有赋默认值的参数后边eg: def f(a, b, c=0)

4、不定长参数:需要一个函数处理比当初声明时更多的参数,叫做不定长参数,声明时不命名(没有形参名字)。

def f(*args, **kwargs)
# 传入的是元祖
def add(*args):
    print(args)
    sum = 0
    for i in args:
        sum =+ i
    print(sum)
add(1)
# 传入的是字典
def print_info(**kwargs):
    for key in kwargs:
        print("{key} is {value}".format(key=key, value=kwargs.get(key)))

print_info(name='jiangqijun', age='18')
#所以像没有名字的被args接收,有名字的被kwargs接收,即直接传入字符、int数据、列表、元祖则被args接收,而name='jiangqijun',被kwargs接收
非常重要:
传入规则:关键参数优先级最高放在最左边,再者就是默认参数,再者是*args,最后是**kwargs。
a.传入的时候要按照顺序来,所以要有命名和无命名的区分。否则报错。
eg:f(1, name='jiangqijun', 2)

def(*args, **kwargs)

s1 = 's1'
s2 =2
s3 = True
s4 = bytes('s4', encoding='utf-8')
s5 = [5,6]
s6 = (6,7)
s7 = {'s7':'7'}
s8 = {'p8'}


1、 def f(*args):
        print(args)
传入s1至s8,如果不带任何*调用,接收后每个变量作为元组的一个元素
    f(s1,s2,s3,s4,s5,s6,s7,s8) 
    #('s1', 2, True, b's4', [5, 6], (6, 7), {'s7': '7'}, {'p8'})

2、def f(*args):
        print(args)
传入s1至s8,如果带*调用,接收后每个变量里面的每个小的元素作为元组的一个元素
    f(*s1,*s5,*s6,*s7,*s8)  注意这里,*后面只能传入可迭代对象,否则报错,字符串是可迭代对象,但是会被拆开成每个字符
    #('s', '1', 5, 6, 6, 7, 's7', 'p8')

3、
def f1(**kwargs):
    print(kwargs)
对于**只能调用可map的对象即 f1(**s7),否则报错,不能f1(s7)调用.

当存在def f1(*args,**kwargs) 时 一定要加**才能正常调用到 f1(**s7)
b.传入的时候*args必须在左边,**kargs必须在右边否则报错
eg:def f(**kwargs,*args)

c.def f(sex='female', *args, **kwargs):这里先给的是默认值,再者是分给args再者给kwargs

def f(sex='female', *args, **kwargs):
    print(sex)
    print(args)
    print(kwargs)

f(1, 2,7,'hello',name='jiangqijun')

结果是:

1
(2, 7, 'hello')
{'name': 'jiangqijun'}

补充

def f1(*args):
    print(args)

l = [1, 2, 3]
f1(l)#这种得到的结果是([1, 2, 3],)
f1(*l)#这种得到的结果是(1, 2, 3)
def f2(**kwargs):
    print(kwargs)

d = {'name':"jiangqijun"}
#f2(d)#报错
f2(**d)#{'name': 'jiangqijun'}

四、return

#1、如果没有添加return则默认返回一个none 2、结束函数 3、返回某个对象
def f():
    print('hello')
    return
#4、如果返回的是多个对象则将多个对象封装为元祖返回
def f2():
    return 'a',4,[1,7]

五、作用域

能够开拓作用域的有类、模块、函数,其他的如if,for,try 不引入作用域模块.

if 2>1:

    = 1

print(x)  # 1

这个是没有问题的,if并没有引入一个新的作用域,x仍处在当前作用域中,后面代码可以使用。

1

2

3

def test():

    = 2

print(x) # NameError: name 'x2' is not defined

def、class、lambda是可以引入新作用域的。 

#作用域
# 1、L local ,局部作用域,函数中定义的变量
# 2、E enclosing 嵌套的父级函数的局部作用域,即包含此函数的上级函数的局部作用域,但不是全局的
# 3、G global,全局变量,就是模块级别定义的变量
# 4、B built_in,系统固定模块里边的变量,比如int bytearray
#搜索顺序是:local>enclosing>global>built-in
b_var = int(8.9) #这里的int函数是built-in变量
g_var = 6        #这里是全局变量

def outer():
    e_var = 5     #嵌套变量
    def inner():
        l_var = 2  #本地变量

 

#a.此处前边已经使用过count,所以后边不能对全局变量进行修改,报错。这里报错的原因是调用test的时候代码全部
#加载到内存,print(count)找到下面的局部变量count,所以报错count使用应该在声明之后
count = 2
def test():
    print(count)
    count=1
test()
#b.此处函数里的count是一个新的count
count = 2
def test():
    count=1
    print(count)
#c.通过一个关键字global声明进行修改
count = 2
def test():
    global count
    print(count)
    count=1
    print(count)
#d.通过关键字nolocal修改嵌套变量
def outer():
    e_var = 5     #嵌套变量
    def inner():
        nonlocal e_var
        print(e_var)
        l_var = 2  #本地变量
        e_var=3
        print(e_var)
    inner()
outer()

小结:

(1)变量查找顺序:LEGB,作用域局部>外层作用域>当前模块中的全局>python内置作用域;

(2)只有模块、类、及函数才能引入新作用域;

(3)对于一个变量,内部作用域先声明就会覆盖外部变量,不声明直接使用,就会使用外部作用域的变量;

(4)内部作用域要修改外部作用域变量的值时,全局变量要使用global关键字,嵌套作用域变量要使用nonlocal关键字。nonlocal是python3新增的关键字,有了这个 关键字,就能完美的实现闭包了。 

六、高阶函数

# 高阶函数
#1、函数名称就是一个变量,里边的指向代码块,函数名可以赋值给其他变量
#2、函数名可以作为函数参数
#3、函数名作为函数的返回值eg.foo3(),如果return inner()则会调用,如果是return inner则只返回一个变量
# def func(n):
#     return n*n
#
#
# def foo(a, b, f):
#     print(func(a)+f(b))
#
# foo(1, 2, func)

# def foo3():
#     def inner():
#         return 3
#     return inner
#
# print(foo3())  #返回的是inner的对象地址

定义:既然变量可以指向函数,函数的参数能接收变量,那么一个函数就可以接收另一个函数作为参数,这种函数就称之为高阶函数。

一个最简单的高阶函数:

def add(x, y, f):
    return f(x) + f(y)

七、递归函数

递归函数的优点:    是定义简单,逻辑清晰。理论上,所有的递归函数都可以写成循环的方式,但循环的逻辑不如递归清晰。

递归特性:

1. 必须有一个明确的结束条件

2. 每次进入更深一层递归时,问题规模相比上次递归都应有所减少

3. 递归效率不高,递归层次过多会导致栈溢出(在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返     回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出。)

def count(n):
    if n < 1:
        return -1
    elif n == 1:
        return 1
    return n*count(n-1)

八、内置函数

#1、eval传入的参数locals()则只能用函数内部的,传入的参数globals()则使用全局变量,这里表示等与x+y
# x = '1'
# y = '2'
# def test():
#     x = 2
#     y = 3
#     num1 = eval('x+y')
#     print(num1)
#     num2 = eval('x+y', globals())
#     print(num2)
# test()

#2、filter()用作过滤,传入的是函数和迭代器,里边加的函数必须包含判断条件,使用filter得到的是一个迭代器对象。需要其他函数进行强制转换
# def test(s):
#     if s!='a':
#         return s
#
# s = 'abcd'
# result = filter(test, s)
# print(list(result))

#3、map()方法,传入的是函数和迭代器,返回的是一个迭代器,需要其他函数进行强制转换
# def test(n):
#     return n*n
# result = map(test, [1,2,3])
# print(list(result))

#4、reduce() 传入函数和一个迭代器,这里表示先传入1,2得到结果3再传入3,3,以此类推
# def test(x, y):
#     res = x + y
#     return res
#
# l = [1, 2, 3, 4, 5, 6, 7]
# print(reduce(test, l))

#5、lambda 命名规则是,在左边传入函数的参数,冒号右边传入函数的返回值,创建时没有名字所以叫做匿名函数
# add = lambda x,y:x+y
# print(add(1,2))

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值