• 微信公众号:美女很有趣。 工作之余,放松一下,关注即送10G+美女照片!

python基础–函数

开发技术 开发技术 2周前 (05-03) 8次浏览

函数

定义:

①函数是组织好的,可以重复使用的,用来实现单一,或相关联功能的代码段

②函数能提高应用的模块性,和代码的重复利用率

格式:

①函数代码块使用def关键字开头,后接函数标识符名称圆括号()

②任何传入参数和自变量必须放在括号中间。圆括号之间可以用于定义参数

③函数的第一行语句可以选择性地试用文档字符串——用于存放文档说明

文档字符串以''' 或者 """ 开头和结尾

④函数体以 : 开始,并且需要每段都缩进

return[表达式]结束函数,选择性的选择一个值给调用方。不带表达式的 return相当于返回None

函数可以返回多个值,但是其实返回的是一个元组

语法:

def functionname( parameters ):
    """函数_文档字符串"""
    function_suite
    return [expression]

其中:

functionname是函数名称;

parameters是参数名称;

function_suite是函数体;

expression是表达式;

注意:默认情况下,参数值和参数名称是按函数声明中定义的顺序匹配的。

pass

pass语句什么都不做,可以用它作为占位符,当不知道这个函数需要干什么,就可以使用它,让程序跑起来。

函数调用

①函数调用只需要给一个函数名称,圆括号以及圆括号里的参数,函数调用就是执行函数。

function_name(args)

参数传递

①在Python中,类型(=后)属于对象,变量(=前)是没有类型的

a=[1,2,3]
b="中国"
#以上代码中,[1,2,3]是List类型,"中国"是String类型,而变量a和b没有类型,它仅仅是一个对象的引用(一个指针),可以指向List类型对象,也可以指向String类型对象

②在Python中,定义函数时的参数是形式参数,调用函数时的参数是实际参数;

③在Python中,有不可更改对象(Number,String,Tuple)和可更改对象(List,Dictionary,Set)

不可更改对象:对象一定义就不可更改

可更改对象:对象定义后也可以更改

④在Python中,函数的参数传递:

不可变类型:类似c++的值传递,不影响对象本身。如整数,字符串,元组

可变类型:类似c++的引用传递,影响对象本身。如列表,字典,集合。

⑤**在Python中,一切都是对象,严格说引用我们不能说值传递还是引用传递,我们应该说是传递不可变对象和传递可变对象 **

函数的参数

在Python中,调用函数时可以使用的正式参数类型:必备参数,关键字参数,默认参数,不定长参数

必备参数|位置参数(positional argument):

①必备参数需要以正确的顺序传递参数

②调用时参数的数量必须和声明时的一样

#定义一个函数
def printme( str ):
    '''打印任何传入的字符串'''
    print(str)
    return
#调用printme函数
printme("我爱祖国!")

默认参数(default argument):

①定义函数时可以给参数提供一个默认值

②调用函数时,默认参数的值如果没有传入,则被认为是默认值。

#定义一个函数
def printme( name , str="祖国" ):
    '''打印任何传入的字符串'''
    print(f"{name}爱{str}!")
    return
#调用printme函数
printme("张三")

注意:

  1. 定义默认参数时,默认参数必须指向不变对象(字符串,元组,数字)
  2. 默认参数一般为变化小的参数
  3. 必备参数在前,默认参数在后
#默认参数的坑:
def add_end(L=[]):
    L.append('END')
    return L
add_end()
#result:['END']
add_end()
#result:['END','END']
add_end()
#result:['END','END','END']
原因:Python函数在定义时,默认参数L的值就被计算出来了,即[],因为默认参数L也是一个变量,他指向对象[],每次调用该函数,如果改变了L的内容,则下次调用时,默认参数的内容就变了,不再是函数定义时的[]了
#修改:
def add_end(L=None):
    if L is None:
        L=[]
    L.add_end('END')
    return L

可变参数:

  1. 可变参数就是传入的参数个数是可变的。
  2. 可变参数的定义:定义参数时,参数前加*
  3. 可变参数允许传入0-N个参数,可变参数在函数调用时自动组装成为一个Tuple。
# *args
def calc(*numbers):
    sum=0
    for n in numbers:
        sum=sum+n*n
    return sum
calc(1)
calc(1,2,4)
calc(1,2,3,4,4)
#因为有for循环,所以numbers一定是一个list|tuple,所以传递参数时需要list|tuple作为参数,但由于参数使用的是可变参数,而可变参数本身就是一个tuple来接收参数,所以不需要再传参数时传入list|tuple

#如何把num作为可变参数传进去:
#方法:在list|tuple前加*变成可变参数,然后再传入进去。
num=[1,2,3]
def calc(*numbers):
    sum=0
    for n in numbers:
        sum=sum+n*n
    return sum
calc(*num)

关键字参数:

  1. 关键字参数就是参数定义时,有参数名的参数
  2. 关键字参数的定义:定义参数时,参数前加**
  3. 关键字参数允许传入0-N个含参数名的参数,关键字参数在函数调用时自动组装成为一个dict。
# **KWargs
def person(name,age,**KWargs):
   print('name:',name,'age:',age,'other:',KWargs)
person('xwh',12)

#问题:如何把dict作为关键字参数传入进去
#方法:在dict前加**变成关键字参数,然后再传入进去。
ps={'city':'wh'}
def person(name,age,**KWargs):
   print('name:',name,'age:',age,'other:',KWargs)
person('xwh',12,ps)

命名关键字参数:

  1. 命名关键字参数就是检查是否有规定名字的参数
  2. 命名关键字参数的定义:定义参数时,前方参数和后方参数使用 * 隔开,* 后面的参数被视为命名关键字参数
  3. 如果函数定义中已经有了可变参数,那么就不用使用*分隔符
  4. 命名关键字参数传入时必须指定参数名,否则python会认为是位置参数。
# *
def person(name,age,*,city,job):
    print(name,age,city,job)
person('xwh',24,city='wh',job='aj')

作用域

全局作用域

  • 在函数外的变量称为全局作用域的全局变量。
    • 全局作用域的变量可以在任何位置被使用。
    • 全局变量的生命周期:

局部作用域

  • 在函数内的变量称为局部作用域的局部变量。
    • 局部变量不能在全局作用域内使用。
    • 局部作用域不能使用其他局部作用域的变量。
    • 局部变量的生命周期:
    • 如果需要在一个函数内修改全局变量,可以使用关键字global

引用

  • 引用:引用是一个值,指向地址。
  • 变量的引用:是指向一个变量的地址值。
  • 列表的引用:是指向一个列表的地址值。
  • 把一个变量赋值给另一个变量:实际上是把变量的引用赋给了另一个变量。
  • 把一个列表赋值给一个变量:实际上是把列表的引用赋给了变量, 即变量不保存列表的值,仅仅是保存列表的引用。
l = [1,2,3,4,5]
s = l
print(l)
print(s)
s.append(6)
print(l)
print(s)
  • 解释:为什么只改变了s的值,l的值改变了?
    • l = [1,2,3,4,5]:因为当创建列表时,是将对列表的引用赋值给了变量。
    • s = l:而这行代码只是将l中的列表引用拷贝到s,而不是列表本身。这就意味着存储在l和s中的值,现在都指向了同一个列表。所以只有一个列表。如果s对其列表进行操作,那么也就是l对此列表进行同样的操作,所以l中的值改变了。

参数传递

传递引用

当函数被调用时,参数的引用被赋值给函数的形式参数,对于列表(字典,集合)等可变类型数据,函数的形式参数得到的是引用的拷贝,所以在函数中修改了参数的值,那么原参数也会被修改。

值传递

当函数被调用时,参数的引用被赋值给函数的形式参数,对于数字,字符串,元组等不可变类型数据,由于不可变类型一经创建就不可以修改,所以赋值代表创建了新的对象,所以在函数中修改了参数的值,那么原参数不会被修改。

函数高级

  1. 函数是Python内建的封装
  2. 函数是面向过程程序设计的基本单元
  3. 函数式编程:一种抽象程度很高的编程范式
  4. 函数式编程的特点:允许把函数本身作为参数传递到另一个函数,还允许返回一个函数

高阶函数

  1. 函数的别名:函数本身也可以赋值给变量,即变量可以指向函数。
  2. 函数名也是变量:函数名是指向函数的变量
  3. 高阶函数:变量可以指向函数,函数的参数可以接收变量,那么一个函数就可以接收另一个函数作为变量,这种把函数作为变量的函数称为高阶函数。

闭包

  1. 函数除了可以接收函数作为参数外,还可以把函数作为返回值返回。
  2. 闭包:在一个函数 f1() 中定义另一个函数 f2(),并且,内部函数 f2() 可以引用外部函数 f1() 的参数和局部变量,当 f1()返回f2() 时,相关的参数和变量都保存在返回的函数中,这就称之为闭包
    1. 当调用 f1() 时,每次调用都会返回一个新的函数,即使传入的参数相同
  3. 注意:返回函数不要引用任何循环变量,或者后续会发生改变的变量。如果一定要引用循环变量,可以再创建一个函数,使用该函数的参数绑定循环变量当前的值,无论循环变量后续如何改变,已经绑定到函数参数的值不变。

匿名函数

在Python中使用Lambda来创建匿名函数

①lambda只是一个表达式,函数体比def简单得多

②lambda的主体是一个表达式,而不是代码块。仅仅能在lambda中封装有限的逻辑进去。

③lambda函数拥有自己的命名空间,且不能访问自有参数列表之外或全局命名空间里的参数。

④虽然lambda看起来只能写一行,却不等同于c或c++中的内联函数,后者的目的是调用小函数时不占用内存从而增加运行效率。

⑤语法:

lambda [arg1[,arg2,...,argn]]:expression
#使用lambda
sum = lambda s1,s2:s1+s2

#调用sum函数
print(f"s1+s2的值是{sum(1,2)}")

装饰器(dec++orator)

  • 函数是一个对象,且函数对象可以被赋值给变量,所以通过变量也可以调用函数。
def now():
	print('2021-3-11')
print("函数也是变量now=",now)
f = now
print("函数对象可以被赋值给变量f=",f)
print("变量也可以调用函数f()=",f())
  • 函数对象有一个 __name__ 属性:获取函数名称
print("函数对象的‘__name__’属性获取函数名",now.__name__)
  • 装饰器:在代码运行期间动态增加功能的方式。
  • 装饰器本质上就是一个返回函数的高阶函数
  • 使用装饰器:借助Python@语法 ,把装饰器置于函数定义处
def log(func):
	def wrapper(*args,**kw):
		print("call %s():" % func.__name__)
		return func(*args,**kw)
	return wrapper
#log()内部定义wrapper(),并且log()返回wrapper()

# @log == log(now)
@log
def now():
	print('2021-1-2')

now()
  • 如果装饰器自带参数:那么再加一层返回装饰器函数名称。

偏函数(Partial func++tion)

  • functools.partial的作用就是:把一个函数的某些参数给固定住(即设置默认值),返回一个新的函数

程序员灯塔
转载请注明原文链接:python基础–函数
喜欢 (0)