函数

Posted 浩元

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了函数相关的知识,希望对你有一定的参考价值。

函数重点:

技术分享
什么是函数?
为什么要用函数?
函数的分类:内置函数与自定义函数
如何自定义函数
  语法
  定义有参数函数,及有参函数的应用场景
  定义无参数函数,及无参函数的应用场景
  定义空函数,及空函数的应用场景
调用函数
    如何调用函数
    函数的返回值
    函数参数的应用:形参和实参,位置参数,关键字参数,默认参数,*args,**kwargs
高阶函数(函数对象)
函数嵌套
作用域与名称空间
装饰器
迭代器与生成器及协程函数
三元运算,列表解析、生成器表达式
函数的递归调用
内置函数
面向过程编程与函数式编程
函数重点内容

一、用函数与不使用函数的问题(具备某一功能的工具即函数)

  1、组织结构不清晰

  2、代码冗余

  3、无法统一管理且维护难度大

二、函数分类

  1、内置函数

  2、自定义函数

    1、内置函数:python 解释器自带的函数,python解释器启动就会定义好这些函数

    2、自定义函数:

    语法:
    def 函数名(参数1,参数2,...):
  ‘‘‘注释信息‘‘‘
  函数体
  return 返回值

三、为何要定义函数

  函数即变量,变量必须先定义后使用,未定义而直接引用函数,就相当于引用一个不存在的变量名。

四、定义函数做的事?

  只检测语法,不执行代码。

五、如何定义函数(函数名要反映其意义)

  def...

六、定义函数的三种形式

  无参:应用场景仅仅只是执行一些操作,比如与用户交互,打印

  有参:需要根据外部传进来的参数,才能执行相应的逻辑,比如统计长度,求最大值最小值

  空函数:设计代码结构

七、函数的调用(函数:必须遵循先定义,后调用)

    1 先找到名字

   2 根据名字调用代码

def tell_tag():#定义阶段
    print(‘======‘)
def tell_msg(msg):
    print(msg)
#调用阶段
# tell_tag()
# tell_msg(‘hello world‘)
# tell_tag()

 

   函数的返回值?

  0->None
  1->返回1个值
  多个->元组
  什么时候该有?
    调用函数,经过一系列的操作,最后要拿到一个明确的结果,则必须要有返回值
    通常有参函数需要有返回值,输入参数,经过计算,得到一个最终的结果
  什么时候不需要有?
    调用函数,仅仅只是执行一系列的操作,最后不需要得到什么结果,则无需有返回值
    通常无参函数不需要有返回值
八、函数调用的三种形式
  1、语句形式:foo()
  2、表达式形式:3*len(‘hello’)
  3、当中另外一个函数的参数:range(len(‘hello‘))
九、函数的参数
 1 形参和实参定义
2 形参即变量名,实参即变量值,函数调用则将值绑定到名字上,函数调用结束,解除绑定
3 具体应用
位置参数:按照从左到右的顺序定义的参数
位置形参:必选参数
位置实参:按照位置给形参传值

关键字参数:按照key=value的形式定义实参
无需按照位置为形参传值
注意的问题:
1. 关键字实参必须在位置实参右面
2. 对同一个形参不能重复传值

默认参数:形参在定义时就已经为其赋值
可以传值也可以不传值,经常需要变得参数定义成位置形参,变化较小的参数定义成默认参数(形参)
注意的问题:
1. 只在定义时赋值一次
2. 默认参数的定义应该在位置形参右面
3. 默认参数通常应该定义成不可变类型


可变长参数:
针对实参在定义时长度不固定的情况,应该从形参的角度找到可以接收可变长实参的方案,这就是可变长参数(形参)
而实参有按位置和按关键字两种形式定义,针对这两种形式的可变长,形参也应该有两种解决方案,分别是*args,**kwargs

===========*args===========
def foo(x,y,*args):
print(x,y)
print(args)
foo(1,2,3,4,5)

def foo(x,y,*args):
print(x,y)
print(args)
foo(1,2,*[3,4,5])


def foo(x,y,z):
print(x,y,z)
foo(*[1,2,3])

===========**kwargs===========
def foo(x,y,**kwargs):
print(x,y)
print(kwargs)
foo(1,y=2,a=1,b=2,c=3)

def foo(x,y,**kwargs):
print(x,y)
print(kwargs)
foo(1,y=2,**{‘a‘:1,‘b‘:2,‘c‘:3})


def foo(x,y,z):
print(x,y,z)
foo(**{‘z‘:1,‘x‘:2,‘y‘:3})

===========*args+**kwargs===========

def foo(x,y):
print(x,y)

def wrapper(*args,**kwargs):
print(‘====>‘)
foo(*args,**kwargs)

命名关键字参数:*后定义的参数,必须被传值(有默认值的除外),且必须按照关键字实参的形式传递
可以保证,传入的参数中一定包含某些关键字
def foo(x,y,*args,a=1,b,**kwargs):
print(x,y)
print(args)
print(a)
print(b)
print(kwargs)

foo(1,2,3,4,5,b=3,c=4,d=5)
结果:
1
2
(3, 4, 5)
1
3
{‘c‘: 4, ‘d‘: 5}
#1、形参与实参
#形参:在函数定义阶段,括号内定义的参数的称为形参,相当于变量名
#实参:在函数调用阶段,括号内定义的参数的称为实参,相当于变量值
#在调用阶段,实参的值会绑定给形参,调用结束后解除绑定关系

# def foo(x,y):
#     print(x,y)
# foo(1,2)

#参数的分类:
‘‘‘
1、位置参数
    位置形参:必选被传值的参数,多一个不行,少一个不行
    位置实参:从左到右依次赋值给形参

‘‘‘
# def foo(x,y):
#     print(x,y)
# foo(1,2)

‘‘‘
#2、关键字参数:在函数调用阶段,按照key=value的形式定义实参
可以不依赖位置,指名道姓给形参传值
注意:可以与位置形参混用:
    1、位置实参必须在关键字实参的前面
    2、不能为一个形参重复传值
‘‘‘
# def foo(x,y):
#     print(x,y)
# foo(1,y=2)#
‘‘‘
#3、默认参数:在函数的定义阶段,已经为形参赋值了,在定义阶段已经赋值,意味着在调用阶段可以不传值
经常变得用形参,不变的用实参。
注意:
    1、默认参数的值,只在定义时赋值一次
    2、位置形参应在默认参数的前面
    3、默认参数的值应是不可变类型
‘‘‘

# def foo(x,y=10):
#     print(x,y)
# foo(x=8,y=11)

# def register(name,age,sex=‘male‘):
#     register(‘egon‘,18)
#     register(‘alex‘,38,None)

# def register(name,age,sex=‘boy‘):
#     print(name,age,sex)
# register(‘chy‘,18)



‘‘‘
4、可变长参数
实参可变长度:实参值的个数是不固定的
而实参的定义形式两种:
    1、位置实参      *
    2、关键字实参   **  
针对这两种形式的实参个数不固定,相应的,形参也有两种解决方案


‘‘‘
# #针对按照位置定义
# def func(x,y,*args):
#     print(x,y)
#     print(args)
# func(1,2,3,4)
# func(1,2,*[3,4])#func(1,2,3,4)
# func(*[1,2,3,4])
# func(1,2)#()为空
#
# def fun(x,y,z):
#     print(x,y,z)
# l=[1,2,3]
# fun(*l)

#针对按照关键字定义的那部分实参,形参:**kwargs
# def foo(x,y,**kwargs):
#     print(x,y)
#     print(kwargs)
# foo(y=2,x=1,z=3,b=2)
# foo(1,2,3,y=2,x=1,z=3,b=2)
# foo(y=1,x=2,**{‘a‘:1,‘b‘:2,‘c‘:3})#无序

# 用途:装饰器

#5、命名关键字参数:形参中,在*后定义的参数称之为命名关键字参数
#特性是:传值时必须按照关键字实参的形式传值
def foo(x,y,*args,a=1,b):
    print(args)
    print(x,y,a,b)
foo(1,2,6,7,b=3,a=4)

#形参:位置参数===》默认参数===》*args===》命名关键字惨呼===》**kwargs

 


十、阶段性练习
一、函数对象
  函数是第一类对象,即函数可以当作数据传递
  1、可以被引用
  2、可以当作参数传递
  3、返回值可以是函数
  4、可以当做容器类型的元素
  #利用该特性,优雅的取代多分支的if
def foo():
print(‘foo‘)

def bar():
print(‘bar‘)

dic={
‘foo‘:foo,
‘bar‘:bar,
}
while True:
choice=input(‘>>: ‘).strip()
if choice in dic:
dic[choice]()
#1、函数是第一类对象:函数可以当做数据来使用
def foo():
    print(from foo)


#可以被引用
# f=foo
# print(f)
#可以当做参数传入一个函数
# def foo(m):
#     print(m)
# foo(x)
# def wrapper(func):
#     print(func)
#     func()
# wrapper(foo)


#可以当做函数的返回值
# def bar():
#     return x
# print(bar())
# def wrapper():
#     return foo
# f=wrapper()
# print(f is foo)


#可以当做容器类型的一个元素
# print([x,1,2])

# l=[foo,1,2]
# l[0]()


def select(sql):
    print(select功能:,sql)
def update(sql):
    print(update功能:,sql)
def insert(sql):
    print(insert功能:,sql)
def delete(sql):
    print(delete功能:,sql)
func_dic={
    select:select,
    update:update,
    insert:insert,
    delete:delete,
}
def main():
    while True:
        inp=input(>>: ).strip()
        if not inp:continue
        sql=inp.split()
        cmd=sql[0]
        if cmd in func_dic:
            func_dic[cmd](sql)
        else:
            print(command not found)
main() 
二、函数的嵌套
  1、函数的嵌套调用
       def max(x,y): return x if x > y else y def max4(a,b,c,d): res1=max(a,b) res2=max(res1,c) res3=max(res2,d)
                return res3
print(max4(1,2,3,4))
  2、函数的嵌套定义:在定义一个函数内部,又定义了一个函数
三、名称空间与作用域
  
1、名称空间:存放名称与值绑定关系的地方
    内置名称空间:内置的名字与值的绑定关系
      生效:python解释器启动后
      失效:python解释器关闭后
    全局名称空间:文件级别定义的名字与绑定关系
      生效:执行python文件时,将改文件级别定义的名字与绑定关系生效
      失效:文件执行完毕
    局部名称空间:函数内部定义的名字与值的关系
      生效:调用函数临时失效
      失效:函数调用结束
    加载顺序:内置==》全局==》局部(不一定会产生)
    查找名字的顺序:局部=全局==》内置=》
  2、作用域
   
全局作用域:包含内置空间的名字与全局空间的名字
    全局存活、全局有效(伴随着程序的开始到结束)
    局部作用域:包含局部名称空间的名字
   临时存活、局部有效(临时存活)
# print(globals())
# print(locals())

‘‘‘
作用域关系:在函数定义时,就已经固定了,与调用位置无关
‘‘‘
x=10000000000000000000000
def f1():
def f2():
print(x)
return f2
f=f1()
print(f)


#global nonlocal #硬改全局
x=1
def f1():
global x
x=10
f1()
print(x)


def func():
# x=123 除了全局那改,其它的没有意义
f()
func()

#nonlocal 从函数内部找,硬改全局

x=155
def f1():
x=26
def f2():
nonlocal x
x=1111
f2()
f1()
print(x)
 
 
 
 
 
 
























































































































































































以上是关于函数的主要内容,如果未能解决你的问题,请参考以下文章

使用从循环内的代码片段中提取的函数避免代码冗余/计算开销

在 Visual Studio 中创建构造函数的代码片段或快捷方式

调用模板化成员函数:帮助我理解另一个 *** 帖子中的代码片段

web代码片段

C#常用代码片段备忘

php 一个自定义的try..catch包装器代码片段,用于执行模型函数,使其成为一个单行函数调用