python 学习 10 函数与代码复用

1 .函数的概念

函数是一段具有特定功能的,可重用的语句组,用函数名来表示并通过函数名进行完成功能调用,函数也可以看作是一段具有名字的子程序,可以在需要的地方调用执行,不需要在每个执行的地方重复编写这些语句,每次使用函数可以提供参数作为输入,以实现对不同数据的处理,函数执行后,还可以反馈相应的处理结果。
有时候我们需要输出多个语句,但我们不想反复去复制粘贴,就可以通过给一个语句组取一个名字,在后面我们就可以直接通过这个名字来进行调用。(把某个特定的语句组封装成一个函数以后通过函数名就可以直接调用)

2 .python中函数的定义

python 定义一个函数使用def关键字,语法形式如下:

def<函数名><参数列表>):   # 函数名同变量名 (形参:语句组中可以变化的数据,多个参数用逗号隔开
	<函数体>
	return<返回值列表>

函数名的命名同变量名

3 实例

3.1 实例1 打印金字塔

def print_star(n):形参
    """
    打印一个八层金字塔
    :return:
    """

     # n 层数 
    for i in range(n):
        # 计算星星的个数
        star_num = i * 2 + 1
        # 计算空格
        space_num = n - i - 1
        # 输出
        print(' '*space_num + '*' * star_num)

print_star(5)实参
print_star(6)
print_star(7)
#  打印出三个金字塔

3.2 实例2 唱生日歌

过生日要为朋友唱生日歌,歌词为:

Happy birthday to you!

Happy birthday to you!

Happy birthday,dear<名字>

Happy birthday to you!

编写程序为Mike和Lily输出生日歌,最简单的方式是重复使用print()语句

# 最简单的方式
# 最简单的方式
print('Happy birthday to you!')
print('Happy birthday to you!')
print('Happy birthday, dear Mike!')
print('Happy birthday to you!')

print('Happy birthday to you!')
print('Happy birthday to you!')
print('Happy birthday, dear Lily!')
print('Happy birthday to you!')

Happy birthday to you!
Happy birthday to you!
Happy birthday, dear Mike!
Happy birthday to you!
Happy birthday to you!
Happy birthday to you!
Happy birthday, dear Lily!
Happy birthday to you!

用函数的方式

# 定义函数
def happy():
    print('Happy birthday to you!')

def happy_birthday(name):
    happy()
    happy()
    print('Happy birthday, dear {}!'.format(name))
    happy()

# 调用函数  函数名+括号表示调用
happy_birthday('Mike')
print()
happy_birthday('Lily')


Happy birthday to you!
Happy birthday to you!
Happy birthday, dear Mike!
Happy birthday to you!

看起来比上面的直接print()还多了两行代码,但是要考虑如果要给100个人唱生日歌的情况

4 .函数的调用过程

程序调用一个函数需要执行以下四个步骤:

  • 调用程序在调用处暂停执行
  • 在调用时将实参赋值给函数的形参
  • 执行函数体语句
  • ‘函数调用结束给出返回值,程序回到调用前的暂停处继续执行
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    函数名的命名规范:只能由数字字母下划线组成,不能用数字开头,命名风格,尽量简短,见名知义,推荐使用下划线命名法,每个单词之间用下划线连接
    注意点:不能和python中的关键字重名,也不要和python中的内置函数重名(如果重名会覆盖内置函数)

5.函数的参数

定义函数时()里的参数叫做形参(形式参数),它只是一个变量名,供函数体中的代码调用,函数调用时,传入()里面的参数叫做实参(实际参数),会传递给形参,供函数体执行

5.1形参

定义函数的时候,形参根据功能的不同,可以定义几种类型

- 必须参数

有些函数,必须传递某个参数才能运行,这种参数就需要定义为必须参数,调用的时候必须要传实参,否则报错,直接定义在函数名后面的()中的形参就是必须参数
例如上面 happy_birthday(name) 函数中的name和print_star(n)中的n

- 默认参数

某个形参有默认值,可以定义为默认形参
定义规范:在函数名后()中,以参数名=默认值的形式定义的形参就是默认参数
调用的时候如果不传实参,那么就使用默认值,
调用的时候,传递实参会覆盖默认值。
案例1

def print_star(n=3):
    """
    打印一个八层金字塔
    :return:
    """

     # n 层数
    for i in range(n):
        # 计算星星的个数
        star_num = i * 2 + 1
        # 计算空格
        space_num = n - i - 1
        # 输出
        print(' '*space_num + '*' * star_num)

print_star()

案例2
定义一个函数,它接收两个参数content和times
content是函数要打印的内容
times是函数打印的次数,如果不传递times则默认打印1次,

def print_times(content, times=1):
    '''
    重复打印
    :param content:打印内容
    :param time: 打印次数,默认值为1
    :return:
    '''

    for i in range(times):
        print(content)

print_times('好好学习')
print_times('天天向上',3)

# 好好学习打印一遍,天天向上打印三遍。

注意:默认形参要写在必须参数的后面

- 不定参数(不确定传递几个参数)

在定义函数时,不确定在调用时会传递多少个参数时,可以定义为不定参数。
不定参数根据传递实参的不同分为两种

①:位置不定参

以位置参数传递的不确定个数的参数就需要通过位置不定形参来解决
定义:在函数名后的()中,在形参前加星号可以定义位置不定参,通常它会被定义为*args,它用于接收函数调用时,以位置传递过来的超过形参数量的多余的实参。
注意:不定参数必须定义在默认参数后面
作用:所有传递进来的多余的位置实参会形成一个元祖赋值给位置不定参。
案例1:

def func(a, b=1, *args):  # * 只起一个修饰作用,参数还是args
    print(a,b)
    print(args)

func(1)
print('--------')
func(1,2)
print('---------')
print(1, 2, 3, 4)

1 1
()
--------
1 2
()
---------
1 2
(3,4)

案例2:
定义一个函数,接收两个以上的数,打印它们的和

def my_sum(x, y, *args):
    '''
    接收两个以上的数,打印它们的和
    :param a:一个数
    :param b:一个数
    :param args:一些数
    :return:
    '''
    sum = x + y
    for num in args:
        sum = sum + num
    print(sum)


my_sum(1, 2, 3, 4, 5)
②:关键字不定参数

不定参,不确定形参传递几个参数
当传递不确定关键字形式的实参的时候,使用关键字不定形参来解决。
传递的多余的关键字实参会形成字典,然后赋值给关键字不定参。
**kwargs

def func(a, b=1, **kwargs):
    print(a, b)
    print(kwargs)


func(1)
print('-------------')
func(1, 2)
print('-------------')
func(1, 2, c=3, d=4, f=5)

1 1
{}
-------------
1 2
{}
-------------
1 2
{'c': 3, 'd': 4, 'f': 5}

可以同时定义位置不定参和关键字不定参数
这个时候传递的多的位置实参会被*agrs形成元祖,
传递的多的关键字实参会被**kwargs形成字典

def func(a, b=1, *args, **kwargs):
    print(a, b)
    print(args)
    print(kwargs)


func(1)
print('-------------')
func(1, 2)
print('-------------')
func(1, 2, 3, 8, c=4, d=5, f=6)

1 1
()
{}
-------------
1 2
()
{}
-------------
1 2
(3, 8)
{'c': 4, 'd': 5, 'f': 6}

Process finished with exit code 0

5.2 实参

调用函数时传递的实际参数
根据调用方式的不同有两种方式

以位置传递实参

调用函数时,传递实参时默认会按照形参的位置一 一对应,这种实参传递叫做位置传递。
案例:定义一个函数实现打印一个数的n次幂

def my_pow(x, n):
    '''
    打印x的n次幂
    :param x:一个数
    :param n:一个数
    :return:
    '''
    print(x ** n)

my_pow(2, 3)  # 8
my_pow(3, 2)  # 9
以关键字传递实参

调用函数时,传递实参时以形参名=实参的形式传递参数,叫做关键字参数。

def my_pow(x, n):
    '''
    打印x的n次幂
    :param x:一个数
    :param n:一个数
    :return:
    '''
    print(x ** n)

my_pow(n=3, x=2)
my_pow(2, n=3)
# 结果是一样的
# 有时候可能又有位置传递又有关键字传递
# my_pow(2, n=3) 可以
#  my_pow(n=3,2)报错  注意:不能把关键字传递写在前面

注意,当实参有位置传递和关键字传递两种方式时,不能把关键字传递方式放在前面。
解包: * 和 ** 除了在定义不定参的时候会用到,我们也可以用它来解包


6 传递实参–可迭代对象解包

什么叫*解包?
当我们想将一个迭代对象中的元素依次当作位置参数传递给一个函数的时候,我们可以在这个迭代对象的前面加一个星号。
先思考几个问题
例1:

def my_sum(x, y, *args):
    '''
    接收两个以上的数,打印他们的和
    :param x: 一个数
    :param y: 一个数
    :param args:
    :return:
    '''
    sum = x + y
    for num in args:
        sum = sum +num
    print(sum)
ls = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99]
 my_sum(ls[0],ls[1],ls[2],...ls[99]).....这样写也太繁琐了吧,那我们要怎么解决呢?
 my_sum(*ls)  # 等价于 my_sum(ls[0],ls[1],ls[2],...ls[99]) 会依次把元素往里面传
 # 4950

调用函数传参的时候可以对元组或者列表进行解包
例2:

f(*[1, 2, 3])  # 等价于 f(1,2,3)
f(*'abc')  # 等价于 f('a', 'b' ,'c')
(1, 2, 3)
('a', 'b', 'c')

7.传递实参–字典解包

什么是字典解包?

def connect(host, user, password, db, port, charset):
    '''
    数据库连接
    :param host:
    :param ueer:
    :param password:
    :param db:
    :param port:
    :param charset:
    :return:
    '''
    print(host)
    print(user)
    print(password)
    print(db)
    print(port)
    print(charset)


db_config = {
    'host': '127.0.0.1',
    'user': 'root',
    'password': '123456',
    'db': 'lemonban',
    'port': 3306,
    'charset': 'utf8'
}
connect(host=db_config['host'], user=db_config['user'],
        password=db_config['password'], db=db_config['db'],
        port=db_config['port'], charset=db_config['charset'])

这样也太麻烦了!
这个时候我们可以使用**号解包字典
优化:

connect(**db_config) # 等价于上面的 connect(host=db_config['host']).....

注意:字典的键一定要和参数的名字全部对的上。

8 .函数返回值

函数的返回值,通过关键字return来定义
return后面返回一个数据,函数调用完接收到的就是这个数据
return后面返回一个以上的数据,函数调用完接收到的是一个元组
定义函数的时候什么时候需要写return?什么时候不写?
看需求!
比如:打印三角形的函数?不需要return
比如:获取数据的长度?需要在函数里面把数据的长度return出来

def my_sum(x, y, *args):
    '''
    接收两个以上的数,打印他们的和
    :param x: 一个数
    :param y: 一个数
    :param args:
    :return:
    '''
    sum = x + y
    for num in args:
        sum = sum + num
    print(sum)


res = my_sum(1, 2, 3)  # 6
print(res)  # None  没有返回值

def my_sum(x, y, *args):
    '''
    接收两个以上的数,返回他们的和
    :param x: 一个数
    :param y: 一个数
    :param args:
    :return:和 一个数
    '''
    sum = x + y
    for num in args:
        sum = sum + num
    print(sum)

    return sum


res = my_sum(1, 2, 3)  # 6
print(res)  # 6


def add_num()
	a = 10
	b = 20
	c = a+ b
	d = a- b
	return c,d
aa,bb =add_number()
print(aa)
print(bb)

返回多个值

9 .变量作用域

python中一个变量能够被访问的范围叫做作用域,根据作用域的大小简单的分为全局变量和局部变量

9.1 全局变量

python是解释型编程语言,解释器在运行一个python程序时会在计算机内存中申请一块内存用来运行这个程序,全局变量在这块内存空间中都可以被访问和修改。直接定义在函数外的变量就是全局变量,在程序运行的全过程有效.
全局变量,在脚本中顶格定义的变量,定义后在整个脚本中都可以访问到这个变量。全局变量的作用域就是在文件内部。

name = '陈浩'


def func():
    print(name)


func()    # 陈浩

注意:变量要先定义再调用。

9.2 局部变量

定义在函数里的变量就是局部变量,它只在它定义的函数里起作用,一旦函数执行完毕它就不存在了

def func():
    print(name)


def func2():
    name = '刘德华'
    print(name)  # 在函数里面找变量的时候会首先找它自己


name = '心蓝'

func()
func2()
print(name)
心蓝
刘德华
心蓝

在函数外部不能直接访问函数内部定义的局部变量。
在这里插入图片描述
在函数里面可以访问全局变量,在函数外面不能访问函数里面的变量。
在这里插入图片描述
打个比喻
全局变量:手机流量,不管在家里还是外面都可以使用
局部变量,我家的wifi,只能在我家这一点范围使用
注意:在命名的时候局部变量尽量不要跟全局变量重名,如果重名会有什么影响呢,没有什么影响,但是的话在使用的时候就可能会出现问题。

9.3全局变量的访问和修改

函数外部可以直接修改全局变量
函数内部不能对全局变量进行修改
在这里插入图片描述

9.4 变量访问的优先级

在家上网先看WiFi能不能用,不能用再用流量
在这里插入图片描述
函数内部访问变量,优先查找局部变量,如果布局变量中没有才会引用全局变量。
函数外部访问变量,不会去找局部变量,会直接去找全局变量。

为什么自定义的函数和内置函数重名会覆盖掉内置函数?

因为引用的优先级是先找自己的,如果自己没有定义的话才会去python的内建环境(全局变量)中去找,如果在自己的模块里面定义了一个叫id的函数,那么按照引用的优先级它会先找自己的,找到了有id,它就不会去找全局的id了。自定义的函数,在当前模块中的优先级高于内置函数。

9.5 如何在函数内部修改全局变量

通过 global 关键字声明变量,比如下面的a,声明之后 ,在函数内的a都是全局变量,也可以直接在函数里面创建全局变量,例如下面的b。
注意:如果要在函数内修改全局变量,要把global放在第一行,避免后面出错.(问的概率比较高)
在这里插入图片描述

9.6 扩展

在函数内部能不能动态的往可变数据类型中添加或删除元素?
在这里插入图片描述这样是不行的

换一种方式
在这里插入图片描述

在函数内部可以动态的往可变类型数据中添加或删除数据(因为没有改变1全局变量指向的内存地址) 比如列表 使用append extend 都可以,只要不修改它的id,对于可变数据类型,可以动态地往里面添加元素。如果赋值的话,只是指向相同的引用,id是不相同的

10. python内置函数

常用内建函数

10.1 学过的内置函数

在这里插入图片描述

更多方法及其使用详见: 官方文档.

10.2 内置函数拓展

注意,要同种数据类型,才能做比较。
min 获取最小值
在这里插入图片描述
max 获取最大值
在这里插入图片描述
sum 求和
在这里插入图片描述
在这里插入图片描述

eval:识别字符串中有效的python表达式
在这里插入图片描述
10 *20是一个有效的python表达式,但是它是一个字符串,在这里不会把它当作一个python代码去执行,eval可以去识别python中的有效表达式并执行(只要python能认识就是有效的python表达式,在上面的代码中会去掉引号,把结果输出出来。不管字符串里面放什么东西,它都可以通过eval去识别出来。当用eval去转化数据的时候就相当于把字符串两端的引号脱掉,剩下什么就是什么。
如果不是有效的Python表达式它会报一个语法错误(后面主要用于从excel里读取数据)
在这里插入图片描述
zip:聚合打包
通常用来做聚合打包
把两个列表仍进去,会把仍进去数据的索引进行聚合,先把索引为0的聚合起来放在一个元组里面,再把索引为1的聚合起来,放在一个元组里面…

两个字典聚合
在这里插入图片描述
如果两个列表长短不一会以最短的为基准,多出的数据不要会删掉
三个列表聚合
在这里插入图片描述聚合只是把里面的数据取出来,至于里面是什么数据类型,没关系
需求,把两个列表变成一个字典
在这里插入图片描述
匿名函数:可以用来定义结构非常简单的函数。 认识一下即可
lambad 参数:返回值

前面我们写的一个函数
def add_number(a,b):
return a + b

如果要用匿名函数去写要怎么写呢
add2 = lambda a,b : a + b
res = add2(11,22)
print(res)
和上面的函数是一样的
只能定义结构非常简单的函数。

11 小练习

1 .使用异常处理改写成绩评价代码,使程序可以输入非法字符

while True:
    score = input('请输入你的成绩,退出请输入q>>>:')
    if score == 'q':
        break
    try:
        score = float(score)
        if score < 40:
            print('等级:E')
        elif 40 <= score < 60:
            print('等级:D')
        elif 60 <= score < 75:
            print('等级:C')
        elif 75 <= score < 85:
            print('等级:B')
        else:
            print('等级:A')
    except ValueError:
        print('请输入合法的成绩')

2 .实现 is_odd()函数,接收一个整数参数,如果为奇数,返回‘True’,否则返回False。
思路:凡是能够被2整除的数就是偶数,模上2余数为0就是偶数

def is_odd(num):

    '''
    判断一个整数是否是奇数
    :param n:
    :return:
    '''
    # 1.为0的情况
    if num == 0:
        return False
    # 其他情况
    if num % 2 == 0:
        return False  # 只要执行了 return, 下面的语句就不会执行了,因为return有退出函数的作用。
    return True

res = is_odd(2)  # res:False
print(res)

3 实现 is_num() 函数,参数为一个字符串,如果这个字符串属于整数或浮点数,则返回’True,否则返回False
判断一个字符串是不是一个数
‘1.1’ float('1.1)
‘123’ float(‘123’)
‘123.123.123’ float(‘123.123.123’) no
总结:所有的数值字符串,都可以被float转换

    def is_num(s):
    '''
    判断一个字符串是否是一个数的表示
    :param s:
    :return:
    '''
    try:
        float(s)
        return True
    except Exception as e:
        print(e)   # 这两行代码的意思是捕获所有的异常,然后取个别名,输出一下。
        return False


res_1 = is_num('a')
print(res_1)

res_2 = is_num('1.5')
print(res_2)

could not convert string to float: 'a'
False
True

4 实现’multi()函数,最少接收两个参数,返回所有参数的乘积。
计算给定数列的乘积
最少两个参数
多少个数是不确定的,参数是不确定的,位置不定参

def multi(x, y, *args):   # args 接收多余的位置不定参数,并形成一个元祖。
    '''
    计算n个数的积
    :param x:
    :param y:
    :param args:
    :return:
    '''
    res = x * y
    for i in args:
        res *= i
    return res


res = multi(1, 2, 3)
print(res)  #  6

注意:函数里面的变量是局部变量,函数外面的变量是全局变量,它们相互不会有干扰。

5 . 实现 “is_prime’函数,参数为整数,要有异常处理,如果整数是质数,返回True,否则返回False
判断一个数是质数
什么是质数? 除了1和它本身能够被它整除外,其他的中间的数都不能被它整数,那么它就是一个质数。
如果一个数m 它只能整除1和m,2到m-1都不能被它整除,那么这个m就是一个质数。

def is_prime(num):
    '''
    判断一个数是不是质数
    :param num:
    :return:
    '''
    # 1.  0.1  排除在外
    if num == 0 or num == 1:
        return False
    # 2.  2
    if num == 2:
        return True
    # > 2
    #  num = 13
    #  num = 15
    try:
        for i in range(2, num):  
            if num % i == 0:  #  条件只要有一个满足就不用循环了
                return False
        return True
    except:
        print('传入的参数不是整数')

在这里插入图片描述

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值