上节作业回顾

#!/usr/bin/env python3
# -*- coding:utf-8 -*-
# author:Mr.chen
# 实现简单的shell命令sed的替换功能import sys,ospara_argv = sys.argv
Tag = True#判断参数的传递
if para_argv[1] == "-i" and len(para_argv) == 4 :if type(para_argv[2]) == str :if os.path.isfile(para_argv[3]) and os.popen("whoami").read().strip() == "root" :#对过滤条件的字符串进行分割,请注意此处写法,可以降低判断嵌套深度List = []if "#" in para_argv[2] and para_argv[2].count("#") == 3 :List = para_argv[2].split("#")elif "@" in para_argv[2] and para_argv[2].count("@") == 3:List = para_argv[2].split("@")elif "/" in para_argv[2] and para_argv[2].count("/") == 3:List = para_argv[2].split("/")else :print ("请用@或/或#分隔过滤条件,分隔符只能是3个")#对分割以后的列表进行判断if len(List) != 0 and List[0].strip() == "s" :if List[3].strip() != "" and List[3] != "g" :print ("{}是个无法识别的字符".format(List[3]))else :with open(para_argv[3],"r") as f , open(para_argv[3]+".bak","w") as f_new :for line in f :if List[1] in line and List[3].strip() == "" :line = line.replace(List[1],List[2],1)else :line = line.replace(List[1],List[2],-1)f_new.write(line)os.system("/bin/mv "+para_argv[3]+".bak "+para_argv[3])print ("命令执行成功!")elif len(List) != 0 and List[0].strip().count("s") == 1 and List[0].strip().endswith("s") :if List[0].strip().count(",") == 1 :if List[0].strip().split(",")[0].isdigit() and List[0].strip().split(",")[1][:-1].isdigit() :num_one = int(List[0].strip().split(",")[0])num_two = int(List[0].strip().split(",")[1][:-1])with open(para_argv[3],"r") as f , open(para_argv[3]+".bak","w") as f_new :for index,line in enumerate(f) :if num_one <= index+1 <= num_two :if List[1] in line and List[3].strip() == "" :line = line.replace(List[1],List[2],1)elif List[1] in line and List[3].strip() == "g" :line = line.replace(List[1],List[2],-1)f_new.write(line)os.system("/bin/mv "+para_argv[3]+".bak "+para_argv[3])print ("命令执行成功!")else :print ("无法识别的字符{}".format(List[0].strip()))else :if List[0].strip()[:-1].isdigit() :num = int(List[0].strip()[:-1])with open(para_argv[3],"r") as f , open(para_argv[3]+".bak","w") as f_new :for index,line in enumerate(f) :if index+1 == num :if List[1] in line and List[3].strip() == "" :line = line.replace(List[1],List[2],1)elif List[1] in line and List[3].strip() == "g" :line = line.replace(List[1],List[2],-1)f_new.write(line)os.system("/bin/mv "+para_argv[3]+".bak "+para_argv[3])print ("命令执行成功!")else :print ("{}不是一组数字,无法识别".format(List[0].strip()[:-1]))elif os.path.isfile(para_argv[3]) and os.access(para_argv[3],os.R_OK) and os.access(para_argv[3],os.W_OK):print ("为了节约时间,只对用户是root的情况做出判断。")else :print ("error!{}不是一个有效的文件或者文件的读写权限有问题。".format(para_argv[3]))else :print ("error! 格式为:{} -i '{过滤条件}' filename".format(para_argv[0]))
elif type(para_argv[1]) == str and len(para_argv) == 3 :print ("为了节约时间,只实现了有参数-i的对文件的替换操作")
else :print ("您输入的参数有误!") print ("格式:{} [-i] '过滤条件' filename".format(para_argv[0]))

架构导引

一个故事引发的深思:

假如有一天老板让你写一个监控程序,监控服务器的系统状况,当cpu/memory/disk等指标的使用量超过阈值即发邮件报警,你掏空了所有的知识量,写入了以下代码。

while True :if cpu利用率 > 90% :连接邮件服务器发送邮件关闭连接if 硬盘使用空间 > 90% :连接邮件服务器发送邮件关闭连接if 内存占用 > 80% :连接邮件服务器发送邮件关闭连接

 

上面的代码实现了功能,但即使是邻家女孩也看出了端倪,少女亲切的摸了下你家儿子的脸蛋,说,你这个重复代码太多了,每次报警都要重写一段发邮件的代码,太low了,这样干存在2个问题:

  • [x] : 代码重复过多,一个劲的copy and paste 不符合高端程序员的气质
  • [x] : 如果日后需要修改发邮件的这段代码,比如加入群发功能,那你就需要在所有用到这段代码的地方都修改一遍

你觉得少女说的对,你也不想写重复代码,但又不知道怎么做,少女好像看出了你的心思,此时她抱起你儿子,笑着说,其实很简单,只需要把重复的代码提取出来,放在一个公共的地方,起个名字,以后谁想用这段代码,就通过这个调用就行了,如下:

def 发送邮件(内存)连接邮箱服务器发送邮件关闭连接while True :if cpu利用率 > 90% :发送邮件(“CPU报警”)if 硬盘使用空间 > 90% :发送邮件(“硬盘报警”)if 内存占用 > 80% :发送邮件(“内存报警”)

 

你看着少女写的代码,气势恢宏,磅礴大气,代码里透露着一股内敛的傲气,心想,这个人真是不一般,突然对她的背景更感兴趣了,问她,这些花式玩法你都是怎么知道的?她亲了一口你儿子,捋了捋不存在的胡子,淡淡的讲,“老娘,年少时,师从京西航天桥Mr.chen ”.

一,函数

1.1 介绍

在过去的十年间,大家广为熟知的编程方法无非两种:面向对象和面向过程,其实,无论哪种,都是一种编程的规范或者是如何编程的方法论。而如今,一种更为古老的编程方式:函数式编程,以其不保存状态,不修改变量等特性重新进入人们的视野。

  • [x] : 面向对象
  • [x] : 面向过程
  • [x] : 函数式编程

这三种其实都是在叫你们如何来编程,也就是说他们仅仅只是编程的方法论。如果我们将这三种比作武林门派:

面向对象====>华山派==(秘籍)==>类==(关键字)==>class
面向过程====>少林派==(秘籍)==>过程===(关键字)==>def
函数式编程====>逍遥派==(秘籍)==>函数==(关键字)==>def

下面我们就来依次了解这些传统的编程理念,让我们从基本的函数概念开始。

1.2 定义

初中数学函数定义:一般的,在一个变化过程中,如果有两个变量x和y,并且对于x的每一个确定的值,y都有唯一确定的值与其对应,那么我们就把x称为自变量,把y称为因变量,y是x的函数。自变量x的取值范围叫做这个函数的定义域。

编程语言中函数定义:

函数是逻辑结构化和过程化的一种编程方法。

#Python中函数定义方法:def test(x) :“The function definitions”x += 1return xdef :定义函数的关键字
test:函数名
():内可定义形参
“” :文档描述(非必要,但是强烈建议为你的函数添加描述信息)
x+=1:泛指代码块或程序处理逻辑
return:定义返回值

 

1.3 为何使用函数

没有函数的编程只是在写逻辑(功能),想脱离函数,重用你的逻辑,唯一的方法就是拷贝。

例:

#假设我们编写好了一个逻辑(功能),用来以追加的方式写日志:
with open("a.txt","ab") as f :f.write("end action")#现在有三个函数,每个函数在处理完自己的逻辑后,都需要使用上面这个逻辑,那么唯一的方法就是,拷贝三次这段逻辑def test1() :print ("test1 starting action...")with open("a.txt","ab") as f:f.write("end action")def test2() :print ("test2 starting action...")with open("a.txt","ab") as f :f.write("end action")def test3():print ("test3 starting action....")with open("a.txt","ab") as f:f.write("end action")

 

那么我们假设有大于N个函数都需要使用这段逻辑,你可以拷贝N次吗?

优化:

def logger() :with open("a.txt","a+") as f :f.write("end action\n")def test1() :print ("in the test1")logger()def test2() :print ("in the test2")logger()def test3() :print ("in the test3")logger()

1.4 函数和过程

过程定义:

过程就是简单特殊没有返回值的函数

这么看来我们在讨论为何使用函数的时候引入的函数,都没有返回值,没有返回值就是过程,没错,但是在Python中有比较神奇的事情

#代码演示:def test01() :msg = "hello The little green frog"print (msg)def test02() :msg = "hello WuDaLang"print (msg)return msgt1 = test01()
t2 = test02()print ("from test01 return is {} ".format(t1))
print ("from test02 return is {} ".format(t2))#输出结果

hello The little green frog
hello WuDaLang
from test01 return is None
from test02 return is hello WuDaLang

总结:
当一个函数/过程没有使用return显示的定义返回值时,Python解释器会隐式的返回None,所以在Python中即便是过程也可以算作函数。

1.5 函数返回值

在Python里调用函数是可以有返回值的。

#代码演示:def test01() :passdef test02() :return 0def test03() :return 0,10,"hello",["Mr.chen","yunjisuan"],{"WuDaLang":"lb"}t1 = test01()
t2 = test02()
t3 = test03()print ("from test01 return is {} {}".format(type(t1),t1))
print ("from test01 return is {} {}".format(type(t2),t2))
print ("from test01 return is {} {}".format(type(t3),t3))#输出结果from test01 return is <class 'NoneType'> None
from test01 return is <class 'int'> 0
from test01 return is <class 'tuple'> (0, 10, 'hello', ['Mr.chen', 'yunjisuan'], {'WuDaLang': 'lb'})

  • 我们发现当我们调用这个函数,如果函数里有return这个东西,后边跟着的东西就作为函数的结果返回到调用的地方,同时这个返回值可以赋值给变量。
  • 那么函数执行了return后,函数里其他的代码还能执行吗?同学们继续往下看
#代码演示:def test1() :print ("in the test1")return 0print ("我还能出现吗?")    #这句能正常输出吗?

x = test1()#输出结果

[root@localhost scripts]# python3 test.py
in the test1

  • 我们发现在函数体里的代码,一旦遇到return就返回到调用函数的地方了。而函数体里return之后的代码将不再执行。
  • 那么return里能返回什么东西呢?关键字可以吗?函数的名字可以吗?我们继续往下看。
#代码演示:def test1() :print ("in the test1")return 0def test2() :print ("in the test2")return test1    #能返回函数名吗?当然可以#def test3() :
#    print ("in the test3")
#    return def      #关键字能返回吗?当然不可以

x = test2()
print (x)    #输出结果

[root@localhost scripts]# python3 test.py
in the test2
<function test1 at 0x7f15525bb378>  #我们发现返回的是一个内存地址

  • 内存地址:是一个指向内存的对象,Python根据这个地址从内存中提取数据,或者运行代码。
  • 那么,同学们,函数名和函数名()有什么区别呢?我们继续实验。
#代码演示:def test1() :print ("in the test1")return 58                                                                  def test2() :print ("in the test2")return test1()  #返回的是什么呢?还是地址吗?
x = test2()
print (x)#输出结果

[root@localhost scripts]# python3 test.py
in the test2
in the test1
58      #返回的58

综上,我们发现,当我们return一个函数的名字时,返回的是一个指向内存的地址(并没有去内存中运行程序),当我们return一个函数名字+()时,返回的是那个函数体执行的结果。因此,()我们可以理解成执行前边的函数名对象。

1.6 函数为什么要有返回值?

因为在代码编写的过程中,我们经常需要知道一个函数体里的代码的执行情况。我们可以通过判断函数体的返回值来决定接下来的代码的走向。

#代码演示:def test1() :return 0def test2() :return 1if test1() :print ("我是test1")
elif test2() :print ("我是test2")#输出演示

[root@localhost scripts]# python3 test.py
我是test2

二,函数参数及调用

2.1 函数的调用

调用方法:

(1)形参和实参

  • 形参:形式参数,不是实际存在,是虚拟变量。在定义函数和函数体的时候使用形参,目的是在函数调用时接收实参(实参个数,类型应与实参一一对应)
  • 实参:实际参数,调用函数时传给函数的参数,可以是常量,变量,表达式,函数,传给形参。

区别:

形参是虚拟的,不占用内存空间,形参变量只有在被调用时才分配内存单元,实参是一个变量,占用内存空间,数据传送单向,实参传给形参,不能形参传给实参。

#代码演示:def test(x) :      #x就是形参               print (x)test(2)             #2就是实参,向函数test传递实参#输出结果2

(2)位置参数和关键字

同学们思考,形参可以比实参个数多吗?

标准传参调用方式

#代码演示:def test(x,y) :                                                   print (x)test(2)#输出结果

[root@localhost scripts]# python3 test.py
Traceback (most recent call last):File "test.py", line 7, in <module>test(2)
TypeError: test() missing 1 required positional argument: 'y'    #显示找不到y的值

所以,我们得出结果,形参个数不能比实参多。那么反过来呢?实参个数能不能比形参多?

#代码演示:def test(x) :                                                     print (x)test(2,4)#输出结果

[root@localhost scripts]# python3 test.py
Traceback (most recent call last):File "test.py", line 7, in <module>test(2,4)
TypeError: test() takes 1 positional argument but 2 were given    #显然也是错的

因此,形参个数和实参个数必须一一对应。形参有多少个,在传递参数的时候实参就必须有多少个。

关键字调用方式:

如果不指定实参具体传给哪个形参,那么默认是要按照顺序一一对应的。如果指定就会按照指定的方式赋值。

#代码演示:def test(x,y) :     print (x)print (y)def test2(x,y) :print (x)print (y)test(2,4)   #没指定,一一对应传参赋值方式
test2(y=2,x=4)      #指定的传参赋值方式#输出结果

[root@localhost scripts]# python3 test.py
2   #这是test函数的x
4   #这是test函数的y
4   #这是test2函数的x
2   #这是test2函数的y

思考:同学们分析下如下代码中的各种x,y都是什么意思?下面这段代码能正常执行吗?

#代码演示def test(x,y) : print (x)print (y)x = 1
y = 1test(x=x,y=y)  

继续思考,同学们下面这段代码能正常执行吗?

#代码演示:def test(x,y) : print (x)print (y)test(x=2,3) #传递了一个未指定的实参和一个指定了的形参

 

还得思考,同学们下面这段代码能正常执行吗?

#代码演示:def test(x,y) : print (x)print (y)test(y=2,3) #传递了一个未指定的实参和一个指定了的形参

 

不能不思考:,同学们下面这段代码呢?能正常执行吗?

#代码演示:def test(x,y) : print (x)print (y)test(3,x=2)

 

最后的思考:,同学们下面这段代码能正常执行吗?

#代码演示:def test(x,y) : print (x)print (y)test(3,y=2)

 

同学们,是否已经懵逼了呢?请同学们仔细理解上面的几个例子然后验证如下的话:

  • [x] :位置参数必须写在关键字参数的前边
  • [x] :被位置参数赋值的形参,是不允许被关键字参数继续赋值的。

理解了上面几句话,请同学们继续分析如下例子。

#例1def test(x,y,z):print (x)print (y)print (z)
test(3,6,x=3) #例2def test(x,y,z):print (x)print (y)print (z)
test(3,6,z=3) #例3def test(x,y,z):print (x)print (y)print (z)
test(3,y=3,6)#例4def test(x,y,z):print (x)print (y)print (z)
test(3,y=3,z=5)#例5def test(x,y,z):print (x)print (y)print (z)
test(3,y=3,z=5)#例6def test(x,y,z):print (x)print (y)print (z)
test(3,z=3,y=5)#例7def test(x,y,z):print (x)print (y)print (z)
test(x=5,7,z=9)

 

能正确说出上述七个例子的答案,就说明你真的懂了。

三,架构引导与作业

架构引导:

  • 通过对函数的学习,我们不难发现,所谓面向过程,其实就是利用我们对函数的定义来优化经常需要重复编写的代码,以达到简化代码的目的。
  • 而通过调用的方式,我们可以将函数体内的代码在程序的每个关键点重复的去执行。
  • 然而,拥有了参数传递的函数体,更可以实现我们许多复杂的逻辑计算功能。
  • 因此,从函数这节开始,我们对整个代码编写的着眼点,就要放在如何利用函数思想,去设计优化我们的代码架构,使之更精简,更可读。
  • 但是,同学们我们在学习函数体时,从未在函数体内赋值过新的变量。我们只是在介绍何为函数何为参数以及如果去使用和调用。
  • 那么,函数体内可以创建新的变量吗?假如函数体内的变量和函数体外的变量名称冲突,那又会发生什么呢?这就需要我们学习下一节的知识:函数的作用域

作业:

利用函数思想优化并实现"用户管理接口"
完成时间:间隔一次课

  1. 有功能选择主菜单
  2. 可以注册用户账号
  3. 可以登陆用户账号
  4. 可以删除用户账号
  5. 可以修改用户密码
  6. 只能在功能选择菜单中退出程序
  7. 每个分支功能均可返回到主菜单
  8. 用户数据保存在文件中
金牌IT职业再教育培训机构,欢迎来校资源。QQ:215379068
转自

Python运维开发基础09-函数基础 - 陈思齐 - 博客园
https://www.cnblogs.com/chensiqiqi/p/9163057.html

转载于:https://www.cnblogs.com/paul8339/p/9647862.html

Python运维开发基础09-函数基础【转】相关推荐

  1. Python运维开发基础01-语法基础【转】

    开篇导语 整个Python运维开发教学采用的是最新的3.5.2版,当遇到2.x和3.x版本的不同点时,会采取演示的方式,让同学们了解. 教学预计分为四大部分,Python开发基础,Python开发进阶 ...

  2. Python运维开发基础10-函数基础【转】

    一,函数的非固定参数 1.1 默认参数 在定义形参的时候,提前给形参赋一个固定的值. #代码演示: def test(x,y=2): #形参里有一个默认参数 print (x) print (y) t ...

  3. 阅后即焚,Python 运维开发99速成

    2019独角兽企业重金招聘Python工程师标准>>> -欢迎大家订阅微信公众号:Python从程序猿到程序员 导读 本文篇幅较长,请收藏并耐心阅读 首先请读者原谅这个文章标题有些唬 ...

  4. day01.介绍python运维开发

    第1节:介绍python运维开发 课程的开场白: 学完次课程可以开发出高效的自动化软件.运维监控.聊天软件.网站等内容. 这个运维开发跟实际上的开发是有区别的,区别在我们是实现功能,但是不能向开发那样 ...

  5. Python运维开发工程师养成记(循环语句)

    图示 循环语句类型 while循环 for循环 嵌套循环 循环控制语句 break语句:在语句块执行过程中终止循环,并且跳出整个循环 continue语句:在语句块执行过程中终止当前循环,跳出该次循环 ...

  6. python运维开发做什么_想做运维开发工程师,Python Django学的很迷茫,怎么办?...

    不只一个想要转型成为运维开发工程师的小伙伴问过我,Python语法学起来那么简单,为什么一个Django框架就那么难? 学Python的小伙伴往往会有这样的困惑: 我看了100多个小时的教学视频,为什 ...

  7. python运维开发培训_运维架构师-Python 自动化运维开发-014

    运维架构师-Python 自动化运维开发-014 九.标准数据类型 1.为什么编程语言中要有类型 类型有以下几个重要角色:对机器而言,类型描述了内存中的电荷是怎么解释的. 对编译器或者解释器而言,类型 ...

  8. python运维开发招聘_GitHub - PlutoaCharon/LiunxNotes: 校招-运维开发(Liunx,Python,Golang)面试学习笔记...

    校招-运维开发(Liunx,Python,Golang)面试学习笔记 1. 网络基础类 2. Linux系统管理类 3. Linux服务管理类 4. 数据库管理 ​ 索引(包括分类及优化方式,失效条件 ...

  9. python运维开发工程师_运维开发工程师的工作职责精选

    运维开发工程师需要负责优化.改进运维支撑系统,并保证其安全高效稳定的运行.下面是学习啦小编为您精心整理的运维开发工程师的工作职责精选. 运维开发工程师的工作职责精选1 职责: 1. 负责主导运维平台的 ...

最新文章

  1. oracle cpu分配,CPU 分配 - Oracle VM Server for SPARC 2.0 管理指南
  2. LNMP安装常见问题集锦(一)
  3. traceroute命令---Linux学习笔记
  4. asp文件上传和下载
  5. apache camel_Apache Camel中的短重试与长重试
  6. js练习--贪吃蛇(转)
  7. 解决EF 4.0 中数据缓存机制
  8. php与eCharts结合,23.安装php和echarts进行结合展示图表
  9. android调用日历库,Android学习教程之日历库使用(15)
  10. 全球首发!惯性导航导论(剑桥大学)第十部分
  11. if vue 跳出_vue实现弹框遮罩点击其他区域弹框关闭及v-if与v-show的区别介绍
  12. webpack配置路径及hash版本号,利用html-webpack-plugin自动生成html模板
  13. 如何用小学生计算机来玩游戏,小学生一年级第一次玩电脑作文
  14. 投稿SCI 中文文献翻译后 中英文混排的解决办法
  15. Mac 屏幕色温一直变化
  16. D3D粒子系统设计关键要点
  17. IP地址中的A、B、C类地址详解
  18. 下一轮人工智能泡沫,或将由消费机器人引发
  19. vue脚手架和html,vue脚手架的作用是什么?
  20. Towards Open Set Deep Networks(CVPR 2016)

热门文章

  1. Python 实现判断身份证号码的有效性
  2. 更换MAC笔记本电池
  3. Visual Studio 2019 许可证过期解决办法
  4. 车辆违章查询API 封装
  5. [算法]LCS及输出LCS
  6. u大师u盘装系统win7_u盘怎么安装win7系统 u盘安装win7系统教程【详细介绍】
  7. 谷粒商城skuId远程调用查询库存功能总结
  8. 快捷键 鼠标滚轮与触控板翻转 mac
  9. 前端跨域携带cookie
  10. 圆周分孔计算公式表图_圆周等分系数表(带图示例,版式清晰)