python基础之函数

简介: python基础之函数

Python函数


函数是python为了代码最大程度的重用和最小化代码冗余而提供的最基本的程序结构。函数也是一种设计工具,使用函数,我们也可以把复杂的系统分解为可管理的部件


函数的意义


  • 最大化代码重用和最小化代码冗余


  • 流程的分解


函数的相关语句和表达式


语句 例子
Calls my_function(‘Fir Arg’,’Sec Arg’)
def def myfunction(fir_arg,sec_arg):
return return fir_arg+sec_arg
global global x;x=new_value
nonlocal nonlocal x;x=new_value
yield def my_sqr(x): for i in range(x): yield i **2
lambda funcs=[lambda x: x*2,lambda x:x3]


编写函数


def是可执行的代码。在python里,只有def执行之后,才会生成相应的函数。要是def没有执行,相应的函数就不会生成。def语句在if、while语句甚至是其他def语句里也是合法的。


  • def创建了一个对象,并将其赋值给一个变量。def语句是生成一个函数对象,并将其赋值给函数名变量
  • lambda创建一个函数对象发送给调用者。因此,也可使用lambda表达式创建函数,这一功能允许我们把函数定义内联到语法上一条def语句不能工作的地方
  • return将一个结果对象返回给调用者。这个返回值成为函数调用的结果。
  • yield向调用者返回一个结果对象,但是记住他离开的地方
  • global声明了一个模块级的变量并被赋值。在默认情况下,所有在函数内被赋值的变量,是在这个函数里的本地变量,并仅在函数运行过程中存在。为分配一个可以在整个模块中都可以使用的变量名,函数需要在global语句中列举出来。
  • nonlocal声明了将要赋值的一个封闭的函数变量。python3.x里才有的语句。函数里嵌套函数时,都是用相同变量名,只想继承上一个函数里的相同变量时可以使用。
  • 函数是通过赋值(对象引用)传递的。参数是通过赋值传递的。但是在python中赋值就是对象引用。因此当参数被传递的对象为可变对象,当对参数进行变更时,会影响到被传递进来的变量
  • 参数、返回值以及变量并不需要声明。这个与其他变量相同,不需要提前声明。


def语句


def语句将创建一个函数并将其赋值给一个变量名:


def <变量名>([参数1,参数2,…]):
   <语句>


def语句的首行定义函数名,并引用函数对象,函数名的本质就是函数的内存地址。


参数个数是0或以上数目。


语句里,可以包含return语句,在调用函数时,会返回一个值。当没有return时,默认返回值为None。


函数里,也可以使用yield语句来生成返回值。


因为def是执行语句,因此函数是实时生成的


>>> def hanshu(x,y):
        return x*y
>>> hanshu('abc',2)
'abcabc'
>>> hanshu(2,[1,2,3])
[1, 2, 3, 1, 2, 3]


在这个函数里,x*y的结果取决于x和y的对象类型,因为python本身不定义变量,因此传递的值的类型与返回的类型都不一定是固定的类型。


python作用域


作用域针对的是变量。在使用同一个变量名时,会出现作用域问题。


  • 一个def内定义的变量名能够被def内部使用。不能在函数外部引用这个变量名。
  • def内的变量名与def外的变量名并不冲突。在def内赋值的与def外赋值的相同变量名是不同变量。


变量名有如下三种不同作用域:


  1. 全局:在def外定义的变量名是全局变量
  2. 本地:在def内部定义的叫做本地变量
  3. 其他:嵌套def时,各自的变量也是独立的。


本地变量与全局变量


>>> x=10        #全局变量
>>> def funx():
        x=20        #本地变量
        print(x)
>>> print(x)    #打印的是全局变量
10
>>> funx()      #打印的是本地变量
20
>>> x=10
>>> def funx():
    print(x)    #本地变量没有定义的话会引用全局的变量
>>> print(x)
10
>>> funx()
10


作用域法则


  • 内嵌的模块是全局作用域
  • 全局作用域的作用范围仅限于单个文件
  • 每次的函数的调用都创建了一个新的本地作用域
  • 赋值的变量名除非声明全局变量或非本地变量,否则均为本地变量
  • 所有其他的变量名都可以归纳为本地全局或者内置。


变量名使用时,查找顺序:


  • 本地变量名——在本地是否使用此变量名赋值过
  • 上一层结构中def或lambda的本地变量名——上一层是否使用此变量名赋值过
  • 全局变量名——在整个文件里是否对变量名赋值过
  • 内置变量名——python内部是否存在此变量名


如果找不到以上变量名则会报错


>>> def newdef():
    x=20
        def newdef2():
            print(x)
        newdef2()
>>> newdef()
20
>>> x=10
>>> def newdef():
        def newdef2():
            print(x)
        newdef2()
>>> newdef()
10


global语句


在函数内,想改变全局变量,可以使用global语句来定义此变量为全局变量。


 

>>> g='global'
>>> l='global'
>>> def glo():
        global g
        g='local'
        l='local'
>>> g
'global'
>>> l
'global'
>>> glo()
>>> g
'local'
>>> l
'global'


在glo函数里,都重新赋值了g与l,但在函数执行后只有g改变了,当使用global之后,当前函数里所使用的所有对变量g的更改都会对全局变量g进行更改。


除了这个方法,还有引用自己的方法(交互模式里,可以import __main__)与sys.modules的方法(可以使用引用过的所有模块,交互模式里本身可用__main__方式)。


>>> x=10
>>> import __main__
>>> __main__.x
10
>>> def glo():
    __main__.x+=1
>>> glo()
>>> x
11
>>> s=10
>>> import sys
>>> sys.modules['__main__'].s
10
>>> def glo():
    sys.modules['__main__'].s+=1
>>> glo()
>>> s
11


作用域与嵌套函数


被嵌套函数的作用域就是上级函数,在这里,想调用inner函数,必须是在函数outer里面,不能直接使用。可以使用返回内部函数的方法来提取内部函数:


>>> def outer():
        def inner():
            print('inner')
        inner()
>>> func1=outer()
inner


工厂函数


工厂函数:根据要求的对象,一个能够记住嵌套作用域的变量值的函数。


>>> def printx(x):  
        def printy(y):  #嵌套函数
            return x*y  #返回x*y的值
        return printy   #返回嵌套的函数
>>> a=printx(3)    #定义x值为3后的嵌套函数赋值
>>> a(2)
6
>>> a(3)
9


nonlocal语句


nonlocal让内部函数中的变量在上一层及以下层函数中生效(父级级父级以下)


x=1
>>> def func1():
    x=2
        def func2():
            nonlocal x
            x=3
            return x
        func2()
        print(x)
>>> func1()
3
>>> x
1


因为x并不是全局变量,所以只有在调用函数时nonlocal语句才会生效,这里x=3,当直接输出x而不调用函数时那么x=1


参数


参数简介


参数:argement或parameter,对象作为输入值传递给函数的方式。


参数传递时的简要关键点:


  • 参数的传递是通过自动将对象赋值给本地变量名来实现
  • 在函数内部的参数名的赋值不会影响调用者
  • 改变函数的可变对象参数的值也许会对调用者有影响


传递参数为可变对象与不可变对象时:


不可变对象通过值进行传递——数值、字符串等


可变对象是通过指针进行传递——列表、字典等


>>> a=3
>>> def printa(a):
        a=a+1
        print(a)
>>> a
3
>>> printa(a)
4
>>> a
3


参数传递


在这里,b[:]方式会新生成一个列表对象,因此函数里的y与setlist(b[:])是两个不同的对象。这种方法可以避免可变参数的修改。


>>> def setlist(y):
        y.append(3)
>>> a=[1,2]
>>> setlist(a[:])
>>> a
[1, 2]
>>> setlist(a)
>>> a
[1, 2, 3]


参数传递是由特定匹配规则的:


  • 位置:从左到右
  • 关键字参数:通过参数名进行匹配
  • 默认参数:为没有传入值得参数定义参数值
  • 可变参数:收集任意多基于位置或关键字的参数——参数以 或*开头
  • 可变参数解包:传递任意多的基于位置或关键字的参数——传递值以 或*开头
  • Keyword-only参数:参数必须按照名称传递


传递参数时,要注意顺序:非关键字参数->关键字参数->字典参数


>>> def myfunc(a,b):
    print(a,b)
>>> myfunc(1,2)
1 2
>>> myfunc(b=1,a=2)
2 1


匹配语法


语法 位置
func(value) 调用者  常规参数:通过位置进行匹配
func(name=value) 调用者 关键字参数:通过变量名匹配
func(*sequence) 调用者 迭代传递所有元素
func(**dict) 调用者  以‘键’为关键字,‘值’为相应值的方式传递字典所有元素
def func(name) 函数  常规参数:通过位置或变量名进行匹配
def func(name=value) 函数 默认参数值:如果没有在调用中传递的话
def func(*name) 函数 匹配并收集(在元组中)所有包含位置的参数
def func(**name) 函数 匹配并收集(在字典中)所有包含关键字的参数
def func(*arg,name) 函数 参数必须在调用中按照关键字传递


常规参数函数用法:


>>> def myfunc(a,b):
    result=a+b
    print(result)
>>> myfunc(1,2)
3


关键字参数函数:


>>> def myfunc(a,b):
    result=a+b
    print(result)
>>> myfunc(b=1,a=3)
4


迭代传递参数用法:


>>> def myfunc(a,b,c):
    result=a+b+c
    print(result)
>>> myfunc(*[1,2,3])
6


在字典中匹配所有参数用法:


>>> def myfunc(a,b,c):
    result=a+b+c
    print(result)
>>> myfunc(**{'a':1,'b':2,'c':3})
6
>>> myfunc(1,**{'b':2,'c':3})
6


默认参数函数用法:


>>> def myfunc(a,b=3):
    print(a+b) 
#当有默认参数存在时,可以只传入其他的参数
>>> myfunc(3)
6
>>> myfunc(3,2)
5


可变参数函数用法:


可变参数,可以传递任意个参数


*args方式是把所有常规参数调用与迭代调用放进一个元组里:


>>> def myfunc(*a):
    result=''.join(a)    
    print (result)
>>> myfunc('1,','2,','3')
1,2,3
>>> myfunc('first,',*['second,','third'])
first,second,third


**args方法是把任意个关键字参数与字典调用方式存放在变量名为args的字典里


>>> def myfunc(**a):
    print(a)
>>> myfunc(a='1',b='2')
{'a': '1', 'b': '2'}
>>> myfunc(a='1',b='2',**{'c':'3'})
{'a': '1', 'b': '2', 'c': '3'}


必须使用关键字传递的方法:


函数里的参数:


常规——有/无默认值

*args——存放在列表

**args——存放在字典


在python3开始,在*
args与**args中间可以加入一个“必须使用关键字传递的参数”


使用方法为是0个或多个常规参数+*或*args+“必须使用关键字传递的参数”+0个或1个**args。


>>> def myfunc(*,b,**c):
    print(b,c)
>>> myfunc(**{'b':4})
4 {}
>>> def myfun(*a,b,**c):
    print(a,b,c)
>>> myfun(2,**{'b':4,'c':5})
(2,) 4 {'c': 5}


特殊参数的传递:


在python里,函数也是对象,函数名也是变量名,因此函数本身也可以传递。


计算最大、最小值的函数时,一般用法:


#这是一个求最小值的函数
>>> def min1(*a):
    reg=a[0]    
    for i in a[1:]:        
        if i <reg:
            reg=i
    print(reg)
>>> min1(2,3,5,1,6,8)
1
#这里将最大和最小值的函数作为参数传入到求最大和最小值的函数里
>>> def lessthan(x,y):
    return x<y
>>> def morethan(x,y):
    return x>y
>>> def minmax(test,*args):
    res=args[0]    
    for i in args[1:]:        
        if test(i,res):
            res=i
    print(res)
>>> minmax(lessthan,2,3,5,1,6)
1
>>> minmax(morethan,2,3,5,1,6)
6


函数的高级用法


递归函数


>>> def mysum(s):
    if not s:        
        return 0
    else:
        return s[0]+mysum(s[1:])
        #或
>>> def mysum(s):
    return 0 
    if not s else s[0]+mysum(s[1:])
>>> mysum([1,2,3,4])
10


嵌套列表里面的值相加


>>> li=[1,2,[3,4,5],6,[7,[8,9],10]]>>> def sumlist(a):
    sum=0
    for i in a:        
        if not isinstance(i,list):  
        #判断遍历的i是否是列表
            sum += i        
        else:
            sum += sumlist(i)    
        return sum
>>> sumlist(li)
55


函数对象:属性和注解


在python里函数也是以对象的形态出现。函数名也是以变量名形式存放。因此函数也可以跨模块,以参数传递等形式。函数对象也能调用根本无关的操作:属性存储与注释。


间接函数调用:


>>> def func(x):
    print(x)
>>> func2=func
>>> func2(2)
2


把函数放进列表或元组里:


>>> def myfunc(func_name,arg1):
    func_name(arg1)
>>> def func_name(arg1):
    print (arg1)
>>> li=[(func_name,1),(func_name,2),(func_name,3)]
>>> for i in li:
    myfunc(i[0],i[1])
123


匿名函数:lambda


lambda会生成函数对象,但不赋值给任何变量。


lambda表达式:


lambda [<arg1>][,<arg2>][,<arg3>]….:expression using args


参数不是必须的,但没有参数就没有相对意义。


lambda简单说明:


lambda是一个表达式,而不是一个语句,也不是一个的代码块。——生成一个对象。


>>> myfunc=lambda a:a*2
>>> myfunc(4)
8
>>> (lambda a,b:a*b)(5,4)
20


当我们把函数对象放进列表里等操作的时候,使用def感觉很臃肿,这时可以使用lambda来简化过程。


>>> funclist=[lambda x: x**2,
          lambda x: x**3,
          lambda x: x**4]
>>> funclist[0](2)
4
>>> funclist[1](3)
27


在序列中映射函数:map


使列表中的每个值都加10


>>> l=[1,2,3,4]
>>> list(map(lambda x: x+10,l))
[11, 12, 13, 14]


函数式编程工具:filter


filter与map相似,但是针对返回的bool结果判断,结果为真,保留元素;结果为假,弃用元素。结果也是保存在可迭代对象里:


>>> list(filter(lambda x: x>1,[-1,0,1,2,3,4,5]))
[2, 3, 4, 5]


函数式编程工具:reduce


reduce函数是在functools模块里的,因此我们需要导入这个函数。


这个方法是第一次从可迭代对象里提取两个元素当作函数的参数传入,按前面的函数进行运算,保存返回值,当可迭代对象里还有元素的时候,之前的返回值为第一个参数,可迭代对象里取下一个继续运算,知道可迭代对象空。最后返回函数的返回值。


>>> from functools import reduce
>>> reduce(lambda x,y: x+y,[1,2,3,4])
10
>>> reduce(lambda x,y:x if x>y else y,[3,5,2,6,7,4,1,9])
9
相关文章
|
5天前
|
存储 JavaScript Java
(Python基础)新时代语言!一起学习Python吧!(四):dict字典和set类型;切片类型、列表生成式;map和reduce迭代器;filter过滤函数、sorted排序函数;lambda函数
dict字典 Python内置了字典:dict的支持,dict全称dictionary,在其他语言中也称为map,使用键-值(key-value)存储,具有极快的查找速度。 我们可以通过声明JS对象一样的方式声明dict
40 1
|
5天前
|
算法 Java Docker
(Python基础)新时代语言!一起学习Python吧!(三):IF条件判断和match匹配;Python中的循环:for...in、while循环;循环操作关键字;Python函数使用方法
IF 条件判断 使用if语句,对条件进行判断 true则执行代码块缩进语句 false则不执行代码块缩进语句,如果有else 或 elif 则进入相应的规则中执行
56 1
|
5天前
|
Java 数据处理 索引
(numpy)Python做数据处理必备框架!(二):ndarray切片的使用与运算;常见的ndarray函数:平方根、正余弦、自然对数、指数、幂等运算;统计函数:方差、均值、极差;比较函数...
ndarray切片 索引从0开始 索引/切片类型 描述/用法 基本索引 通过整数索引直接访问元素。 行/列切片 使用冒号:切片语法选择行或列的子集 连续切片 从起始索引到结束索引按步长切片 使用slice函数 通过slice(start,stop,strp)定义切片规则 布尔索引 通过布尔条件筛选满足条件的元素。支持逻辑运算符 &、|。
45 0
|
16天前
|
设计模式 缓存 监控
Python装饰器:优雅增强函数功能
Python装饰器:优雅增强函数功能
220 101
|
23天前
|
缓存 测试技术 Python
Python装饰器:优雅地增强函数功能
Python装饰器:优雅地增强函数功能
168 99
|
23天前
|
存储 缓存 测试技术
Python装饰器:优雅地增强函数功能
Python装饰器:优雅地增强函数功能
147 98
|
27天前
|
缓存 Python
Python中的装饰器:优雅地增强函数功能
Python中的装饰器:优雅地增强函数功能
|
3月前
|
PHP Python
Python format()函数高级字符串格式化详解
在 Python 中,字符串格式化是一个重要的主题,format() 函数作为一种灵活且强大的字符串格式化方法,被广泛应用。format() 函数不仅能实现基本的插入变量,还支持更多高级的格式化功能,包括数字格式、对齐、填充、日期时间格式、嵌套字段等。 今天我们将深入解析 format() 函数的高级用法,帮助你在实际编程中更高效地处理字符串格式化。
319 0
|
2月前
|
Python
Python 函数定义
Python 函数定义
141 1
|
1月前
|
算法 安全 数据安全/隐私保护
Python随机数函数全解析:5个核心工具的实战指南
Python的random模块不仅包含基础的随机数生成函数,还提供了如randint()、choice()、shuffle()和sample()等实用工具,适用于游戏开发、密码学、统计模拟等多个领域。本文深入解析这些函数的用法、底层原理及最佳实践,帮助开发者高效利用随机数,提升代码质量与安全性。
182 0

推荐镜像

更多