学习python第四天03【函数】

1.函数是组织好的,可复用的,用来实现单一或相关联功能的代码段;因为写代码的原则是高复用、低耦合。
2.语法:

def 函数名(参数列表):
    函数体 
    return XXX

return有两个作用,一是返回数据,二是结束方法(当函数执行到return时,函数会结束执行)。

#有参函数:
def add():
    a=1
    b=1
    print(a+b)
add()
#无参函数:
def add(a,b):
    print(a+b)
add(3,4)
#函数中不写return时,会默认返回None
def add(a,b):
    print('函数内部:',a+b)
    return a+b
ret=add(2,2)
print('返回值:',ret)
一般情况下,不允许函数内部输出结果,只能return返回它产生的结果,至于用什么方式展示结果,不用写在函数内部。

可更改(mutable)与不可更改(immutable)对象
在python中,string、tuples和numbers是不可更改的对象,而list、dict等则是可以修改的对象。

不可变类型:变量赋值 a=5 后再赋值 a=10,这里实际上是新生成了一个int值对象10,再让a指向它,而5被丢弃,不是改变a的值,而是产生了新的a。(常量不可被改变但是会被替换;被改变时阀中的名字不变,指向堆中的地址会被改变)
可变类型:变量赋值 la=[1,2,3,4]后再赋值 la[2]=5 ,则是将list  la 的第三个元素值更改,本身la没有动,而是其内部的一部分被修改了。(被改变时阀中的名字不变,指向堆中的地址会不改变,地址中的内容改变)

python函数的参数传递:
不可变类型:值传递(复制一个副本),如 整数、字符串、元组。如fun(a),传递的只是a的值,没有影响a对象本身。比如在fun(a)内部修改 a 的值,只是修改另一个复制的对象,不会影响a本身。
可变类型:类似 c++ 的引用传递,如 列表、字典。如 fun(la),则是将 la 真正的传递过去,修改后,fun外部的la也会受影响。

#不可变类型的值:
def fun(a):
    a=10
    print('函数内部a:',a)
a=5
print('调用前',a)
fun(a)
print('调用后',a)

#可变类型的值:
def fun1(q):
    q[0]='123'
    q[1]='456'
q=['456','123','789']
print('调用前',q)
fun1(q)
print('调用后',q)
#上面的那个函数使用的是传进去的q变量,下面这个两函数未使用传进去的q变量
f=['123','456','789']
def fun1(q):
    q=f
q=['456','123','789']
print('调用前',q)
fun1(q)
print('调用后',q)

def fun1(q):
    q=['123','456','789']
q=['456','123','789']
print('调用前',q)
fun1(q)
print('调用后',q)

以下调用函数时可使用的真是参数类型:

在python中定义函数,可以用必选参数、默认参数、可变参数、关键字参数和命名关键字参数,这5种参数都可以组合使用,除了可变参数无法和命名关键字参数混合(一个函数的参数里不能既有可变参数又有命名关键字参数)。但是请注意,参数定义的顺序必须是:必选参数、默认参数、可变参数/命名关键字参数和关联参数。

必选参数:有形参也必须要有实参,形参和实参一一对应。
形参是定义函数时写在括号里的参数,实参时调用函数时写在括号里的参数。

函数中可以写函数的文档注释,多行注释在函数内是文档注释,想访问函数内的文档注释可以用函数名调用__doc__方法,函数内只能写一个文档注释,除第一个外的文档注释不会被__doc__方法访问到。

默认参数:(缺省参数)缺省参数必须写在后面,可以不指定参数名,但是顺序要保证,否则要指定参数名。

在定义函数时,参数名和值都写在函数名后面的括号里的参数。

 

命名关键字参数:在调用函数时,以变量赋值的形式传入参数。在调用函数时,关键字参数不能在已经有值的必选参数后面再次为在必选参数位置上的形参赋值;如果以变量赋值的形式在被调用函数时赋值了形参(name=value),那么后面的参数也要用变量赋值的方式传参;这种方式赋值函数,不需要顺序与形参排列顺序一致。

*args不定长参数(可变参数):可变参数允许传入0个或任意个参数,这些可变参数在函数调用时自动组装为一个tuple。

在定义函数时,在括号里参数名的前面加一个*就是不定长度参数;不定长参数可以被遍历,不定长参数是元组类型参数,不定长参数在传入时会把列表类型的值作为元组中的单个值来使用;将列表作为可变长度参数时,在列表前加一个*可以将列表解包;
不定长参数在传参数时,会逐个分割参数args,去逐个对应形参列表。

**kw关键字参数:关键字参数允许你传入0个或任意个含参数名的参数,这些关键字参数在函数内部自动组装为一个dict;传参数时,只能对应到形参列表的**kw。

def student(name,age,**kw):
    print('姓名:{},年龄:{},other{}'.format(name,age,kw))
student('tom',30,aihao1='篮球',aihao2='足球')
输出结果>>>姓名:tom,年龄:30,other{'aihao1'='篮球','aihao2'='足球'}
dic={'一':123,'二':456,'三':789}
student('mi',30,**dic)
输出结果>>>姓名:mi,年龄:30,other{'一':123,'二':456,'三':567}
#关键字参数赋值方式是复制副本,函数内部修改参数不会影响外部参数的值。

组合参数:定义一个函数,包含上述若干参数:

def func(a,b,c=0,*args,**kw):
    print('a=',a, 'b=',b, 'c='c, 'args=',args, 'kw=',kw)
args=(1,2,3,4)
kw={'d':99,'x':'#'}
func('A','B') #分别赋值给a,b
func(b='B',a='A') #分别赋值给a,b
func(b='B',a='A',c=9) #分别赋值给a,b,c
func(*args) #将变量args中的值拆开分别赋值给a,b,c,args;其中args会是元组形式的值
func('A','B',**kw) #分别赋值给a,b,kw;其中kw不会被拆开分别赋值给c,args,kw,这种未赋值的情况下,这三种参数要么是默认值,要么为空。
func(*args,**kw) #将args拆开复制个a,b,c,args,将kw赋值给kw。

小结:
Python的函数具有非常灵活的参数形态,既可以实现简单的调用,又可以传入非常复杂的参数。

默认参数一定要用不可变参数,如果是可变对象,程序运行时会有逻辑错误。(因为使用可变参数,在调用时,可变参数会在一次次调用中被改变)
要注意定义可变参数和关键字参数的语法:
*args是可变参数,args接收的是一个tuple。
**kw是关键字参数,kw接收的是一个dict。

 

变量作用域:因为全局变量与局部变量的位置不同,所以它们的作用域不同、生命周期不同。

a=10
def changeNum():
    a=5
    print('函数内部:',a)
print('调用前:',a)
changeNum() # 只有在调用函数时,函数中的a才会起作用,调用完之后便会失效。函数中的a属于局部变量。
print('调用后:',a)
def changeNum():
    b=5
    print('函数内部:'b)
# 这样子会报错,因为'b'变量是局部变量,没调用函数changeNum()时,'b'变量不存在,
# 调用changeNum()函数时,'b'变量才会存在,调用结束后'b'变量失效。
print('函数外部:',b)
changeNum()
print('函数外部:',b)
a=10
def changeNum():
    # 关键字'global'告诉程序,函数里面的'a'变量是一个全局变量,
    # 这样就可以修改函数外部的'a'变量的值;
    # 如果在调用函数之前没有全局变量'a',也会在这个函数之后创建一个全局变量'a';
    global a
    a=5
    print('函数内部:',a)
print('调用前:',a)
changeNum()
print('调用后:',a)

当全局变量和局部变量同名时,局部变量优先 --> 就近一致原则。

a=10
def changeNum(a):
    print('函数内部:',(a+10))
print('函数changeNum调用前:',a)
changeNum(1)
print('函数changeNum调用后:',a)

匿名函数:python使用 lambda 来创建匿名函数;

语法:lambda [arg1 [,arg2,.....argn]]:expression
语法:lambda [参数列表]:函数体内部的表达式(代码)

def fun1(a,b):
    return a+b
# 上下这两个函数一样
sum = lambda a,b:a+b # 冒号前面的a,b将会作为参数传递到冒号后面的表达式,结果会返回给sum变量。

print(fun1(2+2))
print(sum(2+2))

将函数作为参数进行传递:

def fun1(a,b,fun):
    print(fun(a,b))
fun1(2,2,lambda a,b:a+b) #例一 # 向fun1函数传入一个匿名函数;

def fun2(a,b):
    return a+b
fun1(2,2,fun2) # 例二

Python的三个高阶函数:

# filter函数,符合传入的函数的数据将会被返回;
foo=[2,18,9,22,17,24,8,12,27]
f=filter(lambda x:x%3==0,foo) # 第一个参数是指定规则,第二个参数是被过滤的数据。
print(list(f))
# 例:从[1,4,6,7,9,12,17]中删除偶数,保留奇数:
def is_odd(x): # 先写一个判断奇数的函数
    return x%2==1
filter(is_odd,[1,4,6,7,9,12,17]) # 这里传入的is_odd函数尾部不用加小括号
# map()函数接收两个参数,一个是函数,一个是序列。map函数将序列中的每个元素传入函数中执行,并把结果作为新的list序列返回。
print(list(map(lambda x:x%2,range(10))))
# reduce()函数,将序列内所有元素进行累计操作。这个函数需要导入functools模块之后才可以使用。
import functools
li=[11,22,33]
result=functools.reduce(lambda arg1,arg2:arg1+arg2,li)
'''
reduce函数是一个二元操作函数(两个参数),它用来将一个数据集合(链表、元组)中的所有后数据进行下列操作:用传给reduce中的lambda函数(必须是一个二元操作函数)先对集合中的第1、2个数据进行操作,得到的结果再与第三个数据用lambda函数运算,最后得到一个结果
'''
# 例如:
import functools
def myadd(x,y):
    return x+y
print(functools.reduce(myadd,(1,2,3,4,5,6,7))) # 结果就是输出1+2+3+4+5+6+7的结果,即28。对所有元素求和。
'''
上面例子的计算过程:
先计算头两个元素:结果为3,在把3和第三个元素进行计算,结果为6,再把6和第四个元素进行计算,结果为10,再把10和第五个元素进行计算,结果为15,再把15和第六个元素进行计算,结果为21,再把21和第七个元素进行计算,结果为28,之后没有更多元素了,计算结束,返回最后的结果28。另外,Python内置了一个求和函数sum()。
reduce函数还可以接收第三个可选参数,作为计算的初始值。如果把上面例子的初始值(第三个参数)设为100,计算结果将变为128。100+1+2+3+4+5+6+7=128
'''

Python中的自定义排序函数:sorted()

# sorted函数是一个高阶函数,它可以接收一个比较函数来实现自定义排序,比较函数的执行机制是 传入两个待
# 比较元素x、y,如果x应排在y的前面,返回-1,如果x应该排在y的后面,返回1。如果x和y相等,返回0。
sorted([36,5,12,9,21]) # 返回新的列表
out:[5,9,12,21,36]
# 要实现倒叙排序,给参数reverse赋上True。
sorted([36,5,12,9,21],reverse=True)
out:[36,21,12,9,5]
# sorted函数的 key参数:
ol=[('Bob',75),('Adam',92),('Bart',66),('Lisa',88)]
ul=sorted(ol,key=lambda s:s[1]) # 把每一个元素中的第二个值作为排序依据。
out:[('Bart',66),('Bob',75),('Lisa',88),('Adam',92)]
sorted函数也可以对字符串进行排序,字符串默认按照ASCII码中的顺序进行排序。
# 其他排序方法
ol=[1,32,13,4,45,16,7]
ol.sort() # 使原列表的值改变
print(ol)
out:[1,4,7,13,16,32,45]

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值