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 语句允许再当前运行 ...
随机推荐
- django + nginx + uwsgi
server{ listen ; server_name 0.0.0.0; charset utf-; access_log /var/log/nginx/access.log main; locat ...
- 微服务SpringCloud无法进行服务消费
最近用SpringCloud做微服务,一直无法成功进行服务消费. 我使用的服务消费者是Feign,声明式调用服务提供者. 排查过程 1.检查服务提供者: (1)对提供的方法进行测试,确保提供的服务没有 ...
- 业务数据实体(model) 需要克隆的方法
业务数据实体(model) 需要克隆的时候 可以使用 Json.Deserialize<InquireResult>(Json.Serialize<InquireResult> ...
- 134. Gas Station加油站
[抄题]: There are N gas stations along a circular route, where the amount of gas at station i is gas[i ...
- tomcat7闪退
问题是我昨天运行的好好的,今天加了些代码,tomcat7就会启动闪退.我把conf/server.xml中的<Context />去掉,tomcat又能正常启动! 那么问题出在哪里呢? 我 ...
- 6M - 循环多少次?
我们知道,在编程中,我们时常需要考虑到时间复杂度,特别是对于循环的部分.例如, 如果代码中出现 for(i=1;i<=n;i++) OP ; 那么做了n次OP运算,如果代码中出现 fori=1; ...
- javaweb开发.常用的第三方包
序号 开发包名称 描述 1 dom4j-1.6.1.jar dom4j用于操作XML文件 2 jaxen-1.1-beta-6.jar 用于解析XPath表达式 3 commons-beanuti ...
- JSP请求重定向与请求转发的区别
请求重定向 客户端行为,response.sendRedirect(),从本质上讲等同于两次请求,前一次请求对象不会保存,地址栏URL会改变: 请求转发 服务器行为,request.getReques ...
- MFC字体样式和颜色设置
在编写MFC界面程序时,可能会使用不同大小或者颜色的字体,这里稍做记录. 使用方法 CFont *m_pFont;//创建新的字体 m_pFont = new CFont; m_pFont->C ...
- android 测试
Android Monkey压力测试 monkey测试结果详细分析 Android自动化测试工具 UiAutomator使用详解 在Android Sudio中使用Uiautomator 六款Andr ...