Python函数学习——初步认识
函数使用背景
假设老板让你写一个监控程序,24小时全年无休的监控你们公司网站服务器的系统状况,
当cpu\memory\disk等指标的使用量超过阀值时即发邮件报警,
你掏空了所有的知识量,写出了以下代码

从图中可以看出上述代码存在了两个问题
1.代码冗余
2.维护性差
我们如何解决这个问题?请看下图

从上图可以看出:使用函数可以带来以下好处
- 减少重复代码
- 使程序变的可扩展
- 使程序变得易维护
函数定义
函数一词来源于数学,但编程中的「函数」概念,与数学中的函数是有很大不同的,具体区别,我们后面会讲,编程中的函数在英文中也有很多不同的叫法。在BASIC中叫做subroutine(子过程或子程序),在Pascal中叫做procedure(过程)和function,在C中只有function,在Java里面叫做method。
定义: 函数是指将一组语句的集合通过一个名字(函数名)封装起来,要想执行这个函数,只需调用其函数名即可
代码表现形式:
def 函数名(参数1,参数2):
''' 函数注释'''
print('函数体')
return 返回值
定义: def关键字开头,空格之后接函数名和圆括号,最后还要加一个冒号。
def是固定的,不能变。
函数名:函数名是包含字母,数字,下划线的任意组合,但是不能以数字开头。虽然函数名可以随便取名,但是一般尽量定义成可以表示函数功能的。
#下面这段代码
a,b = 5,8
c = a**b
print(c) #改成用函数写
def calc(x,y):
res = x**y
return res #返回函数执行结果 c = calc(a,b) #结果赋值给c变量
print(c)
函数参数
使用参数可以让你的函数更灵活,根据调用时传参的不同来决定函数内部的执行流程
1.实参和形参
形参: 是函数定义时候定义的参数
只有在被调用时才分配内存单元,在调用结束时,即刻释放所分配的内存单元。因此,形参只在函数内部有效。 实参: 调用的时候传进来的参数
可以是常量、变量、表达式、函数等,无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,
以便把这些值传送给形参。因此应预先用赋值,输入等办法使参数获得确定值

2.参数传递
可以传递多个参数,多个参数之间用逗号隔开。
调用函数时传参数有两种方式:
1.按照位置传参数
2.按照关键字传参数
正常情况下,给函数传参数要按顺序,不想按顺序就可以用关键参数,只需指定参数名即可(指定了参数名的参数就叫关键参数),
但记住一个要求就是,关键参数必须放在位置参数(以位置顺序确定对应关系的参数)之后
用法:1.位置参数必须在关键字参数的前面
2.对于一个参数只能赋值一次
def stu_register(name, age, course,country):
print("----注册学生信息------")
print("姓名:", name)
print("age:", age)
print("国籍:", country)
print("课程:", course) stu_register("alex", 23, "python", "china") # 按照位置传递参数 stu_register("alex", 23, course = "python", country = "china") # 按照位置和关键字传递参数 # 以下两种使用方法不正确
stu_register("alex", "python", 23, "china") # 位置不对 stu_register("王山炮", 22, age=25,country='JP') # age参数被定义两遍
3.默认参数
用法:为什么要用默认参数?将变化比较小的参数设置成默认参数(比如中国网站上注册用户功能,像国籍这种信息,就可以设置个默认值参数country=CN)
定义:默认参数可以不传,不传的时候用的就是默认值,如果传,会覆盖默认值。
def stu_register(name, age, course, country = "CN"):
print("----注册学生信息------")
print("姓名:", name)
print("age:", age)
print("国籍:", country)
print("课程:", course) stu_register("alex", 23, "python") # 使用默认参数 stu_register("Bill", 23, "python", "Japan") # 覆盖默认参数
默认参数使用注意点——可变数据类型 (字符串,数字等)

默认参数使用注意点——不可变数据类型(列表,字典等)

4.动态参数
按位置传值多余的参数都由args统一接收,保存成一个元组的形式
按关键字传值接受多个关键字参数,由kwargs接收,保存成一个字典的形式
元祖
def stu_register(name, age, *args): # *args 会把多传入的参数变成一个元组形式
print(name,age,args) stu_register("Alex",22)
# 输出
# Alex 22 () #后面这个()就是args,只是因为没传值,所以为空 stu_register("Jack",32,"CN","Python")
# 输出
# Jack 32 ('CN', 'Python')
字典
def stu_register(name, age, *args, **kwargs): # *kwargs 会把多传入的参数变成一个dict形式
print(name,age,args,kwargs) stu_register("Alex",22)
#输出
#Alex 22 () {}#后面这个{}就是kwargs,只是因为没传值,所以为空 #传参数的时候:必须先按照位置传参数,再按照关键字传参数
stu_register("Jack",32,"CN","Python",sex="Male",province="ShanDong")
#输出
# Jack 32 ('CN', 'Python') {'province': 'ShanDong', 'sex': 'Male'} def fun(a,b,**kwargs):
print(a,b,kwargs) # 按照关键字传参数
fun(a = 10,b = 20,cccc= 30,dddd = 50)
# 输出
# 10 20 {'cccc': 30, 'dddd': 50} def f(a,b,*args,defult=6,**kwargs):
#位置参数,*args, 默认参数,**kwargs
# print(a,b,args,defult,kwargs)
return a,b,args,defult,kwargs # 传参数的时候:必须先按照位置传参数,再按照关键字传参数
print(f(1,2,7,8,ccc=10,der=5))
# 输出
# 1,2,(7,8),6,{'ccc':10,'der':5}
动态参数拆包与装包
1.*args
def run(a,*args):
#第一个参数传给了a
print(a) #
# args是一个元组,里面是2和3两个参数
print(args) # (2,3)
# *args是将这个元组中的元素依次取出来
print("对args拆包")
print(*args) # 2 3 *args 相当于 a,b = args
print("将未拆包的数据传给run1")
run1(args) # ((2, 3),) 和 (2, 3)
print("将拆包后的数据传给run1")
run1(*args) # (2, 3)和2 3 def run1(*args):
print("输出元组")
print(args)
print("对元组进行拆包")
print(*args) run(1,2,3) #后面的2和3
输出结果
1
(2, 3)
对args拆包
2 3
将未拆包的数据传给run1
输出元组
((2, 3),)
对元组进行拆包
(2, 3)
将拆包后的数据传给run1
输出元组
(2, 3)
对元组进行拆包
2 3 """
理解这段代码需要把握住下面几点:
1. 形参中的*args其实真正接收数据的args,它是一个元组,把传进来的数据放在了args这个元组中。
2. 函数体里的args依然是那个元组,但是*args的含义就是把元组中的数据进行拆包,也就是把元组中的数据拆成单个数据。
3. 对于args这个元组,如果不对其进行解包,就将其作为实参传给其它以*args作为形参的函数时,args这个元组会看看作一个整体,作为一个类型为元组的数据传入。 """
2. **kwargs
def run(**kwargs):
"""
传来的 key = value 类型的实参会映射成kwargs里面的键和值
kwargs是一个字典,将关键字参数以键值对的形式
"""
print(kwargs) # {'a':1,'b':2}
print("对kwargs拆包")
# 此处可以把**kwargs理解成对字典进行了拆包,{"a":1,"b":2}的kwargs字典又
# 被拆成了a=1,b=2传递给run1,但是**kwargs是不能像之前*args那样被打印出来看的
run1(**kwargs) # 1 2
# print(**kwargs) def run1(a, b): # 此处的参数名一定要和字典的键的名称一致
print(a, b) run(a=1, b=2)
d = {'a':1,'b':2}
run(**d) # 输出结果与执行run(a=1, b=2)一样
输出结果
{'a': 1, 'b': 2} #run(a=1,b=2)
对kwargs拆包
1 2
{'a': 1, 'b': 2} #run(**d)
对kwargs拆包
1 2
"""
def run(**kwargs):#传来的 key = value 类型的实参会映射成kwargs里面的键和值
# kwargs是一个字典,将未命名参数以键值对的形式
print(kwargs)
print("对kwargs拆包")
# 此处可以把**kwargs理解成对字典进行了拆包,{"a":1,"b":2}的kwargs字典又
# 被拆成了a=1,b=2传递给run1,但是**kwargs是不能像之前*args那样被打印出来看的
run1(**kwargs)
#print(**kwargs)
def run1(a,b): #此处的参数名一定要和字典的键的名称一致
对于kwargs这个字典,如果不对其进行解包,就将其作为实参传给其它以**kwarg作为形参的函数时,kwarg这个字典会看看作一个整体,作为一个类型为字典的数据传入
"""
总结:
函数返回值
函数外部的代码要想获取函数的执行结果,就可以在函数里用return语句把结果返回
1. 首先返回值可以是任意的数据类型。
2..函数可以有返回值:如果有返回值,必须要用变量接收才有效果
也可以没有返回值:
1.当不写return的时候,函数的返回值为None
2.当只写一个return的时候,函数的返回值为None
3. 函数在执行过程中只要遇到return语句,就会停止执行并返回结果,so 也可以理解为 return 语句代表着函数的结束
def stu_register(name,age,course):
print(name, age, course) # Peiqi 29 安保
return [name, age] # 返回列表形式
status = stu_register('Peiqi',29,'安保')
print(status) # ['Peiqi', 29]
def stu_register(name,age,course):
print(name, age, course) # Peiqi 29 安保
status = stu_register('Peiqi',29,'安保')
print(status) # 无返回值时,返回None
def stu_register(name,age,course):
print(name, age, course) # Peiqi 29 安保
return
print(name, age) # 此句不会执行
status = stu_register('Peiqi',29,'安保')
print(status) # return后面没有值,返回None
Python函数学习——初步认识的更多相关文章
- [python 函数学习篇]默认参数
python函数: 默认参数: retries= 这种形式 def ask_ok(prompt, retries=, complaint='Yes or no, please!'): while Tr ...
- python函数学习的总结
python函数 part1 函数的作用: 函数以功能(完成一件事)为导向 随调随用减少代码重复性 增强代码可读性 函数的结构: def 函数名(): 函数体 函数的返回值 return:在函数中遇到 ...
- python函数学习1
函数1 (1)定义: def 函数名(参数列表) 函数体 (2)参数传递: 在python中,一切都是对象,类型也属于对象,变量是没有类型的. a = [1,2,3] a = "hellow ...
- python函数学习之装饰器
装饰器 装饰器的本质是一个python函数,它的作用是在不对原函数做任何修改的同时,给函数添加一定的功能.装饰器的返回值也是一个函数对象. 分类: 1.不带参数的装饰器函数: def wrapper( ...
- Python函数学习遇到的问题
Python函数的关键字参数 Python函数独立星号(*)分隔的命名关键字参数 Python函数中的位置参数 Python中对输入的可迭代对象元素排序的sorted函数 Python中函数的参数带星 ...
- python函数学习(一)
1.parse_known_args()和parse_args()函数 该函数为命令行解析函数,调用时需要import argparse(命令行选项.参数和子命令的解析器). 以下内容摘自python ...
- Python函数学习——递归
递归函数 在函数内部,可以调用其他函数.如果一个函数在内部调用自身本身,这个函数就是递归函数. 函数实现过程 def calc(n): v = int(n//2) print(v) if v > ...
- Python函数学习——作用域与嵌套函数
全局与局部变量 在函数中定义的变量称为局部变量,在程序的一开始定义的变量称为全局变量. 全局变量作用域是整个程序,局部变量作用域是定义该变量的函数. 当全局变量与局部变量同名时,在定义局部变量的函数内 ...
- Python --函数学习3 (将函数存储在模块中)
将函数存储在模块 函数可以将代码块和主程序分离,通过给函数指定描述性名称,可以让主程序更加容易理解,还可以更进一步,将函数存储在模块的独立文件中,再将模块导入到主程序.import 语句允许再当前运行 ...
随机推荐
- javascript中的getter和setter
在ECMAScript 5中,属性值可以用一个或两个方法代替,这两个方法就是getter和setter var man = { name : 'lidg', weibo : '@lidg', get ...
- python 网络编程 tcp和udp 协议
1. 网络通信协议 osi七层,tcp\ip五层 tcp\ip五层 arp协议:通过IP地址找到mac地址 2.tcp和udp的区别 tcp协议:面向连接,消息可靠,相对udp来讲,传输速度慢,消息是 ...
- POJ-2253.Frogger.(求每条路径中最大值的最小值,最短路变形)
做到了这个题,感觉网上的博客是真的水,只有kuangbin大神一句话就点醒了我,所以我写这篇博客是为了让最短路的入门者尽快脱坑...... 本题思路:本题是最短路的变形,要求出最短路中的最大跳跃距离, ...
- c#命名规范(转载)
出处:脚本之家 链接:http://www.jb51.net/article/57163.htm 注重代码书写的程序员应该是一个比较有修养的人,下面这些命名规则不一定要绝对遵从,但值得参考.在应用规则 ...
- 【转载】在MySQL登录时出现Access denied for user 'root'@'localhost' (using password: YES) 拒绝访问,并可修改MySQL密码
在MySQL登录时出现Access denied for user 'root'@'localhost' (using password: YES) 拒绝访问,并可修改MySQL密码 2018年08月 ...
- 浏览器DOM事件触发
除用户人为交互触发事件外,用js脚本触发事件的一般流程为 创建事件 var e = Event('event_name', {key: value, ...}) 分发事件到 event.target ...
- node.js中stream流中可读流和可写流的使用
node.js中的流 stream 是处理流式数据的抽象接口.node.js 提供了很多流对象,像http中的request和response,和 process.stdout 都是流的实例. 流可以 ...
- 选择困难症的福音——团队Scrum冲刺阶段-Day5(补发 那天csshow)
选择困难症的福音--团队Scrum冲刺阶段-Day 5 今日进展 编写提问部分 游戏分类的界面 将之前错误的图标改正 关于我们的俄罗斯方块,今天有了新的进展 NextBlockView(定义了下一个方 ...
- mysql的innodb和myisam的区别和应用场景
1. 区别: (1)事务处理: MyISAM是非事务安全型的,而InnoDB是事务安全型的(支持事务处理等高级处理): (2)锁机制不同: MyISAM是表级锁,而InnoDB是行级锁: (3)sel ...
- 阿里巴巴Java开发规约插件安装使用指南
编码规范插件安装使用指南 阿里技术公众号于今年的2月9日首次公布<阿里巴巴Java开发规约>,瞬间引起全民代码规范的热潮,后又发布了PDF的终极版,大家踊跃留言,期待配套的静态扫描工具开放 ...