热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

python学习随笔(七)_函数

函数#作用:封装和复用数学定义:yf(x),y是x的函数,x是自变量。yf(x0,x1,,xn)Python函数由若干语句组成的语句块、函数名称、参数列表构成,它是组织代码的

函数    #作用:封装和复用
    数学定义:y=f(x) ,y是x的函数,x是自变量。y=f(x0, x1, ..., xn)
    Python函数
        由若干语句组成的语句块、函数名称、参数列表构成,它是组织代码的最小单元
        完成一定的功能

    函数的作用
        *结构化编程对代码的最基本的封装*,一般按照功能组织一段代码
        封装的目的为了复用*,减少冗余代码
        代码更加简洁美观、可读易懂
    函数的分类
        内建函数,如max()、reversed()等
        库函数,如math.ceil()等

函数定义、调用
    def语句定义函数
    def 函数名(参数列表):
        函数体(代码块)
        [return 返回值]
        函数名就是标识符*,命名要求一样
        语句块必须缩进,约定4个空格
        Python的函数没有return语句,隐式会返回一个None值
        *定义中的参数列表成为*形式参数*,只是一种符号表达,简称形参
    调用
        函数定义,只是声明了一个函数,它不会被执行,需要调用
        调用的方式,就是函数名加上小括号,括号内写上参数
        *调用时写的参数是*实际参数*,是实实在在传入的值,简称实参

定义时是形参,调用时是实参,调用加小括号

python是动态的,强类型语言
因为是动态的,参数没有定义类型,会带来很大问题(自由工业化开发会带来问题)
无法限制参数类型,除非进行判断
能不能控制这个?是解决团队的问题

函数参数
    参数调用时传入的参数要和定义的个数相匹配(可变参数例外)
    位置参数
        def f(x, y, z) 调用使用 f(1, 3, 5)#顺序对应,个数也要相同#传参,传入实参
        按照参数定义顺序传入实参
    关键字参数    #谁等于谁就是关键字传参(keyword)
        def f(x, y, z) 调用使用 f(x=1, y=3, z=5)    #顺序可以不一样,因为可以按名字找
        使用形参的名字来出入实参的方式,如果使用了形参名字,那么传参顺序就可和定义顺序不同
    传参
        f(z=None, y=10, x=[1])
        f((1,), z=6, y=4.1)
        f(y=5, z=6, 2) #位置参数必须在前,keyword在后是可以的
        要求位置参数必须在关键字参数之前传入,位置参数是按位置对应的


函数参数默认值    #记得时候可以记带等号不可以放前面
  参数默认值(缺省值)
  定义时,在形参后跟上一个值
def add(x=4, y=5):
return x+y
测试调用 add(6, 10) 、add(6, y=7) 、add(x=5) 、add()、add(y=7)、 add(x=5, 6) #这个不可以、add(y=8,
4)、add(x=5, y=6)、add(y=5, x=6)
测试定义后面这样的函数 def add(x=4,y)#非缺省跟在非缺省后不可以(记得时候可以记带等号不可以放前面)
  作用
  参数的默认值可以在未传入足够的实参的时候,对没有给定的参数赋值为默认值
  参数非常多的时候,并不需要用户每次都输入所有的参数,简化函数调用
  举例
  定义一个函数login,参数名称为host、port、username、password
函数参数默认值
 

  在形参前使用*表示该形参是可变参数,可以接收多个实参
****收集多个实参为一个tuple***


可变类型和解构类型,但不全相同(keyword-only)

def fn(*args,x,y,**kwargs)
(x,y)属于keyword-only:在后面 必须定义关键字传参
可以用缺省值,必须使用关键字传参#经常给keyword-only定义缺省值
def add(*,x,y):    #逗号标志后面的是keyword-only


***总结定义形参和传参的几种类型(定义时是形参,调用时是实参)
定义形参:,位置参数,可变位置参数(封装成元组tuple),可变关键字传参(封装成dict字典)


定义传参:位置传参,关键字传参,混着用的时候:位置传参在前,关键字传参在后

普通位置传参:位置传参和关键字传参都支持但是位置传参在前
可变参数:
    可变位置传参:不允许关键字传参,只可以写在一起让可变参数对应#add(1,2,3,4)

    可变关键字传参只收集关键字传参,不可以位置传参


位置参数往放前(可变的也要放前),关键字参数放后(记带星的放后星星放最后)

传参时对应形参必须只有一个,全是关键字传参可以不考虑顺序


函数参数
    参数规则
***参数列表参数一般顺序是,普通参数、缺省参数、可变位置参数、keyword-only参数(可带缺
省值)、可变关键字参数
模版:def fn(x, y, z=3, *arg, m=4, n, **kwargs):
print(x,y,z,m,n)
print(args)
print(kwargs)


参数解构
***只能在参数传参中运用
    传参的时候才解构,解构出元素作为实参

  非字典类型使用*解构成位置参数
****字典类型使用**解构成关键字参数
字典解构:一个*解key,**解字典
add(*{‘a‘: 5, ‘b‘: 6})#解构后为x = ‘a‘,y = ‘b‘
#add(**{‘a‘: 5, ‘b‘: 6})#解构后为‘a‘ = 5,‘b‘ = 6

函数默认return none,如果想要函数有返回值修改return

------------------------------------------------------------------------------------------------------------------------------------

函数返回值
return 语句
一个函数只有一条return语句

多分支结构可以有多条return,但只能执行一条return
#多分支结构可以设置个变量,最后return变量,可以省着每次分支都写return
if..ret=..else..ret=..最后return ret

函数可以返回值可以不同类型
一个函数只要碰到return就立即返回终止

函数默认return none,往往函数需要写return

return返回必须是一个值,不是一个会被它封装成一个元组
返回多个值包在容器中  得到它们使用解构一一对应
---------------------------------------------------------------------------------------------------------------------------
作用域****
嵌套函数
    函数内部的函数不可以在外部单独执行#因为在外部没有定义,报NameError

    在外部的函数可以调用嵌套在内的函数

****###函数是有可见范围的,这就是作用域

函数内部的标识符(变量),外部是不可见的


函数定义直接过,执行时看前面定义有没有用到变量

函数内部
x = 5
def show():
    x += 1#报错
    print(x)
show()

x = x +1    #在函数内部要先定义,要不然会说内部没有定义
    #右边x+1,赋值即重新定义,赋值要先算右边,
    #右边是内部本地变量(本地作用域),x要重新定义

嵌套函数:赋值即重新定义,但是是定义自己的变量

全局作用域    #在整个运行环境中都可见

局部作用域(local)    #在函数和类等内部中可见

---------------------------------------------------------------------------------------------------------------------------
全局作用域(了解,写函数基本不用,改动影响太大)
global x    #使用全局作用域变量
    #尽可能放在前面第一行

global 用在局部作用域中定义一个全局作用域中操作变量
但是global只影响当前作用域

函数应该用定义形参,传参这种形式用,尽量不要用global

---------------------------------------------------------------------------------------------------------------------------

闭包***#一般在有嵌套函数时候用

自由变量:未在本地作用域中定义的变量。例如定义在内存函数外的外层函数的作用域中的变量

本来变量在外层函数  内层函数用到了这个局部变量,闭包就已经产生


nonlocal    关键字
    #声明变量不在本地作用域中,但是在外层作用域中找,但是不会再全局作用域中找
    #形成闭包
    #一层层向外找但不在全局中找
    #不可在全局下一层中用(因为全局中的下一层可以直接用全局变量了)
形参可以当局部变量来看

---------------------------------------------------------------------------------------------------------------------------

默认值的作用域

函数也是对象,如果对象中包含引用类型时,会更改默认值,简单类型不会更改默认值

函数名.__defaults__        #查看默认值属性,使用元组保存所有位置参数默认值#使用元组位置就不会变
函数名.__kwdefaults__    #查看使用字典保存所有keyword-only参数的默认值,dict是关键字传参


缺省值函数默认的特殊属性,生命周期跟函数同样周期共消亡

缺省值只有自己的作用域的,要看缺省值指的是什么,如果指的是缺省值送给形参,形参的作用域就在函数内部,它是局部作用域中的局部变量

#default这个东西它又属于函数对象本身的特殊属性,它是放在函数对象上的
#函数对象是和函数定义相关的,函数在定义时它的标识符(形参)关联到它内存中创建的那一个函数对象上去了


默认值作用域为形参用,形参可以当函数的局部变量来看
如果形参可变的类型(如列表),(无缺省值)没有固定的缺省值,有缺省值也会变的
#有时候这个特性是好的,有的时候这种特性是不好的,有副作用

def foo(xyz=[], u=‘abc‘, z=123):
    xyz.append(1)
    return xyz
print(foo(), id(foo))
print(foo.__defaults__)
print(foo(), id(foo))
print(foo.__defaults__)#引用类型默认值改变


def foo(xyz=[], u=‘abc‘, z=123):
   #xyz = foo.__defaults__
    xyz = xyz[:] # 影子拷贝,简单类型空列表内存中新生成一份,内存地址不同
    xyz.append(1)
    print(xyz)
foo()
print(foo.__defaults__)
foo()
print(foo.__defaults__)
foo([10])
print(foo.__defaults__)
foo([10,5])
print(foo.__defaults__)#不改变默认值


def foo(xyz=None, u=‘abc‘, z=123):#使用不可变类型默认值
    if xyz is None:#使用默认值时创建列表
        xyz = []
        xyz.append(1)# 如果传入一个列表,就修改这个列表
    print(xyz)
foo()
print(foo.__defaults__)
foo()
print(foo.__defaults__)
foo([10])
print(foo.__defaults__)
foo([10,5])
print(foo.__defaults__)

第一种方法
    使用影子拷贝创建一个新的对象,永远不能改变传入的参数
第二种方法
    通过值的判断就可以灵活的选择创建或者修改传入对象
    这种方式灵活,应用广泛
    很多函数的定义,都可以看到使用None这个不可变的值作为默认参数,可以说这是一种惯用法


---------------------------------------------------------------------------------------------------------------------------

变量名解析原则LEGB        #一个名词的查找顺序就是LEGB,一层一层向外解析
LEGB规定了查找一个名称的顺序为:local-->enclosing function locals-->global-->builtin

Local,本地作用域、局部作用域的local命名空间。函数调用时创
建,调用结束消亡

Enclosing,Python2.2时引入了嵌套函数,实现了闭包,这个就
是嵌套函数的外部函数的命名空间

Global,全局作用域,即一个模块的命名空间。模块被import时
创建,解释器退出时消亡

Build-in,内置模块的命名空间,生命周期从python解释器启动
时创建到解释器退出时消亡。例如 print(open),print和open都是内置的变量

---------------------------------------------------------------------------------------------------------------------------

函数的销毁
#函数的定义一般只做一次,除非你想把它覆盖掉再定义一次
#定义函数的目的就是复用,要明确为什么要销毁,不要轻易销毁

全局函数的销毁
     重新定义同名函数
    del 语句删除函数对象
    程序结束时

局部函数销毁
    重新在上级作用域定义同名函数
    del 语句删除函数名称,函数对象的引用计数减1
    上级作用域销毁时

--------------------------------------------------------------------------------------------------------------------------

递归函数

#栈和线程相关,栈是每个线程自己的空间
函数执行要压栈,一个落一个,函数局部变量也要压栈,用完后弹出
#局部变量,函数调用时创建,调用结束消亡

递归 Recursion
函数直接或者间接调用自身就是递归

递归一定要有退出条件 return 出一个结果
每次计算后也要return


import sys
print(sys.getrecursionlimit)    #查看递归层数

---------------------------------------------------------------------------------------------------------------------------

匿名函数

格式
    lambda 参数列表 : 表达式

map是生成一个惰性求值的

(lambda x : 0)(3)
冒号后面不可以用等号
---------------------------------------------------------------------------------------------------------------------------
生成器***
生成器generator

next()    #

生成器函数必须包含yield语句,生成器函数的函数体不会立即执行

协程    #非抢占式,轮询

yield from    #新语法从可迭代对象中一个个拿元素
for x in range(10)  =>   yield from range(10)
    yield x


python学习随笔(七)_函数


推荐阅读
  • 本文介绍了lua语言中闭包的特性及其在模式匹配、日期处理、编译和模块化等方面的应用。lua中的闭包是严格遵循词法定界的第一类值,函数可以作为变量自由传递,也可以作为参数传递给其他函数。这些特性使得lua语言具有极大的灵活性,为程序开发带来了便利。 ... [详细]
  • 本文介绍了使用Java实现大数乘法的分治算法,包括输入数据的处理、普通大数乘法的结果和Karatsuba大数乘法的结果。通过改变long类型可以适应不同范围的大数乘法计算。 ... [详细]
  • HDU 2372 El Dorado(DP)的最长上升子序列长度求解方法
    本文介绍了解决HDU 2372 El Dorado问题的一种动态规划方法,通过循环k的方式求解最长上升子序列的长度。具体实现过程包括初始化dp数组、读取数列、计算最长上升子序列长度等步骤。 ... [详细]
  • 本文讨论了Alink回归预测的不完善问题,指出目前主要针对Python做案例,对其他语言支持不足。同时介绍了pom.xml文件的基本结构和使用方法,以及Maven的相关知识。最后,对Alink回归预测的未来发展提出了期待。 ... [详细]
  • 本文讨论了如何优化解决hdu 1003 java题目的动态规划方法,通过分析加法规则和最大和的性质,提出了一种优化的思路。具体方法是,当从1加到n为负时,即sum(1,n)sum(n,s),可以继续加法计算。同时,还考虑了两种特殊情况:都是负数的情况和有0的情况。最后,通过使用Scanner类来获取输入数据。 ... [详细]
  • 本文介绍了C#中数据集DataSet对象的使用及相关方法详解,包括DataSet对象的概述、与数据关系对象的互联、Rows集合和Columns集合的组成,以及DataSet对象常用的方法之一——Merge方法的使用。通过本文的阅读,读者可以了解到DataSet对象在C#中的重要性和使用方法。 ... [详细]
  • 本文介绍了OC学习笔记中的@property和@synthesize,包括属性的定义和合成的使用方法。通过示例代码详细讲解了@property和@synthesize的作用和用法。 ... [详细]
  • 本文详细介绍了Linux中进程控制块PCBtask_struct结构体的结构和作用,包括进程状态、进程号、待处理信号、进程地址空间、调度标志、锁深度、基本时间片、调度策略以及内存管理信息等方面的内容。阅读本文可以更加深入地了解Linux进程管理的原理和机制。 ... [详细]
  • 1,关于死锁的理解死锁,我们可以简单的理解为是两个线程同时使用同一资源,两个线程又得不到相应的资源而造成永无相互等待的情况。 2,模拟死锁背景介绍:我们创建一个朋友 ... [详细]
  • 《数据结构》学习笔记3——串匹配算法性能评估
    本文主要讨论串匹配算法的性能评估,包括模式匹配、字符种类数量、算法复杂度等内容。通过借助C++中的头文件和库,可以实现对串的匹配操作。其中蛮力算法的复杂度为O(m*n),通过随机取出长度为m的子串作为模式P,在文本T中进行匹配,统计平均复杂度。对于成功和失败的匹配分别进行测试,分析其平均复杂度。详情请参考相关学习资源。 ... [详细]
  • 动态规划算法的基本步骤及最长递增子序列问题详解
    本文详细介绍了动态规划算法的基本步骤,包括划分阶段、选择状态、决策和状态转移方程,并以最长递增子序列问题为例进行了详细解析。动态规划算法的有效性依赖于问题本身所具有的最优子结构性质和子问题重叠性质。通过将子问题的解保存在一个表中,在以后尽可能多地利用这些子问题的解,从而提高算法的效率。 ... [详细]
  • 本文介绍了在开发Android新闻App时,搭建本地服务器的步骤。通过使用XAMPP软件,可以一键式搭建起开发环境,包括Apache、MySQL、PHP、PERL。在本地服务器上新建数据库和表,并设置相应的属性。最后,给出了创建new表的SQL语句。这个教程适合初学者参考。 ... [详细]
  • 基于layUI的图片上传前预览功能的2种实现方式
    本文介绍了基于layUI的图片上传前预览功能的两种实现方式:一种是使用blob+FileReader,另一种是使用layUI自带的参数。通过选择文件后点击文件名,在页面中间弹窗内预览图片。其中,layUI自带的参数实现了图片预览功能。该功能依赖于layUI的上传模块,并使用了blob和FileReader来读取本地文件并获取图像的base64编码。点击文件名时会执行See()函数。摘要长度为169字。 ... [详细]
  • Java实战之电影在线观看系统的实现
    本文介绍了Java实战之电影在线观看系统的实现过程。首先对项目进行了简述,然后展示了系统的效果图。接着介绍了系统的核心代码,包括后台用户管理控制器、电影管理控制器和前台电影控制器。最后对项目的环境配置和使用的技术进行了说明,包括JSP、Spring、SpringMVC、MyBatis、html、css、JavaScript、JQuery、Ajax、layui和maven等。 ... [详细]
  • 本文介绍了Java的集合及其实现类,包括数据结构、抽象类和具体实现类的关系,详细介绍了List接口及其实现类ArrayList的基本操作和特点。文章通过提供相关参考文档和链接,帮助读者更好地理解和使用Java的集合类。 ... [详细]
author-avatar
刘志樺伟宇佳君
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有