7-python函数入门

在这里插入图片描述

python函数入门

如果你学过其他编程语言,就知道,函数可以将要实现的一个个功能分别合并成一个个小块,要使用的时候只需调用即可。比如,我们要求 1 + 2 + 3 + . . . + 100 1+2+3+...+100 1+2+3+...+100,很简单,写个循环就可以了,那我们想再求 1 + 2 + . . . + 1000 1+2+...+1000 1+2+...+1000呢,你可能会想,把上面那个的代码复制粘贴,再改改几个数就行了,但是,假如我们还要你求 1 + . . . + 2000 1+...+2000 1+...+2000, 1 + . . . + 3000 1+...+3000 1+...+3000呢,如果还复制粘贴,是不是觉得很麻烦。因此,我们希望,可以用一句代码实现这样一个功能:从a一直加到b,我们只需告诉它a和b是什么就行了。这时,函数就可以上场了,我们把a和b的值告诉函数,再写上自己要实现的功能,然后函数内部就会自动去帮我们完成 a + . . . + b a+...+b a+...+b 。这样,我们只要更改不同的参数a和b,就能实现上述需求了,是不是很简单,接下来我们就学习如何设计一个符合自己需求的函数。

一、学会声明和调用函数

要调用一个函数,首先得有这个函数才行,因此我们要先声明(定义)一个函数。

声明函数

在python中,声明一个函数的形式一般为:

def <函数名>(参数列表):
    <函数语句>
    return <返回值>
  1. 其中返回值不是必须的,甚至return语句也可以没有,在这两种情况下函数都默认返回 None
  2. 参数列表如果有多个参数要用逗号 , 隔开,有些函数也可以没有参数列表。注意没有参数时,也不能省略括号和冒号():
  3. 函数语句必须缩进,以表示这些语句是属于这个函数的。

例如:

def hello(): #无参数
    print('hello world')
def Sum(a, b): #计算 a +...+ b
    s = 0
    while a <= b:
        s = s + a
        a += 1
	return s  #有返回值
调用函数

实际上在之前使用输入输出函数input()、print(),我们就已经在调用函数了,这些是python自带的已经定义好的函数,而调用自己函数的方法和这些是一样的,只不过是在调用前必须先声明。

例如:调用上面第1个函数:

def hello(): #先声明
    print('hello world')
    
hello()  #再调用

#out: hello world

调用第2个函数:

def Sum(a, b): #先声明
    s = 0
    while a <= b:
        s = s + a
        a += 1
	return s  #有返回值

s = Sum(1,10) #再调用
print(s)

#out:55

注意:调用函数时,参数书写有两种方法

  1. 如:Sum(1, 10) 注意顺序不能颠倒,这种传参方法叫位置参数法;
  2. 如:Sum(a=1, b=10)Sum(b=10, a=1),顺序可以颠倒,这种传参方法叫关键字参数法

二、深入函数

默认参数

有的函数,在调用时你既可以传参数,也可以不传参数,例如,改写上面的 Sum 函数,不传入参数时默认计算1+…+100,传入参数时从多少开始到多少结束就从多少开始多少结束。

def Sum(a= 1, b= 100):
    s = 0
    while a <= b:
        s = s + a
        a += 1
	return s 

我们调用一下它:

... #这里是声明部分

s1 = Sum() #不传参数
s2 = Sum(10,1000) #传参数

print('s1= %d'%s1)
print('s2= %d'%s2)

#out:
s1= 5050
s2= 1501500

如果在声明函数时,参数中既有默认参数,也有普通参数,那么在声明时必须把默认参数放在普通参数后面,否则会报错,例如:

错误示例:

def test(a=3, b, c):
    pass

SyntaxError: non-default argument follows default argument

正确示例:

def test(b,c,a=3):
    pass

总之记住,默认参数放在普通参数后面

可变数量的参数传递
用元组收集参数:

有一种情况,可能需要传入多个参数,但在定义时还不知到要声明多少个参数,此时在参数名前加上 * 则表示这是一个可变长参数,如果在调用时,这个可变长参数前面的所有参数都已经被赋值后,还有多余的参数,那么这些多余的参数就会被收集在一个元组中,元组名就是带星号 * 的参数的参数名。

例如:

只有可变长参数

def test(*t):
    print(t)
test(1)
test(1,2,3)

#out
(1,)
(1, 2, 3)

既有普通参数也有可变长参数,一般会把可变长参数放在最后面,例如

def test(a,b,*t):
    pass

当然也可以把可变长参数放在前面,但在调用时就只能用关键字参数法来传递参数,否则后面的位置参数将因为无法获取值而发生错误。如:

错误传参法:

def test(*t,a):
    print(t)
    print(a)
    
test(1,2,3) 	#位置参数法传参,发生错误

TypeError: test() missing 1 required keyword-only argument: 'a'

正确传参法:

test(1,2,3,a=4) 
#关键字参数传参,注意调用时a=4也不能调换顺序,如test(a=4,1,2,3)

#out:
(1, 2, 3)
4

所以,为了避免不必要的麻烦,最好在声明时把可变长参数放在最后面,不过这种声明在调用时不能使用关键字参数进行传参,只能用位置参数法

例如:

错误传参法:

def test(a,*t):
    print(t)
    print(a)
    
test(a=1,3,4,5) #关键字参数法
SyntaxError: positional argument follows keyword argument

正确传参法:

test(1,3,4,5)

#out:
(3, 4, 5)
1

好麻烦,看得头都大了,如果感到乱的听我一句话,记住第二种方法,很多时候我们更喜欢按顺序传入参数,简单又好看。>__<

用字典收集参数

用元组收集参数时,调用时提供的参数不能是关键字参数,如果要收集不定数量的关键字参数,可以在自定义的参数前加两颗星 **,如 **valuename 这样一来,多余的关键字参数就会以字典的方式被存起来了,字典名就是 valuename

注意:声明和调用时关键字参数要放在最最最后面

例如:

def test(a,b=666,*t,**d):
    print(a)
    print(b)
    print(t)
    print(d)
test(1,2,3,4,5,c=10,d=11)
#out:
1
2
(3, 4, 5)
{'c': 10, 'd': 11}
拆解序列的参数传递

前面讨论的参数传递方法都是位置参数或关键字参数,实际上调用时还可以将元组和字典进行拆解调用

  • 拆解元组:提供位置参数
  • 拆解字典:提供关键字参数

例如:

def test(a,b,c):
    return a + b + c
t = (1,2,3)
d = {'a':4,'b':5,'c':6} #键要与参数一一对应

print('拆解元组:',test(*t))
print('拆解字典:',test(**d))

#out:
拆解元组: 6
拆解字典: 15
函数调用时参数类型问题

python中元素有可变与不可变之分,像整数、浮点数、字符串、元组等都是不可变的,而列表、字典是可变的。

在函数调用时,若传入的参数是不可变参数,那么在函数内部对它的值修改时,在函数外部它的值是不变的,例如:

a = 1
def change(a):
    a = 2
    print('函数调用时a的值是%d'%a)
    
print('函数调用前a的值是%d'%a)
change(a)
print('函数调用后a的值是%d'%a)

#out:
函数调用前a的值是1
函数调用时a的值是2
函数调用后a的值是1

可见,虽然在函数内部a的值发生了改变,但是函数调用前后a的值一样

然而,如果在调用时传入的参数是可变的,那么在函数内部对它的值修改时,在函数外部它的值也会改变,例如:

b = [1,2]
def change(b):
    b.append(3)
    print('在函数调用时b是:',b)

print('在函数调用前b是:',b)
change(b)
print('在函数调用后b是:',b)

#out:
在函数调用前b是: [1, 2]
在函数调用时b是: [1, 2, 3]
在函数调用后b是: [1, 2, 3]

看,调用前后发生改变了吧!

列表,字典作为函数参数时的一个"陷阱":

def fun(L=[]):
    L.append('abc')
    print(L)

#三次调用这个函数
fun()
fun()
fun()

#看看输出结果:
['abc']
['abc', 'abc']
['abc', 'abc', 'abc']

哈哈,意外吧!所以说在调用函数时(不仅要注意顺序,而且)一定要注意传入参数的类型啊。

三、变量作用域

python中,作用域分以下几个:

  1. 内置作用域:python预先定义的
  2. 全局作用域:范围是所编写的整个程序
  3. 局部作用域:范围是某个函数内部
  • 每次运行函数,都会创建一个新的命名空间,这个新的命名空间就是局部作用域,同一函数在不同时间执行,其作用域是独立的(即互不影响);

  • 不同函数作用域不同,可以有相同的参数名。

  • 在函数内部声明过的变量,在函数外依然可以使用,并且在程序执行过程中,其值互不影响。(内外分明,互不影响)

看个例子:

def fun():
    a = 1		#在函数内
    print('局部',a)
    
a = 2		#在函数外
print('全局',a)
fun()
print('全局',a)

#out:
全局 2
局部 1
全局 2

然而,有一种方法可以在函数内部修改全局变量,就是在变量名前使用global 关键字

def fun():
    global a    #在函数内使用全局变量
    a = 3
    print('函数内',a)

a = 2		#在函数外
print('函数外',a)
fun()
print('函数外',a)

#out:
函数外 2
函数内 3
函数外 3

可以看到,在调用函数后函数外的变量 a 的值发生了变化。

四、使用匿名函数lambda

lambda 可以用来创建匿名函数,也可以将匿名函数赋值给一个一个变量供调用,它是python中比较特殊的一种声明函数的方式,来源于 LISP 语言,其语法形式为:

lambda params:expression
  • params:实际上就相当于函数的参数列表,中间有多个参数要用逗号 , 隔开
  • expression:就相当于函数返回值的语句

相当于没有函数名的一般函数,但一般函数必须要有函数名。

def <函数名>(params):
    return expression

lambda函数常在以下场景使用

  • 简单匿名函数:写起来快速简单
  • 只用一次的函数:当你在定义函数而为一个函数名头疼时,并且这个函数只用一次,你可以选择匿名函数
  • 为了代码清晰:某些时候使用匿名函数可以让代码清晰

例如:

z = lambda x,y:x ** 2 + y ** 2
z(3,4)

#out:
25

五、python常用内建函数

内建函数:指在python程序中没有导入任何模块或包就可以用的函数,除了之前用过的一些外,还有:

  1. help(obj):显示对象帮助信息
    在这里插入图片描述

  2. bin(aint):十进制整型数据转为二进制的字符串形式
    在这里插入图片描述

  3. hex(aint):十进制整型数据转为十六进制的字符串形式
    在这里插入图片描述

  4. oct(aint):十进制整型数据转为八进制的字符串形式
    在这里插入图片描述

  5. callable(obj):检查对象是否可以被调用(即函数)
    在这里插入图片描述
    在这里插入图片描述

  6. chr(aint):将ASCII码转为字符
    在这里插入图片描述

  7. ord(char):将字符转为ASCII码
    在这里插入图片描述

  8. filter(fun, seq):对序列的数据进行过滤,传入两个参数,第一个fun是个函数,第二个seq是个序列
    在这里插入图片描述

  9. map(fun, seq):对序列的数据逐个变换,传入两个参数,第一个fun是个函数,第二个seq是个序列
    在这里插入图片描述

  10. isinstance(obj,typestr):检查对象是否为某种类型的数据
    在这里插入图片描述
    在这里插入图片描述

最后,提醒一点,filter()map()这两个函数比较重要,最好记住。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

[小G]

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值