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

原文地址:https://www.cnblogs.com/springquanquan/p/9573783.html

时间: 2024-11-11 21:23:45

python学习随笔(七)_函数的相关文章

Python学习笔记七:函数

1. 定义一个函数 任何传入参数和自变量必须放在圆括号中间.圆括号之间可以用于定义参数.参数值和参数名称是按函数声明中定义的的顺序匹配起来的. 函数的第一行语句可以选择性地使用文档字符串—用于存放函数说明. 函数内容以冒号起始,并且缩进. Return[expression]结束函数,选择性地返回一个值给调用方.不带表达式的return相当于返回 None. 1 def functionname( parameters ): 2 "函数_文档字符串" 3 function_suite

python学习随笔(三)_字符串

字符串***    是由一个个字符组成的有序的序列,是字符的集合    使用单引号,双向引号,三引号引住的字符序列    #三引号中可以放sql语句    字符串是不可变对象 字符串元素访问    字符串支持使用索引访问    有序列的字符集合,字符序列    字符串可以是个容器,可以被一个个迭代出来,因为它是有顺序的 字符串join连接*    "string".join(iterable) -> str        将可迭代对象连接起来,使用string作为分隔符     

python学习笔记七:条件&循环语句

1.print/import更多信息 print打印多个表达式,使用逗号隔开 >>> print 'Age:',42 Age: 42   #注意个结果之间有一个空格符 import:从模块导入函数 import 模块 from 模块 import 函数 from 模块 import * 如果两个模块都有open函数的时候, 1)使用下面方法使用: module1.open()... module2.open()... 2)语句末尾增加as子句 >>> import ma

python学习笔记(03):函数

默认参数值:   只有在行参表末尾的哪些参数可以有默认参数值,即 def func(a, b=5 )#有效的 def func( a=5,b )#无效的 关键参数: #!/usr/bin/python # Filename: func_key.py def func(a, b=5, c=10): print 'a is', a, 'and b is', b, 'and c is', c func(3, 7) func(25, c=24) func(c=50, a=100) #输出: $ pyth

Python学习第七天课后总结

<html> ? python学习第七天课后总结: 今日内容: 一,,字符编码:其实就是人类的语言与机器的语言进行转化的一种媒介. ? 1,人类语言与机器语言对照关系的结构被称为:编码表 ? 常用编码表大致有以下几个: ? 1> ascii (ASCII) 现为今出现最早的编码表,采用一个字节来存储字母却无法编码汉字 ? 2> GBK 这个是专门为中文来制作的编码,国人专用 ? 3> Shift_JIS 日文使用的文件编码方式 ? 4> Euc-kr 韩文使用的编码方式

Linux下Python学习笔记 3:函数

一.什么是函数 函数简单来理解就是数字按一定规律重复出现的规则,我们知道圆的面积计算公式为:S = πr²,当我们知道半径r的值时,就可以根据公式计算出面积.在编程中函数被进一步封装成了方法,接收外部传入的参数来带入规则,继而返回相应的结果.那方法的封装其实是一种抽象的结果. 抽象是数学中非常常见的概念.举个例子: 计算数列的和,比如:1 + 2 + 3 + ... + 100,写起来十分不方便,于是数学家发明了求和符号∑,可以把1 + 2 + 3 + ... + 100记作: 100 ∑n n

(记录)python篇:七_高级特征(1)

切片 L=list(range(100)) #L列表循环100次 >>>L[:10:2] #前10个数,每两个取一个 >>>L[:1] #:前没有数字默认为0,0到1 >>>L[3] #第3个数 >>>L[1:2] #1到2 >>>L[:-1] #0到-1,-1为倒数一个数,此时为0-99 >>>L[::-1] #0到:(:表示全部),(全部):到-1,此时0为倒数第一个数,也就是99-0 A=(1

python学习交流 - 内置函数使用方法和应用举例

内置函数 python提供了68个内置函数,在使用过程中用户不再需要定义函数来实现内置函数支持的功能.更重要的是内置函数的算法是经过python作者优化的,并且部分是使用c语言实现,通常来说使用内置函数相比于用户自己定义函数实现相同功能,在执行效率和对内存的分配和使用上是要更加理想的.所以理解和熟练运用python中的内置函数,不仅可以增强代码的可读性,同时也可以提升代码的品质.下面对内置函数的使用方法进行分类介绍,以方便归纳理解. 一.查看作用域中变量相关 global () 功能:查看全局作

Python学习笔记010——匿名函数lambda

1 语法 my_lambda = lambda arg1, arg2 : arg1 + arg2 + 1 arg1.arg2:参数 arg1 + arg2 + 1 :表达式 2 描述 匿名函数不需要return来返回值,表达式本身结果就是返回值. lambda 仅简洁了代码,并不会提高程序运行效率 如果可以用 for...in...if 来完成的,最好不使用匿名函数lambda 使用lambda时,函数内不要包含循环.嵌套:如果存在,则最好使用def函数来完成,这样的代码可读性和复用性均较高 l