首页 > 其他分享 >day12- 函数

day12- 函数

时间:2024-04-02 22:13:14浏览次数:14  
标签:函数 参数 day12 print my 我们 def

我们学习编程的时候,一学到函数就感觉很难,其实函数很简单,听我给你细细道来,在我们之前的学习中,我们最常用的一个操作,打印输出print(),其实这就是我们最先接触的函数,只不过这是由Python源码中编写好的函数,那我们来看下print()函数到底是怎么写的?

从中我们可以看到用到def关键字,然后接一个print还有一个括号并且里边有内容,这样我们就可以使用print打印输出这个功能了,下边我们详细介绍函数

1、什么是函数

1、为什么有函数

函数是组织好的,可重复使用的,用来实现单一、或相关联功能的代码段。这句话怎么理解,比如我们要比较2和3的大小,我们可以直接写
num1 = 2
num2 = 3
if num1 < num2:
    print("2小于3")
else:
    print("2大于3")
那如何我们下次又要比较5和6的大小呢,把代码可以在写一遍,如果下次再比较10和11的大小呢,这时候就可以用到函数

2、函数的定义

我们一般使用 def 关键词作为声明,后面紧接着是函数标识符名称与圆括号 (),最后接一个冒号 :
def 函数名(参数列表):
    # 函数体
    return [返回值]
函数体 必须有缩进,在函数体我们编写要实现的功能逻辑
  • 函数名:见名识意,通俗点,不建议使用单字母
  • 参数列表:设置该函数可以接收多少个参数,多个参数之间用逗号( , )分隔(也可不带参数,但是括号不能省略)
  • return [返回值] :返回该函数的返回值。可以有返回值也可以没有

小栗子

熟悉招式后,我们就可以练习,在我们上边还有一个问题,比较两个数的大小,可能有很多两个数,我们用函数实现
# 定义比较两个数字的函数
def compare_numbers(num1, num2):
    # 如果num1小于num2
    if num1 < num2:   
        # 打印num1小于num2
        print("{}小于{}".format(num1, num2))
    # 否则
    else:
        # 打印num1大于num2
        print("{}大于{}".format(num1, num2))
这样我们就写好了这个函数  

3、函数的调用

调用函数是什么意思,我们不是把函数都写好了吗,我们来执行上边的代码,比较两个数大小的函数 发现执行结果为空 现在懂了吧,函数相当于我们的工具,可以是扳手,也可以是螺丝刀,如果没有手使用,就会毫无效果 所以我们得调用函数,才能使用函数的功能,来看下调用:   语法格式如下所示:
函数名(参数)    # 第一种调用方式,如果有参数就填写对应参数,无参数可以不写
返回值 = 函数名(参数)    # 第二种调用方式,如果函数有返回值,得变量来接收该值
  括号里传的参数需要额外注意,定义函数的时候有几个参数,调用的时候就传几个参数,并且要保持顺序 在我们小栗子中,我们来调用一下
compare_numbers(2, 3)
compare_numbers(6, 5)
compare_numbers(10, 11)


# 执行结果
2小于3
6大于5
10小于11

 

看,这样以后我们不管在比较多少次两个数的大小,就不需要在编写重复的代码了   在我们实际编程工作中,如果不是单一功能的代码,也可以不用使用函数,这个要看情况使用

2、函数的参数

1、函数的值传递和引用传递

函数中有形参和实参,我们拿一个具体例子,传入一个数字,返回这个数字的2倍数字
def toal(num):
    return num * 2
  在我们定义的函数中,num就是我们的形参,相当于放个位置,不做实际使用 我们调用上边的函数
toal(5)
  我们调用函数,括号中实际传入5,这就是我们的实参,函数实际会拿实参来进行逻辑处理 好,我们理解了形参和实参后,就来看下我们的值传递和引用传递:  
  1. 值传递:适用于实参类型为不可变类型(字符串、数字、元组)
  2. 引用(地址)传递:适用于实参类型为可变类型(列表,字典)
  那值传递和引用传递有什么区别啊?  
值传递,形参的值发生改变,不影响实参的值 引用传递,改变形参的值,实参的值也会一同改变
我们来做个例子参考下:
# 定义了一个函数
def change(a):
    a += 100  
    print("函数内:", a)
    
a = 100
change(a)
print("函数外:", a)
  猜猜看,函数内的值是多少,函数外的值是多少   执行结果:
函数内: 200
函数外: 100
大家猜的准吗 这个就属于值传递,虽然形参里的改变了,但是实际我们定义的实际参数值虽然在函数中进行了改变,但是实际的值是不会改变的 当然这种适用于数字,字符串,元祖等不可变类型   那引用传递是什么呢?
# 函数的引用传递
def f(a):
    a[0] = 100
    print('函数内:', a)

a = [1, 2, 3, 4]
f(a)
print('函数外:', a)
  执行结果:
函数内: [100, 2, 3, 4]
函数外: [100, 2, 3, 4]
这下大家应该都猜对了吧,引用传递,传递给函数参数是实际引用地址,修改形参中的值后,引用地址就会改变,所以传递给实参的值也会进行改变

2、位置参数

位置参数,也叫必传参数,顾名思义,参数是必须要传入的,并且还要按照位置顺序传入,如果没有按照上边要求,会报错或者得到结果不一致 直接看例子
def hello(name, message):
    print(f"{name}! {message}")
传入1个参数
hello("小华")

# 执行结果
TypeError: hello() missing 1 required positional argument: 'message'
  传入3个参数
hello("小华", '你好', '哈哈')

# 执行结果
TypeError: hello() takes 2 positional arguments but 3 were given
  传入2个参数
hello("小华", '你好')
hello("你好", '小华')

# 执行结果
小华! 你好
你好! 小华
所以,在调用函数时,一定要确定好位置

3、默认参数

默认参数,函数定义时,如果给某个参数提供一个默认值,这个参数就变成了默认参数 直接看代码:
def hello(name='小华', message):
    pass
 
 def hello(message,name='小华'):
    pass
  上述两个代码有问题吗,在编辑器中发现第一个函数报错了 原因就在默认参数必须在位置参数后面!   那默认值参数有什么用呢? 默认值参数表示这个参数就算不给传参,也有一个默认值,不会报错
def test1(a, b=1):
    print(a, b)
    

test1(0)
test1(0, 2)
  执行结果
0 1
0 2
代码是没问题的

实战练习

Python编程题
# 默认参数传空列表
def my_function(a=[]):
    a.append('A')
    print(a)


my_function()
my_function()
my_function()
  不实际运行代码,答案是什么? 那不很简单吗
['A']
['A']
['A']
如果是这个答案,肯定错误   真正的答案是:
['A']
['A', 'A']
['A', 'A', 'A']
默认参数传入空列表,在我们函数的引用传递中我们知道,如果参数传入的是列表,表示传入的参数的引用地址,而后边列表改变了,默认参数表示这个默认值也对应改变了,所以调用一次函数后续再次调用这个函数的参数的默认值就会改变

4、可变参数

可变参数也叫动态参数,为什么有可变参数呢 比如我们有求2个数的求和函数
def add(a, b):
    return a + b
  之后又需要3个数的求和函数
def add(a, b,c):
    return a + b + c
那之后,我们要求100个数的和,应该怎么做呢 这时候就用到了我们的动态参数   Python的动态参数有两种,分别是*args**kwargs,这里面的关键是一个和两个星号的区别 至于叫*a或者*as是没有区别的,只不过Python官方默认让我们使用这个*args**kwargs  

*args

定义中使用星号 * 来表示。它允许函数接受任意数量的位置参数,并将它们作为一个元组传递给函数
# 函数可变参数
def my_func(*args):
    for arg in args:
        print(arg)


my_func('hello', 'world', 123)
  打印结果
hello
world
123
  如果传入的是一个列表呢
def my_func(*args):
    for arg in args:
        print(arg)


my_func([1, 2, 3, 4])
猜猜打印的结果是什么   正确答案:[1, 2, 3, 4] 为什么不是1,2,3,4分别打印出来呢,因为当传入的参数为列表,是作为一个整体传入的,那接受会用一个元祖接受就是args = ([1, 2, 3, 4],),遍历元祖整个列表表示为1个元素会打印输出   那如果我们想要1,2,3,4作为单独的元素一个个传入给参数呢,我们可以用解包操作符 * 来将列表的元素作为独立的参数传递给函数
my_func(*[1, 2, 3, 4])
  再来看看打印结果
1
2
3
4
  如果可变参数和位置参数和默认参数联合使用呢,看下边这个例子:
def myfun(a, *b, c=None):
    print(a)
    print(b)
    print(c)
myfun(1, 2, 3, 4)

 

猜猜a,b,c各自的值,执行结果:
1
(2, 3, 4)
None

 

a拿到了1,b作为可变参数,把后边的值都接受了,所以c没有拿到值 所以,我们如果想要给c赋值,我们就要指定参数值,这就用到了我们的关键字参数

5、关键字参数

我们在调用函数时,可以以 “参数名 = 参数值” 的形式传递参数,这种我们可以认为强行赋值,不需要传递,所以不受位置影响,还是上边的例子,我们要给c赋值,这时候我们就用关键字参数
def myfun(a, *b, c=None):
    print(a)
    print(b)
    print(c)
myfun(1, 2, 3, c=4)

# 执行结果
1
(2, 3)
4

 

那如果我们把给c赋值放在最前面可以吗?
myfun(c=4, 2, 3)

# 执行结果
 myfun(c=4, 2, 3)
               ^
SyntaxError: positional argument follows keyword argument

 

代码报错了,因为如果有关键字参数,调用的时候顺序必须放在最后面
myfun(2, 3,c=4)
 

6、可变关键字参数

**kwargs

定义中使用星号 ** 来表示,它允许函数接受任意数量的键值对也就是关键字参数,并将它们作为一个字典传递给函数
# 函数可变参数
def my_func(**kwargs):
    for key, value in kwargs.items():
        print(f"{key}: {value}")


my_func(name="小华", age=25, city="beijing")

 

打印结果
name: 小华
age: 25
city: beijing

 

这是第一种传递方式:key=value 的方式传参 如果我们传入整个字典,是否可以?
# 函数可变参数
def my_func(**kwargs):
    for key, value in kwargs.items():
        print(f"{key}: {value}")

my_dict = {
    "name": "小华",
    "age": 25,
    "city": "beijing"
}
my_func(my_dict)

 

执行结果:报错 这是因为,我们传入整个字典,属于位置参数传递方式,但是我们的函数没有任何位置参数,所以类型就会报错,如果我们想要以整个字典的方式传入,我们可以使用字典解包操作符 **,这样就可以将字典中的键值对分别作为关键字参数传递给函数。

7、参数的顺序

一个函数中包含多种参数的组合,必须遵守这样的顺序:位置参数(必传参数),默认参数,单星号参数,双星号参数 定义参数时,位置参数都必须在关键字参数之前
def my_func(a=1, b):
    print(a, b)
    
 # 这种写法就会报错,关键字参数必须放在位置参数后边

 

可变参数中,单星号要在双星号之前
def my_func(a, b, c=0, *args, **kwargs):
    print(a, b, c, args, kwargs)
    

my_func(1, 2, 3, 4, 5, x=9, y=10)
my_func(1, 2, x=9, y=10)
my_func(1, 2, 3, (4, 5), a=9, b=10)
my_func(1, 2, 3, x=9, y=10, z=11)
my_func(1, 2, 3, x=9, y=10, z=11, a=12)

 

不运行代码,猜猜结果   还有一个小细节,单星号后面的都是关键字参数,无论是否带=;
def my_func(a, b, c=0, *args, d , **kwargs):
    print(a, b, c, args,d, kwargs)

 

上述中的d在*args后面,因此属于关键字参数,虽然没有带=

3、函数的返回

1、返回是什么

Python函数,可以用 return 语句指定应该返回的值,该返回值可以是任意类型 语法格式:return [返回值]

2、返回有两个作用

  • 提前退出函数
  • 返回具体的数据
def add(a, b):
    return a + b
    print(a + b)


add(3, 4)

 

上述一个求和的代码,我们执行后会返回什么,试一试,发现返回的是啥也没有,为什么呢?我们的代码里不是有打印a+b吗,是的,但是执行到return的时候,就直接跳出函数了,所以return 语句会提前退出函数 那我们想看下我们返回的数据应该怎么办,有返回值的时候,我们可以将函数赋值给一个变量,变量保存函数的返回值,然后打印输出
num = add(3, 4)
print(num)

 

当然我们如果不需要返回,也可以不写return,这样就会默认返回None的
def add(a, b):
    a + b
num = add(3, 4)
print(num)

 

3、None是什么?

None 是一个特殊的常量,表示空或缺失,和 False 不同,它不表示 0,也不表示空字符串,而表示没有值,也就是空值。 None 常用于 assert、判断以及函数无返回值的情况  

4、return多个值

我们可以使用return返回多个值
def add(a, b):
    return a + b, a - b

 

上述函数返回两个数的和,和两个数的差,我们打印看一下:
print(add(5, 3))

# 执行结果
(8, 2)
  return 多个返回值,得到的是一个元组,后续我们可以根据元祖取值 这里,我们也可以分别接受一下对应的值
he, cha = add(5, 3)
print('和:', he)
print('差:', cha)

 

 

day12练习

初级: 1.定义函数名add,接受两个数字参数,求和返回值 2.定义函数名Area,参数接受r半径的值,求圆的面积,(计算公式:π*r*r) 3.定义函数名season,接受一个月份参数,返回其对应的季节(春夏秋冬) 4.定义函数名reverse,接受一个字符串参数,并返回逆序后的字符串(比如传入abcdef,返回fedcba)     中级: 1.编写一个函数 find_max(numbers),接受一个整数列表 numbers,并返回列表中的最大值 2.编写一个函数 is_prime(n),判断一个正整数 n 是否为素数(质数) 3.编写一个函数 remove_list(numbers),接受一个整数列表 numbers,并移除列表中的重复元素,返回去重后的列表   高级 1.请写一个函数 equals ,该函数参数为任意数量的数字,请在函数中统计出这些参数数字中重复的数字有多少个 比如 :
equals(3, 4, 3, 4, 1, 6, 2) 

 

输出为:
数字 3 出现了 2 次
数字 4 出现了 2 次
数字 1 出现了 1 次
数字 6 出现了 1 次
数字 2 出现了 1 次

 

   

标签:函数,参数,day12,print,my,我们,def
From: https://www.cnblogs.com/nuomituan/p/18111267

相关文章

  • 粒子群算法(主要针对连续型函数优化问题)
    文章主要参考了以下博文:https://zhuanlan.zhihu.com/p/5648197181.简介粒子群算法是一种解决最优化问题的通用方法,其优点是求解速度快,数值相对稳定,算法简单。粒子群算法分为连续型粒子群算法和离散型粒子群算法,分别用于解决连续型问题和离散型问题。粒子群优化算法源自对鸟......
  • callback回调函数的使用
    callback回调函数的使用二、例子收拾二、例子收拾/**回调方法*/asyncfunctionsubmitForm(callback:(data:Record<string,string>[],callback:()=>void)=>void){loading.value=truecallback(formData,()=>{loading.value=false......
  • 函数或方法参数传递问题
    ★一般情况函数参数的传入顺序依次为:必备参数=>默认参数=>不定长参数=>关键字参数案例#函数传入参数顺序必备默认不定长defdouble_sum(x,y=88,*args,**kwargs):print(x)print(y)print(args)print(kwargs)double_sum(10,20,......
  • 常用Hash函数速度比较
    常用Hash函数速度比较结论常见的这些Hash函数,没有数量级上的差别,当然这只是针对在长度为20000以内的字符串所得出的结论.如果是对文件进行摘要,请还是使用非可逆的Hash函数,而不是crc/murmur这类​crc​的性能非常出色,但是与murmur3​的性能没有拉开差距,由于......
  • 构造函数init到底是什么作用 是下面的方法都可以从init里面获取参数吗?(AI+Python)
    大家好,我是Python进阶者。一、前言前几天在Python白银交流群【无敌劈叉小狗】问了一个Python基础的问题,问题如下:问一下构造函数init到底是什么作用是下面的方法都可以从init里面获取参数吗?二、实现过程这里【黄志诚】分享了自己的一个经验:全局呀,相当于初始化一个参数,全局都......
  • 【C语言】函数(涉及生命周期与作用域)
    文章目录函数(function)**函数的概念****函数的作用**在本阶段一般会涉及到两类函数:库函数和自定义函数自定义函数**函数的语法形式****形参和实参****实参和形参的关系**函数返回值**函数返回值类型说明****return语句**数组做函数参数**函数嵌套调用和链式访问**函......
  • 类的函数成员(三):拷贝构造函数
    一.什么是拷贝构造函数?1.1概念        同一个类的对象在内存中有完全相同的结构,如果作为一个整体进行复制或称拷贝是完全可行的。这个拷贝过程只需要拷贝数据成员,而函数成员是共用的(只有一份拷贝)。        在建立对象时可用同一类的另一个对象来初始化该对......
  • JS- 构造函数调用与常规函数和方法调用的主要区别
    构造函数调用与常规函数和方法调用的主要区别:特征构造函数调用常规函数和方法调用调用方式使用new关键字直接调用函数名或通过对象调用方法参数处理构造函数可以接受任意数量和类型的参数,并且通过this来引用它们函数和方法可以接受任意数量和类型的参数this的值新创建......
  • 22_shell脚本条件判断、函数和循环
    shell脚本条件判断、函数和循环一、shell脚本条件判断​shell脚本支持条件判断,虽然可以通过&&和||来实现简单的条件判断,但是稍微复杂一点的场景就不适合了。shell脚本提供了ifthen条件判断语句,写法if条件判断;then//判断成立要做的事情fi还有ifthenelse语句,写法......
  • 生信小白菜之关于mutate函数的一切
    RforDataScience准备包和示例数据library(dplyr)library(nycflights13)mutate()函数基本用法#作用是添加新列,新列是由原有数据计算的来#添加的新列在数据集的最后#举例flights_sml<-select(flights,year:day,ends_with("delay"),distance,air_time)mu......