前言
前面我们已经学习了Python的基础语法,了解了Python的分支结构,也就是选择结构、循环结构以及函数这些具体的框架,还学习了列表、元组、字典、字符串这些Python中特有的数据结构,还用这些语法完成了一个简单的名片管理系统。下面我就将介绍一下Python的一些进阶语法规则,为后面更复杂的编程打下基础。
闭包与装饰器
什么是闭包、装饰器函数、yield关键字python高阶函数
lambda匿名函数、reduce函数、map函数、filter过滤器函数面向对象编程
什么是面向对象、对象的封装、类的继承、类的多态进程与线程编程
python中的进程与线程、多线程编程
第一章. 闭包与装饰器1. 什么是闭包
# coding=utf-8# 闭包# def func1():# print ("函数1运行")# return func2()# #函数1的返回值是函数2的引用# def func2():# print ("函数2运行")# return 2# r =func1()# print (r)# r2= r() # r = func2# print (r2)def func1(): print ("函数1运行") def func2(): print ("函数2运行") func2() return func2()f2 = func1()print(f2)f2() """在一个函数,比如func1中的内部定义了另外一个函数function2并且函数1(func1)的返回值是函数2(func2)的引用这种情况,我们称之为闭包简单来说就是外部函数返回内部函数的引用就叫做闭包"""
print打印结果:
函数1运行函数2运行函数2运行None
案例:龟兔赛跑
# coding=utf-8import timeimport random# 定义跑道长度track_length = 10def runtime(func): def wrapper(): start_time = time.time() func() end_time = time.time() print (func.__name__,"运行时间是",end_time-start_time,"秒") return wrapper @runtimedef tortoise(): # for i in [1,2,3,4,5,6,7,8,9,10]: for i in range(1,track_length+1): print ("乌龟跑的{}米".format(i)) time.sleep(1)@runtimedef rabbit(): for i in range(1,track_length + 1): if i % 5 == 0: time.sleep(random.randint(1,10)) print ("兔子跑了{}米".format(i))tortoise()rabbit()
print打印结果:
乌龟跑的1米乌龟跑的2米乌龟跑的3米乌龟跑的4米乌龟跑的5米乌龟跑的6米乌龟跑的7米乌龟跑的8米乌龟跑的9米乌龟跑的10米tortoise 运动时间是 10.04876708984375 秒 兔子跑了1米兔子跑了2米兔子跑了3米兔子跑了4米兔子跑了5米兔子跑了6米兔子跑了7米兔子跑了8米兔子跑了9米兔子跑了10米rabbit 运动时间是 9.022485494613647 秒
2. 什么是装饰器呢?
就是在特定条件下为某些函数再不改动函数体的时候为函数新添加一些功能,这就是装饰器
实现原理:
基于@语法和函数闭包,将原函数封装在闭包中,然后将函数赋值为一个新的函数(内置函数),执行函数时再在内层函数中执行闭包中的原函数
实现效果:
可以在你改变函数内部代码和调用的前提下,实现在函数执行和执行拓展功能
适用场景:
多个函数系统统一在执行前后定义一些功能
关于前言我们了解这么多就够了,然后小编带着大家推导出装饰器
装饰器:
装饰器的写法:
这里我们有一个需求,我们定义了5个函数,想在5个函数执行前和执行后都打印一句话:装饰器的学习。首先我们来写于一下没有装饰器的写法,话不多说直接上代码:
def a(): pass def b(): pass def c(): pass def d(): pass def e(): pass
先定义5个函数,再加上我们要打印的话:
def a(): print("装饰器的学习") print("装饰器的学习") def b(): print("装饰器的学习") print("装饰器的学习") def c(): print("装饰器的学习") print("装饰器的学习") def d(): print("装饰器的学习") print("装饰器的学习") def e(): print("装饰器的学习") pass print("装饰器的学习") a()b()c()d()e()
运行一下:
发现运行成功,但我们想如果我要修改打印的话就要都修改一次,特别麻烦,而且,这是5个函数如果是500个,我们还要一个一个的去加吗?这就有我们的装饰器了,首先我用装饰器修改下,再给大家解释。
def outer(origin): def inner(): print("装饰器的学习") res = origin() print("装饰器的学习") return res return inner @outerdef a(): pass @outerdef b(): pass @outerdef c(): pass @outerdef d(): pass @outerdef e(): pass a()b()c()d()e()
运行一下:
发现这样我们也成功了,接下来小编来个大家解释
首先:
我们要明白@的作用,那我们的函数a来举例子@的作用就是帮我们执行一次a=outer(a),首先python将把我们的a变成参数传给outer函数,运行后再赋值给a,这就是@的作用。
其次给大家解释一下自定的outer函数
我自己称这个函数为@下函数的补丁函数,也就是装饰器函数还是拿a函数举例子,首先a函数变成参数传给了我们的outer函数,outer里又嵌套了一个inner函数 ,然后将函数a赋值给res,然后用return语句返回出结果,外层函数返回inner函数,也就是将inner函数运行一次,这就是工作流程。
最后分别在各函数前加上装饰,最后运行出结果
这就是装饰器的写法。
装饰器的参数
这时我遇到一个问题如果函数内有参数而且每个函数的参数数量不同,我们应该怎末办,先看下面代码
def outer(origin): def inner(): print("装饰器的学习") res = origin() print("装饰器的学习") return res return inner @outerdef a(g, e): pass @outerdef b(w): pass @outerdef c(u, y, t): pass @outerdef d(c): pass @outerdef e(): pass a()b()c()d()e()
这时我们运行一下
发现报错,是因为我们的装饰器内没有这两个参数,那可以在装饰器内设置两个参数,但问题是,有的函数内有3个参数,而有的函数内没有参数,那我们应该怎么办?
针对这个问题我们可以给装饰器设置动态参数,先看代码:
def outer(origin): def inner(*args, **kwargs): print("装饰器的学习") res = origin(*args, **kwargs) print("装饰器的学习") return res return inner @outerdef a(a1): print("我是一函数") @outerdef b(a1, a2): print("我是二函数") @outerdef c(a5, a6, a7): print("我是三函数") a(1)b(2, 3)c(4, 5, 6)
因为函数太多了,小编有点麻烦就剪了几个函数,但道理是相同的,这时我们再运行一下
这样我们就成功了,以上就是装饰器的写法,接下来给大家拓展一下
装饰器的拓展:(functools模块)
首先给大家引入一下这时教给大家几个魔法方法
接下来我们实战一下
def outer(origin): def inner(*args, **kwargs): # 我是一个装饰器函数 print("装饰器的学习") res = origin(*args, **kwargs) print("装饰器的学习") return res return inner @outerdef c(a5, a6, a7): # 我是个函数 print("我是三函数") c(4, 5, 6)print(c.__name__)print(c.__doc__)
运行一下:
这时我们发现我要的是c函数,但给我反馈的是inner函数,这是为什么呢?
这就是工作原理,直接就把c函数装饰成了inner函数,那以后再工作中一定会要自己函数的名字,而不要我装饰后的函数,这样就可以让我们的函数装饰的更像,其实在以后中,都想装饰的更像,那我们应该怎末办?
这时就需要我们的第三方模块functools,直接上代码
import functools def outer(origin): @functools.wraps(origin) def inner(*args, **kwargs): # 我是一个装饰器函数 print("装饰器的学习") res = origin(*args, **kwargs) print("装饰器的学习") return res return inner @outerdef c(a5, a6, a7): # 我是个函数 print("我是三函数") c(4, 5, 6)print(c.__name__)print(c.__doc__)
这时再运行一下
这时我们发现,我们伪装成功了,这样就会让我们的装饰更像。
装饰器模板:
接下来送给大家装饰器的模板,以后需要随时ctrl+c和ctrl+v
import functools def outer(origin): @functools.wraps(origin) def inner(*args, **kwargs): # 这里书写需要装饰的功能 res = origin(*args, **kwargs) return res return inner
第二章. Python高阶函数1. lambda表达式(匿名函数)
# coding=utf-8# lambda表达式(匿名函数)# 计算圆形的面积# pi * r * r# 导入数学模块import mathdef circle_area(r): result = math.pi * r * r return resultr = circle_area(3)print (r)"""lambda是一个关键字冒号前边的r是这个函数的参数冒号后边的是这个函数的运算逻辑"""result = lambda r:math.pi * r * rr = result(3)print (r)def calc_function(o): if o == "+": return lambda a,b : a + b elif o == "-": return lambda a,b : a - b elif o == "*": return lambda a,b : a * b elif o == "/": return lambda a,b : a / bf = calc_function("*")print (f)r = f(3,4)print (r)
print打印结果:
28.274333882328.2743338823<function at 0x03159B70>12
2. map自动拆分的计算函数
# coding=utf-8# map函数my_list = [1,2,3,4,5]# 1result = []for i in my_list: result.append(i + 1)print (result)# 2def add_one(e): return e + 1r = map(add_one,my_list)print (list(r))def add_two(e): if e == 1: return e + 3 elif e == 2: return 2 - 1 else: return er =map(add_two,my_list)print (list(r))# 3print (list(map(lambda e:e+1,my_list)))
print打印结果:
[2, 3, 4, 5, 6][2, 3, 4, 5, 6][4, 1, 3, 4, 5][2, 3, 4, 5, 6]
3. reduce自动堆叠计算函数
# coding=utf-8# reduce# 导入reducefrom functools import reducea =[2,4,6,8,10]def add(x,y): return x + yresult = reduce(add,a)print (result)print (reduce(lambda x,y : x+y,a))
print打印结果:
3030
4. filter过滤器函数
# coding=utf-8# filter函数letter=['a',"B",'c',"D",'e',"F"]upper_letter = filter(lambda x: x == x.upper(),letter)print (upper_letter)print (list(upper_letter))student_name = ['李元芳','李建国','莫怀羽']print (list(filter(lambda x:x.startwith("李"), student_name)))
print打印结果:
['B', 'D', 'F']['B', 'D', 'F']['李元芳','李建国']
第三章. 面向对象编程1. 对象的封装
# coding=utf-8# 对象的封装# 类的概念"""类的名字:当名字由多个单词构成时,我们采用驼峰命名法就是说多个单词,每个单词的首字母需要大写这也是python的命名规则"""class BeautifulGirl(): # 类的属性 eye = "" nose = "" mouth = "" hair = "" face = "" # 构造函数 def __init__(self,eye,nose,mouth,hair,face): self.eye = eye self.nose = nose self.mouth = mouth self.hair = hair self.face = face print ("构造函数运行了") # 在这就叫做类的方法 def dance(self): print ("美女在跳舞") def get_beautiful_girl(self): print ("这个美女的样貌是:") print (self.nose) print (self.mouth) print (self.hair) print (self.face) print (self.eye)# 实例化就是获取具体对象的一个过程 new新的一个。girl = BeautifulGirl("大大的眼睛" ,"小巧的嘴唇" ,"乌黑亮丽的头发" ,"清秀的脸庞")girl.dance()girl.get_beautiful_girl()girl2 = BeautifulGirl("小小的眼睛",'鼻子','嘴','头发','脸庞')girl2.get_beautiful_girl()
print打印结果:
大大的眼睛小巧的嘴唇乌黑亮丽的头发清秀的脸庞小小的眼睛这个美女的样貌是:鼻子嘴头发脸庞
2. 类的私有属性
# coding=utf-8# 类的私有属性class BeautifulGirl(): # 类的属性 eye = "" nose = "" mouth = "" hair = "" face = "" # 这就是私有属性,私有属性在类的外部是不可以访问的 __name ="高圆圆" address = "河北省唐山市" # 构造函数 def __init__(self,eye,nose,mouth,hair,face): self.eye = eye self.nose = nose self.mouth = mouth self.hair = hair self.face = face print ("构造函数运行了") # 在这就叫做类的方法 def dance(self): print ("美女在跳舞") def __dd(self): print ("美女在跳舞") def get_beautiful_girl(self): print ("这个美女的样貌是:") print (self.__name) print (self.nose) print (self.mouth) print (self.hair) print (self.face) print (self.eye)girl = BeautifulGirl("大大的眼睛" ,"小巧的嘴唇" ,"乌黑亮丽的头发" ,"清秀的脸庞")print (girl.mouth)print (girl.address)# print (girl.__name)# # 类的私有属性可以访问吗?# print (BeautifulGirl.__dict__)# print (girl._beautiful__name)girl.get_beautiful_girl()
print打印结果:
构造函数运行了这个美女的样貌是:高圆圆大大的眼睛小巧的鼻子薄薄的嘴唇乌黑亮丽的头发清秀的脸庞
3. 类中的方法
# coding=utf-8# 类的私有属性class BeautifulGirl(): # 类的属性 eye = "" nose = "" mouth = "" hair = "" face = "" # 这就是私有属性,私有属性在类的外部是不可以访问的 __name ="高圆圆" address = "河北省唐山市" # 构造函数,也叫构造方法 def __init__(self,eye,nose,mouth,hair,face): self.eye = eye self.nose = nose self.mouth = mouth self.hair = hair self.face = face print ("构造函数运行了") # 在这就叫做类的方法 def dance(self): print ("美女在跳舞") # 这个叫做私有方法 def __dd(self): print ("美女在跳舞") # 这个叫做一般方法 def get_beautiful_girl(self): print ("这个美女的样貌是:") print (self.__name) print (self.nose) print (self.mouth) print (self.hair) print (self.face) print (self.eye) # 静态方法 # 静态方法不能够访问类中的属性 @staticmethod def study(): print ("美女在实习") # 类方法 # 类方法是不可以访问实例变量的,它可以访问类变量(类的属性 @classmethod def girl_friend(cls): print (cls.__name) print (cls.address) print (cls.face)girl = BeautifulGirl("大大的眼睛" ,"小巧的嘴唇" ,"乌黑亮丽的头发" ,"清秀的脸庞")# print (BeautifulGirl.__dict__)# 这就访问了类中的私有方法# girl.beautifulGirl__dd()girl.study()BeautifulGirl.study()# 类名,一般方法的名称调用是会报错的# BeautifulGirl.dance(girl)girl.girl_friend()BeautifulGirl.girl_friend()girl.get_beautiful_girl()
print打印结果:
构造函数运行了这个美女的样貌是:高圆圆河北省唐山市高圆圆河北省唐山市大大的眼睛小巧的鼻子薄薄的嘴唇乌黑亮丽的头发清秀的脸庞
4. 类的继承
# coding=utf-8# 类的继承# 父类和子类class Father(object): age = 38 def __init__(self,name): self.name = name print ("父类的构造函数运行了") def father_money(self): print ("父亲有很多钱") def __father_knowleger(self): print ("父亲的知识体系") @staticmethod def study(): print ("父亲在学习") @classmethod def father_friend(cls): print ("父亲有很多朋友") def face(self): print ("父亲非常帅")# 意味着son这个类继承了father这个类class Son(Father): def __init__(self): print ("子类的构造函数运行了")# son = Son("小王")son = Son()# 在继承中,子类如果有构造函数,name就不会调用弗雷德构造函数# 在继承中,一般的方法是可以被继承的son.father_money()# 私有方法可以被继承# son.__father_knowleger()son.study()son.father_friend()class Mother(): def face(self): print ("妈妈长的很漂亮")# 这就叫做多继承class Son2(Mother,Father): def __init__(self): print("2儿子的构造函数运行了")son2 = Son2()son2.father_money()son2.face()# 当多继承的时候,多个父类拥有一个名称的变量或方法时# 哪个父类写在继承列表的前边,子类就继承谁的
print打印结果:
子类的构造函数运行了父亲有很多钱父亲在学习父亲有很多朋友2儿子的构造函数运行了父亲有很多钱妈妈长的很漂亮
5. 类的多态
# coding=utf-8# 类的多态# 指的是多种形态class Animal(): def run(self): print ("动物开始跑")# 子类在继承父类的过程中,重写了父类中的方法class Dog(Animal): def run(self): print ("狗狗跑")class Cat(Animal): def run(self): print ("猫跑")class Person(Animal): def run(self): print ("人类跑")dog = Dog()dog.run()cat = Cat()cat.run()person = Person()person.run()# 多个类继承同一个类,都重写了父类的方法,呈现出了不同的形态# 多态性class A(Animal): passa = A()def run(obj): obj.run()run(dog)run(cat)run(person)run(a)
print打印结果:
狗狗跑猫跑人类跑狗狗跑猫跑人类跑动物开始跑
6. 多进程编程
# coding=utf-8# 多进程编程代码演示import timefrom multiprocessing import Processimport osdef target_function(): print ("子进程的ID:{}".format(os.getpid())) time.sleep(2)if __name__== "__main__": print (__name__) print ("主进程ID:{}".format(os.getpid())) ps = [] for i in range(10): p = Process(target_function()) p.start() ps.append(p) # 让主进程等待子进程进行运行完成后在停止 for p in ps: p.join()
print打印结果:
__main__主进程ID:2692子进程的ID:2692子进程的ID:2692子进程的ID:2692子进程的ID:2692子进程的ID:2692子进程的ID:2692子进程的ID:2692子进程的ID:2692子进程的ID:2692子进程的ID:2692
最后
访问量破千,一起加油!
写博客是为了记录和分享自己的学习历程,温故知新!做的不好的地方欢迎指正!!!