python自动化 时间:2016.08.09
笔者QQ:572891887、552408925
linux架构交流群:471443208、524721466
1.1Python函数面向对象
面向过程
1.可读性差
2.重用性差
函数式编程
1.1.1自定义函数看一个函数的例子:db文件内容为 xuliangwei|123
deflogin(username,password): ''' 用于用户登陆 :param username: 用户输入用户名 :param password: 用户输入密码 :return: true,登陆成功 false,登陆失败 ''' file_name=open("db",'r') forlineinfile_name: line_list=line.split("|") ifline_list[0] ==usernameandline_list[1] ==password: return True return False解释:
1.def:表示函数的关键字 2.函数名:函数的名称,日后根据函数名调用函数 3.函数体:函数中进行一系列的逻辑计算,如:发送邮件 4.返回值:当函数执行完毕后,可以给调用者返回数据。 5.参数:为函数体提供数据(Python函数传递参数是传递一个引用。而不是重新赋值.) 1.普通参数(严格按照顺序,将实际参数赋值给形式参数) 2.默认参数(必须放置在参数列表的最后) 3.指定参数(将实际参数复制给指定的形式参数) 4.动态参数: *args默认将位置参数,全部放置在元组中 **kwargs默认将关键字参数(字典),全部放置在字典中 5.万能参数 1.1.2 局部变量1.在程序中定义的变量成为局部变量。
2.局部变量作用域是定义该变量的子程序。
3.当全局变量与局部变量冲突时,在定义局部变量的子程序内,局部变量起作用,在其他地方全局变量起作用。
#!/usr/bin/env python # Author:xuliangwei name= "XuLiangWei" defchange_name(name): print("before change:",name) name= "我是有Tesla的男人" #定义局部变量 print("after chage:",name) change_name(name) print("在外面看name改了么?",name)执行结果:
before change: XuLiangWei after chage: 我是有Tesla的男人 在外面看name改了么? XuLiangWei 1.1.3 全局变量1.在程序一开始定义的变量称为全局变量。
1.全局变量定义变量,必须都是大写(潜规则)。比如:NAME="xuliangwei" 2.函数优先读当前环境变量,如果没有则会读全局变量,全局变量在所有的作用域都可读。 3.修改全局变量需要先globalname,表示name是全局变量(重新赋值)。 4.特殊:列表,字典,元组嵌套列表,可修改,不可重新赋值。 1.1.4内置函数 # all #非0即真 # any # # bool #0和,空字典空列表都是假 # callable #表示是否可执行,或是否可调用 # dir #快速查看对象提供了哪些功能 # divmod #文章分页使用 # isinstance #用于判断,对象是否是某个类的实例 # globals #列出全局变量 # locals #列出所有局部变量 # hash # #enumerate #float #format #frozenset # max #最大 # min #最小 # sum #求和 # int #整数 # hex #十进制转换十六进制 # bin #十进制转二进制 # oct #十进制转十进制 # filter #内部循环,参数比较 # map #将函数返回值添加到结果中 # compile #将字符串,编译成Python代码 # eval #执行表达式,并且获取结果 # exec #执行Python代码,接收:代码或者字符串 #id #查看内存地址 #input #等待用户输入 # isinstance #查看某个对象是不是某个类的实例 # issubclass # # len #查看长度 # list # # memoryview #查看内存地址相关类 # next # # iter #创建迭代器 # object #所有类的复类 # open # # ord # # pow # # print # # property # # range # # repr # # reversed #反转 # round # # set #集合 # slice # # sorted # # staticmethod # # str #字符串 # super #面向对象 # tuple #元祖 # type #类型 # vars #当前模块有哪些变量 # zip #压缩 # __import__ #导入模块 # delattr() # getattr() # setattr() 1.1.5函数返回值想要获取函数的执行结果,就可以用return语句把结果返回。
1.函数在执行过程中只要遇到return语句,就会停止执行并返回结果,也可以理解为return语句代表着函数的结果。2.如果未在函数中指定return,那这个函数的返回值为None。 1.1.6递归函数
在函数内部,可以调用其他函数。如果一个函数在内部调用自身,这个函数就是递归函数。
#!/usr/bin/env python # Author:xuliangwei defcalc(n): print(n) ifint(n/2) ==0: returnn returncalc(int(n/2)) calc(10)递归特征:
1.必须有一个明确的结束条件。
2.每次进入更深一层递归时,问题规模相比上次递归都应有所减少。
3.递归效率不高,递归层次过多会导致栈益处(在计算机中,函数调用是通过栈(stack)这种数据结果实现的,每当进入一个函数调用,栈就会加一层栈帧,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈益处。)
1.1.7匿名函数匿名函数就是不需要显示的指定函数
#!/usr/bin/env python # Author:xuliangwei defcalc(n): returnn**n print(calc(10)) #换成匿名函数 calc= lambdan:n**n print(calc(10)) #从上看来好像并无卵用,如果是这么用确实没毛改进,不过匿名函数主要是和其他函数搭配使用,如下: res=map(lambdax:x**2,[1,5,7]) foriinres: print(i) #结果: 1 25 49 1.1.8高阶函数变量可以指向函数,函数的参数能接收变量,那么一个函数就可以接收另一个函数作为参数,这种函数就称之为高阶函数。
#!/usr/bin/env python # Author:xuliangwei defadd(x,y,f): returnf(x) +f(y) res=add(3,-6,abs) print(res) 1.1.9函数式编程函数是Python内建支持的一种封装,我们通过把大段代码拆成函数,通过一层一层的函数调用,就可以把复杂任务分解成简单的任务,这种分解可以称之为面向过程的程序设计。函数就是面向过程的程序设计的基本单元。
而函数式编程,虽然也可以归结到面向过程的程序设计,但其思想更接近数学计算。
我们首先要搞明白计算机(Computer)和计算(Compute)的概念。
在计算机的层次上,CPU执行的是加减乘除的指令代码,以及各种条件判断和跳转指令,所以,汇编语言是最贴近计算机的语言。
而计算则指数学意义上的计算,越是抽象的计算,离计算机硬件越远。
函数式编程就是一种抽象程度很高的编程范式,纯粹的函数式编程语言编写的函数没有变量,因此,任意一个函数,只要输入是确定的,输出就是确定的,这种纯函数我们称之为没有副作用。而允许使用变量的程序设计语言,由于函数内部的变量状态不确定,同样的输入,可能得到不同的输出,因此,这种函数是有副作用的。
函数式编程的一个特点就是,允许把函数本身作为参数传入另一个函数,还允许返回一个函数!
Python对函数式编程提供部分支持。由于Python允许使用变量,因此,Python不是纯函数式编程语言。
(1 + 2) * 3 - 4 #传统的过程式编程,可能这样写: vara= 1 + 2; varb=a* 3; varc=b- 4; #函数式编程要求使用函数,我们可以把运算过程定义为不同的函数,如下: varresult=subtract(multiply(add(1,2), 3), 4); #这就是函数式编程(就会这么多) 1.2装饰器 1.自动执行xx函数并且将其下面的函数名f1当作参数传递2.将xx函数的返回值,重新赋值
定义:本质是函数,(装饰其他函数)就是为其他函数添加附件功能。
1.不能修改被装饰的函数的源代码2.不能修改被装饰的函数的调用方式
实现装饰器知识储备:
1.函数即"变量"2.高阶函数
3.嵌套函数
高级函数+嵌套函数=>装饰器 无参数和无嵌套函数装饰器 deffoo(func): print 'decorator foo' returnfunc @foo defbar(): print 'bar' bar() # 没有嵌套函数,增加了打印"decorator foo"功能,并且没有改变函数的调用方式。 无参数装饰器(没有参数) #!/usr/bin/env python # Author:xuliangwei importtime defdecorator(func): defwrapper(*args, **kwargs): start=time.time() func(*args, **kwargs) stop=time.time() print ('run time is %s ' % (stop-start)) print ("timeout") returnwrapper @decorator # 装饰器 deftest(list_test): foriinlist_test: time.sleep(0.1) print ('-' * 20,i) # decorator(test)(range(10)) test(range(10)) # 可以看出装饰器decorator并没有参数 有参数装饰器(没有参数) importtime deftimer(timeout=0): defdecorator(func): defwrapper(*args, **kwargs): # 会给装饰器传递参数,因为无法确定装饰器有多少参数,所以使用这个。 start=time.time() func(*args, **kwargs) stop=time.time() print ('run time is %s ' % (stop-start)) print (timeout) returnwrapper returndecorator @timer(2) # 装饰器的参数为2 deftest(list_test): foriinlist_test: time.sleep(0.1) print ('-' * 20,i) # timer(timeout=10)(test)(range(10)) test(range(10)) # 装饰器timer的参数为2,@timer(2)相当于test=timer(2)(test) 1.3迭代器
我们已经知道,可以直接作用于for循环的数据类型有以下几种:
一类是集合数据类型,如list、tuple、dict、set、str等;
一类是generator,包括生成器和带yield的generator function。
这些可以直接作用于for循环的对象统称为可迭代对象:Iterable。
可以使用isinstance()判断一个对象是否是Iterable对象:
xuliangwei:~xuliangwei$Python3 >>> >>> fromcollectionsimport Iterable >>>isinstance([], Iterable) True >>>isinstance({}, Iterable) True >>>isinstance('abc', Iterable) True >>>isinstance((xforxinrange(10)), Iterable) True >>>isinstance(100, Iterable) False而生成器不但可以作用于for循环,还可以被next()函数不断调用并返回下一个值,直到最后抛出StopIteration错误表示无法继续返回下一个值了。
*可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator。可以使用isinstance()判断一个对象是否是Iterator对象:
xuliangwei:~xuliangwei$Python3 >>> >>> fromcollectionsimport Iterator >>>isinstance((xforxinrange(10)), Iterator) True >>>isinstance([], Iterator) False >>>isinstance({}, Iterator) False >>>isinstance('abc', Iterator) False你可能会问,为什么list、dict、str等数据类型不是Iterator?
这是因为Python的Iterator对象表示的是一个数据流,Iterator对象可以被next()函数调用并不断返回下一个数据,直到没有数据时抛出StopIteration错误。可以把这个数据流看做是一个有序序列,但我们却不能提前知道序列的长度,只能不断通过next()函数实现按需计算下一个数据,所以Iterator的计算是惰性的,只有在需要返回下一个数据时它才会计算。
Iterator甚至可以表示一个无限大的数据流,例如全体自然数。而使用list是永远不可能存储全体自然数的。
小结
凡是可作用于for循环的对象都是Iterable类型;
凡是可作用于next()函数的对象都是Iterator类型,它们表示一个惰性计算的序列;
集合数据类型如list、dict、str等是Iterable但不是Iterator,不过可以通过iter()函数获得一个Iterator对象。
Python的for循环本质上就是通过不断调用next()函数实现的,例如:
for x in [1, 2, 3, 4, 5]: pass实际上完全等价于:
# 首先获得Iterator对象: it=iter([1, 2, 3, 4, 5]) # 循环: while True: try: # 获得下一个值: x=next(it) except StopIteration: # 遇到StopIteration就退出循环 break 1.4生成器通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。
所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器:generator。
要创建一个generator,有很多种方法。第一种方法很简单,只要把一个列表生成式的[]改成(),就创建了一个generator: l= [x*xforxinrange(10)] print(l) g= (x*xforxinrange(10)) print(g) #执行结果: [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] <generator object<genexpr>at0x101380938>1.只有在调用时才会生成相应的数据。
只记录当前位置。
只有一个 next ()方法。next()