3

python语法进阶这一篇就够了 - 孙凯玉

 1 year ago
source link: https://www.cnblogs.com/kasia/p/17090278.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

前言

前面我们已经学习了Python的基础语法,了解了Python的分支结构,也就是选择结构、循环结构以及函数这些具体的框架,还学习了列表、元组、字典、字符串这些Python中特有的数据结构,还用这些语法完成了一个简单的名片管理系统。下面我就将介绍一下Python的一些进阶语法规则,为后面更复杂的编程打下基础。

  1. 闭包与装饰器
    什么是闭包、装饰器函数、yield关键字

  2. python高阶函数
    lambda匿名函数、reduce函数、map函数、filter过滤器函数

  3. 面向对象编程
    什么是面向对象、对象的封装、类的继承、类的多态

  4. 进程与线程编程
    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-8
import time
import random

# 定义跑道长度
track_length = 10
def runtime(func):
    def wrapper():
        start_time = time.time()
        func()
        end_time = time.time()
        print (func.__name__,"运行时间是",end_time-start_time,"秒")
    return wrapper
    
@runtime
def 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)
@runtime
def 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()

运行一下:

1675421215622.png

发现运行成功,但我们想如果我要修改打印的话就要都修改一次,特别麻烦,而且,这是5个函数如果是500个,我们还要一个一个的去加吗?这就有我们的装饰器了,首先我用装饰器修改下,再给大家解释。

def outer(origin):
    def inner():
        print("装饰器的学习")
        res = origin()
        print("装饰器的学习")
        return res
 
    return inner
 
 
@outer
def a():
    pass
 
 
@outer
def b():
    pass
 
 
@outer
def c():
    pass
 
 
@outer
def d():
    pass
 
 
@outer
def e():
    pass
 
 
a()
b()
c()
d()
e()

运行一下:

1675421264764.png

发现这样我们也成功了,接下来小编来个大家解释

首先:
我们要明白@的作用,那我们的函数a来举例子@的作用就是帮我们执行一次a=outer(a),首先python将把我们的a变成参数传给outer函数,运行后再赋值给a,这就是@的作用。

其次给大家解释一下自定的outer函数
我自己称这个函数为@下函数的补丁函数,也就是装饰器函数还是拿a函数举例子,首先a函数变成参数传给了我们的outer函数,outer里又嵌套了一个inner函数 ,然后将函数a赋值给res,然后用return语句返回出结果,外层函数返回inner函数,也就是将inner函数运行一次,这就是工作流程。

最后分别在各函数前加上装饰,最后运行出结果

1675421264764.png

这就是装饰器的写法。

装饰器的参数
这时我遇到一个问题如果函数内有参数而且每个函数的参数数量不同,我们应该怎末办,先看下面代码

def outer(origin):
    def inner():
        print("装饰器的学习")
        res = origin()
        print("装饰器的学习")
        return res
 
    return inner
 
 
@outer
def a(g, e):
    pass
 
 
@outer
def b(w):
    pass
 
 
@outer
def c(u, y, t):
    pass
 
 
@outer
def d(c):
    pass
 
 
@outer
def e():
    pass
 
 
a()
b()
c()
d()
e()

这时我们运行一下

image.png

发现报错,是因为我们的装饰器内没有这两个参数,那可以在装饰器内设置两个参数,但问题是,有的函数内有3个参数,而有的函数内没有参数,那我们应该怎么办?

针对这个问题我们可以给装饰器设置动态参数,先看代码:

def outer(origin):
    def inner(*args, **kwargs):
        print("装饰器的学习")
        res = origin(*args, **kwargs)
        print("装饰器的学习")
        return res
 
    return inner
 
 
@outer
def a(a1):
    print("我是一函数")
 
 
@outer
def b(a1, a2):
    print("我是二函数")
 
 
@outer
def c(a5, a6, a7):
    print("我是三函数")
 
 
a(1)
b(2, 3)
c(4, 5, 6)

因为函数太多了,小编有点麻烦就剪了几个函数,但道理是相同的,这时我们再运行一下

1675421364035.png

这样我们就成功了,以上就是装饰器的写法,接下来给大家拓展一下

装饰器的拓展:(functools模块)
首先给大家引入一下这时教给大家几个魔法方法

1675421496515.png
接下来我们实战一下

def outer(origin):
    def inner(*args, **kwargs):
        # 我是一个装饰器函数
        print("装饰器的学习")
        res = origin(*args, **kwargs)
        print("装饰器的学习")
        return res
 
    return inner
 
 
@outer
def c(a5, a6, a7):
    # 我是个函数
    print("我是三函数")
 
 
c(4, 5, 6)
print(c.__name__)
print(c.__doc__)

运行一下:

1675421532140.png

这时我们发现我要的是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
 
 
@outer
def c(a5, a6, a7):
    # 我是个函数
    print("我是三函数")
 
 
c(4, 5, 6)
print(c.__name__)
print(c.__doc__)

这时再运行一下

1675421572219.png

这时我们发现,我们伪装成功了,这样就会让我们的装饰更像。

装饰器模板:
接下来送给大家装饰器的模板,以后需要随时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 math
def circle_area(r):
    result = math.pi * r * r
    return result
r = circle_area(3)
print (r)
"""
lambda是一个关键字
冒号前边的r是这个函数的参数
冒号后边的是这个函数的运算逻辑
"""
result = lambda r:math.pi * r * r
r = 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 / b
f = calc_function("*")
print (f)
r = f(3,4)
print (r)

print打印结果:

28.2743338823
28.2743338823
<function <lambda> at 0x03159B70>
12

2. map自动拆分的计算函数

# coding=utf-8
# map函数
my_list = [1,2,3,4,5]
# 1
result = []
for i in my_list:
    result.append(i + 1)
print (result)

# 2
def add_one(e):
    return e + 1
r = 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 e
r =map(add_two,my_list)
print (list(r))
# 3
print (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
# 导入reduce
from functools import reduce
a =[2,4,6,8,10]
def add(x,y):
    return x + y
result = reduce(add,a)
print (result)

print (reduce(lambda x,y : x+y,a))

print打印结果:

30
30

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):
    pass
a = A()

def run(obj):
    obj.run()

run(dog)
run(cat)
run(person)
run(a)

print打印结果:

狗狗跑
猫跑
人类跑
狗狗跑
猫跑
人类跑
动物开始跑

6. 多进程编程

# coding=utf-8
# 多进程编程代码演示
import time
from multiprocessing import Process
import os

def 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

访问量破千,一起加油!

写博客是为了记录和分享自己的学习历程,温故知新!做的不好的地方欢迎指正!!!


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK