了解 Python 设计模式

news2024/10/7 4:33:41

Python🐍设计模式

在这里插入图片描述

Python 是一种功能强大的、基于对象的高级编程语言,具有动态类型和绑定功能。由于其灵活性和强大功能,开发人员经常采用某些规则或 Python 设计模式。究竟是什么让设计模式如此重要,这对普通的Python开发人员意味着什么?
在这篇文章将解释为什么Python非常适合设计模式,以及如何使用它们来释放更多潜力,或简化开发并使代码更易于维护。

Python 是一种具有动态类型和动态绑定的高级编程语言。许多开发人员都爱上了Python ❤️,因为它清晰的语法,结构良好的模块和包,以及它的巨大灵活性和现代功能的范围。

在 Python 中,没有什么强制要求,在所有场景你都需要编写类并从中实例化对象。如果你在项目中不需要复杂的结构,你可以只编写函数完成功能即可。再简单一点的任务,您可以编写一个简单脚本来执行,而无需为此创建1个完整项目并编译部署。因此,Python程序设计可以不受约束,灵活方便。👍

同时,Python是一种100%面向对象的语言。简单地说,Python中的所有内容都是一个对象。函数是对象,数据类型本身也是对象。

因此,您可以使用Python编写简单的脚本,或者只需打开Python终端并在那里执行语句。您也可以创建复杂的框架、应用程序、库等。你可以在Python中做很多事情。当然有很多限制,但这不是本文的主题。

但是,由于Python非常强大和灵活,因此在编程时我们需要一些规则(或模式)。❓什么是模式,以及它们与Python的关系。:

为什么 Python 用于设计模式编程有好处?

任何编程语言都可用设计模式编程。事实上,应该在任何给定编程语言的上下文中考虑模式。设计模式、语言语法和性质都限制了我们的编程。来自语言语法和语言性质(动态、功能、面向对象等)的限制可能不同,它们存在的原因也可能不同。来自模式的限制是有原因的,它们是有目的的。这是模式的基本目标;告诉我们如何做某事以及如何不做。稍后我们将讨论模式,尤其是 Python 设计模式。
在这里插入图片描述

Python的理念建立在深思熟虑的最佳实践之上。Python是一种动态语言,因此,已经通过几行代码实现或使其易于实现。一些设计模式内置在 Python 中,所以我们甚至在不知情的情况下使用它们。即使是经验一般的开发人员也可以搜索现有的Python代码以查找设计模式,并一目了然地识别它们。由于语言的性质,不需要其他模式。

例如,工厂是一种结构化的Python设计模式,旨在创建新对象,对用户隐藏实例化逻辑。但是在 Python 中创建对象在设计上是动态的,因此不需要像 Factory 这样的附加功能。当然,如果您愿意,您可以自由实施它。在某些情况下,它可能非常有用,但它们是一个例外,而不是常态。

Python的哲学有什么好处?让我们从这个开始(在 Python 终端中通过 import this 来显示):

>>> import this
The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!
优美总比丑陋好。
明了胜于晦涩。
简单胜于复杂。
复杂胜于凌乱。
扁平胜于嵌套。
间隔胜于紧凑。
可读性很重要。
特殊情况不足以违反规则。
虽然实用性胜过完美。
但错误不应该放任。
除非你希望如此。
遇到模棱两可的地方,不要胡乱猜测。
肯定有一种通常也是唯一一种最佳的解决方案。
虽然这种方案并不是显而易见的,因为你不是那个荷兰人[这里指的是Python之父Guido]。
现在开始做比不做好。
不做要比盲目去做好。
如果一个实现方案难于理解,它就不是一个好的方案。
如果实现很容易理解,这可能是一个好主意。
命名空间非常有用 - 应当多加利用!
>>>

这些可能不是传统意义上的Python模式,但这些规则以最优雅和有用的方式定义了“Pythonic” 式的编程风格。

还有 PEP-8 代码指南,可帮助构建我们的代码。这对我来说是必须的,当然,有一些适当的例外。顺便说一下,PEP-8 本身鼓励这些例外:

但最重要的是:知道什么时候不一致——有时编代码编写指南的确不适用。如有疑问,请使用您的最佳判断。查看其他示例并决定最佳外观。不要犹豫,问!

Python设计模式

什么是"设计模式"?

设计模式是解决众所周知问题的常用方法。Python开发者定义的设计模式的基础有两个主要原则:

  • 编程到接口而不是实现。

  • 优先选择对象组合而不是继承。

让我们从 Python 程序员的角度仔细看看这两个原则。

编程到接口名 Program to Interface

Python有个“Duck Typing" 鸭子类型的故事,

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sOnTHojr-1689174005337)(D:\BaiduNetdiskWorkspace\Python技术\Python设计模式.assets\image-20230712212009042.png)]

Duck Typing 是一种编程风格,决定一个对象是否有正确的接口,关注点在于它的方法或属性,而不是它的类(“如果它看起来像鸭子,像鸭子一样嘎嘎叫,那么它一定是鸭子。”)。通过强调接口而不是特定的类,设计良好的代码通过多态提高了灵活性。鸭子类型无需使用 type()isinstance() 进行检查(注意,相反,它通常使用 hasattr() 来检查。

在Python中,我们不喜欢定义各种接口类,但这并不意味着我们不考虑接口,事实上,在鸭子类型风格中,我们一直考虑的是,在相关对象中,直接写新的接口方法调用语句,但并不需要实现相关类的代码。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WCv1szxC-1689174005343)(https://assets.toptal.io/images?url=https%3A%2F%2Fuploads.toptal.io%2Fblog%2Fimage%2F126799%2Ftoptal-blog-image-1533727883728-67efc9f706da65fe2ffccded3221834a.png)]

让我们看看关于鸭子类型的使用方法,看看它如何适应这种范式:Program to Interface(编程到接口名。

不必关心Object对象是什么;我们只想知道它是否能做我们需要的事情(我们只对object的接口感兴趣)。

当前对象会嘎嘎叫吗?所以,让它嘎嘎叫!

try:
    bird.quack()
except AttributeError:  #如果quack()方法不存在,就会执行lof()方法。
    self.lol()

我们为鸭子定义了接口类?没有!我们是否对接口实现进行编程了吗?没有!但代码也能运行,这样也挺好。后面细化时,真的需要实现quack()方法,在相关类里实现即可。

支持对象组合而不是继承

这就是我所说的 Pythonic 原则!与类继承的方式相比,Duck Typing编程风格创建的类/子类更少。

而不是像下例这样,写1个典型的接口实现类

class User(DbObject): # 继承自DbObject
    # do some thing
    .....

用Pythonic 方式,可以这样做

class User:
    _persist_methods = ['get', 'save', 'delete']

    def __init__(self, persister):
        self._persister = persister

    def __getattr__(self, attribute):
        if attribute in self._persist_methods:
            return getattr(self._persister, attribute)

优势是显而易见的。无须实现各种类的方法。我们可以在运行时注入持久化实例!例如,今天它是一个关系数据库,但明天它可能是我们需要的接口(又是那些讨厌的鸭子)。

组合对Python来说是优雅和自然的。

行为型模式

行为型模式涉及对象之间的通信,对象如何交互并完成给定的任务。根据GOF原则,Python中共有11种行为模式:责任链,命令,解释器,迭代器,调解器,备忘录,观察者,状态,策略,模板,访问者。

我发现这些模式非常有用,但这并不意味着其他模式组不是。

迭代模式

迭代器内置于 Python 中。这是该语言最强大的特征之一。几年前,我在某处读到迭代器使Python很棒,我认为情况仍然如此。充分了解 Python 迭代器和生成器,您将了解有关此特定 Python 模式的所有信息。

责任链模式

这种模式为我们提供了一种使用不同方法处理请求的方法,每种方法都处理请求的特定部分。你知道,好代码的最佳原则之一是单一责任原则。

每段代码都必须做一件事,而且只能做一件事。

这一原则深深地融入了这种设计模式中。

例如,如果我们想过滤一些内容,我们可以实现不同的过滤器,每个过滤器都执行一种精确且明确定义的过滤类型。这些过滤器可用于过滤冒犯性词语、广告、不合适的视频内容等。

class ContentFilter(object):
    def __init__(self, filters=None):
        self._filters = list()
        if filters is not None:
            self._filters += filters

    def filter(self, content):
        for filter in self._filters:
            content = filter(content)
        return content

filter = ContentFilter([
                offensive_filter,
                ads_filter,
                porno_video_filter])
filtered_content = filter.filter(content)

命令模式

命令模式在出于某种原因我们需要从准备将要执行的内容开始,然后在需要时执行它的情况下非常方便。优点是,以这种方式封装操作使Python开发人员能够添加与执行的操作相关的其他功能,例如撤消/重做,或保留操作的历史记录等。

让我们看看一个简单且常用的示例是什么样的:

class RenameFileCommand(object):
    def __init__(self, from_name, to_name):
        self._from = from_name
        self._to = to_name

    def execute(self):
        os.rename(self._from, self._to)

    def undo(self):
        os.rename(self._to, self._from)

class History(object):
    def __init__(self):
        self._commands = list()

    def execute(self, command):
        self._commands.append(command)
        command.execute()

    def undo(self):
        self._commands.pop().undo()

history = History()
history.execute(RenameFileCommand('docs/cv.doc', 'docs/cv-en.doc'))
history.execute(RenameFileCommand('docs/cv1.doc', 'docs/cv-bg.doc'))
history.undo()
history.undo()

创建型模式

让我们首先指出,创建模式在 Python 中并不常用。为什么?因为语言的动态性质。Python中,工厂模式是内置在Python中的。这意味着语言本身为我们提供了以足够优雅的方式创建对象所需的所有灵活性;我们很少需要在上面实现任何东西,比如 Singleton 或 Factory。

在一个 Python 设计模式教程中,我发现了对创建设计模式的描述,其中指出这些设计“模式提供了一种在隐藏创建逻辑的同时创建对象的方法,而不是直接使用 new 运算符实例化对象。

这几乎总结了这个问题:我们在 Python 中没有新的运算符!

尽管如此,让我们看看如何实现一些,如果我们认为使用这种模式可能会获得优势。

单例模式

当我们想要保证在运行时仅存在给定类的一个实例时,将使用单例模式。我们真的需要在Python中采用这种模式吗?根据我的经验,简单地故意创建一个实例然后使用它而不是实现单例模式更容易。

但是如果你想实现它,这里有一些好消息:在Python中,我们可以改变实例化过程(以及几乎任何其他过程)。还记得我之前提到的__new__()方法吗?来吧:

class Logger(object):
    def __new__(cls, *args, **kwargs):
        if not hasattr(cls, '_logger'):
            cls._logger = super(Logger, cls
                    ).__new__(cls, *args, **kwargs)
        return cls._logger

在此示例中,logger类是单例模式。

下面是在 Python 中使用 Singleton 的可选功能:

  • 将单例类放入1个模块。
  • 在项目的起动文件(可能在配置文件中)创建一个单例类的实例。
  • 将实例传递给需要它的每个对象。这是一种依赖注入,它是一种强大且易于掌握的机制。

依赖注入

我不打算讨论依赖注入是否是一种设计模式,但我会说它是实现松散耦合的一个非常好的机制,它有助于使我们的应用程序可维护和可扩展。将它与鸭子类型相结合,原力将与您同在。总是。

把它列在这篇文章的创建模式部分,因为它处理了何时(甚至更好的是:在哪里)创建对象的问题。它是在外面创造的。最好说,对象根本不是在我们使用它们的地方创建的,因此依赖项不是在使用它的地方创建的。使用者代码接收外部创建的对象并使用它。

这是对依赖注入的一个很好的解释,让我们很好地了解了这种特定技术的潜力。基本上答案解释了以下示例的问题:不要自己从冰箱里拿东西喝,而是说明需要。告诉你的父母,你需要在午餐时喝点东西。

Python为我们提供了轻松实现所需的一切。想想它在Java和C#等其他语言中可能的实现,你会很快意识到Python的美。

让我们考虑一个简单的依赖注入示例:

class Command:

    def __init__(self, authenticate=None, authorize=None):
        self.authenticate = authenticate or self._not_authenticated
        self.authorize = authorize or self._not_autorized

    def execute(self, user, action):
        self.authenticate(user)
        self.authorize(user, action)
        return action()

if in_sudo_mode:
    command = Command(always_authenticated, always_authorized)
else:
    command = Command(config.authenticate, config.authorize)
command.execute(current_user, delete_user_action)

我们在 Command 类中注入身份验证器和授权方方法。Command 类所需要的只是成功执行它们,而无需担心实现细节。这样,我们可以将 Command 类与我们决定在运行时使用的任何身份验证和授权机制一起使用。

我们已经展示了如何通过构造函数注入依赖项,但我们可以通过直接设置对象属性来轻松注入它们,从而释放更多潜力.

command = Command()

if in_sudo_mode:
    command.authenticate = always_authenticated
    command.authorize = always_authorized
else:
    command.authenticate = config.authenticate
    command.authorize = config.authorize
command.execute(current_user, delete_user_action)

关于依赖注入,可以百度搜索更多解释

同样,在Python中,依赖注入设计模式,是内置功能。

我们不要忘记这一切意味着什么:依赖注入技术允许非常灵活和容易的单元测试。想象一个架构,您可以在其中即时更改数据存储。模拟数据库成为一项微不足道的任务,不是吗?

您可能还想研究原型、生成器和工厂设计模式。

结构型模式

门面模式

这很可能是最著名的Python设计模式。

假设您有一个包含大量对象的系统。每个对象都提供一组丰富的 API 方法。你可以用这个系统做很多事情,但是简化界面怎么样?为什么不添加一个接口对象来公开所有 API 方法的经过深思熟虑的子集?门面!

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-M79xCTVy-1689174005345)(D:\BaiduNetdiskWorkspace\Python技术\Python设计模式.assets\imagesurl=https%3A%2F%2Fuploads.toptal.io%2Fblog%2Fimage%2F126801%2Ftoptal-blog-image-1533728107288-9a9f20e7ad317bb61565c5e176327662.png)]

门面模式是一种优雅的 Python 设计模式。这是简化用户接口的完美方式。

门面模式的1个示例

class Car(object):

    def __init__(self):
        self._tyres = [Tyre('front_left'),
                             Tyre('front_right'),
                             Tyre('rear_left'),
                             Tyre('rear_right'), ]
        self._tank = Tank(70)

    def tyres_pressure(self):
        return [tyre.pressure for tyre in self._tyres]

    def fuel_level(self):
        return self._tank.level

没有惊喜,没有技巧,car类是一个门面,仅此而已。

适配器模式

如果门面模式用于简化接口,那么适配器就是改变接口。如同当系统期待1只鸭子时,你给它1只猪。

假设您有一种将信息记录到给定目标的工作方法。您的方法期望目标具有 write() 方法(例如,每个文件对象都有)。

def log(message, destination):
    destination.write('[{}] - {}'.format(datetime.now(), message))

我会说这是一个编写得很好的依赖注入方法,它允许极大的可扩展性。假设你想登录到某个UDP套接字而不是一个文件,你知道如何打开这个UDP套接字,但唯一的问题是套接字对象没有write()方法。您需要一个适配器!

import socket

class SocketWriter(object):

    def __init__(self, ip, port):
        self._socket = socket.socket(socket.AF_INET,
                                     socket.SOCK_DGRAM)
        self._ip = ip
        self._port = port

    def write(self, message):
        self._socket.send(message, (self._ip, self._port))

def log(message, destination):
    destination.write('[{}] - {}'.format(datetime.now(), message))

upd_logger = SocketWriter('1.2.3.4', '9999')
log('Something happened', upd_logger)

但是为什么我觉得适配器如此重要?当它与依赖注入有效结合时,它给了我们巨大的灵活性。当我们可以实现一个将新接口转换为众所周知的接口的适配器时,原因是适配器可以适应更多场景。

您还应该检查并掌握桥接和代理设计模式,因为它们与适配器相似。想想它们在 Python 中实现是多么容易,并考虑在项目中使用它们的不同方式。

装饰器模式

再次说,用python编程是多么幸运!装饰器真的很好,Python已经将它们集成到语言中。我最喜欢Python的是使用它教会我们使用最佳实践。这并不是说我们不必意识到最佳实践(特别是设计模式),但是对于Python,我觉得我正在遵循最佳实践。

装饰器模式是关于引入其他功能,特别是不使用继承来做到这一点。

那么,让我们看看如何在不使用内置 Python 功能的情况下装饰方法。这是一个简单的例子。

def autheticated_only(method):
    def decorated(*args, **kwargs):
        if check_authenticated(kwargs['user']):
            return method(*args, **kwargs )
        else:
            raise UnauthenticatedError
    return decorated


def authorized_only(method):
    def decorated(*args, **kwargs):
        if check_authorized(kwargs['user'], kwargs['action']):
            return method(*args, **kwargs)
        else:
            raise UnauthorizedError
    return decorated


@authorized_only
@authenticated_only
def execute(action, *args, **kwargs):
    return action()

本例中,你可以看到

现在 execute() 方法:

  • 易于阅读
  • 只做一件事(至少在查看代码时)
  • 通过两个装饰装饰器,就让execute()方法具备身份验证与授权两个功能。

而且两个装饰器可以复用于其它类似的函数。

装饰器不仅有函数装饰器,还有类装饰器等。另外python 标准库的 functools 模块提供很多有用的预定义好的内置装饰器功能。

结论

本文展示了使用Python的设计模式是多么自然和容易。

Python 是一种出色的语言,其本身已经内置了很多设计模式,在其它语言需要采用一套工具链来实现的设计模式,python可以很轻松地几行代码就完成。本文没有对各种设计模式做完整和正式描述的。如果你感兴趣,非常值得你进一步探索与尝试,不断提升编程水平。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-p0hPkOOG-1689174005347)(D:\BaiduNetdiskWorkspace\Python技术\Python设计模式.assets\python.png)]

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/747795.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于51单片机和proteus的水质水位检测系统

此系统是基于51单片机和proteus的仿真设计,功能如下: 1. LCD1602实时显示水质和水位状态。 2. 按键可设定水质检测阈值并通过LCD显示。 3. LED指示水质水位和系统运行状态。 4. 水质差超过阈值后自动启动排水泵。 5. 水位过低时自动启动进水泵。 6…

BI如何对接金蝶云星空数据源?奥威BI SaaS平台有绝招

传统BI部署时需要大量硬件和软件支持,而SaaS BI不仅不需要,还能让企业的数据可视化分析变得更加简单便捷,因此已经渐渐成为数字化时代的BI新趋势。那么,SaaS BI平台是如何快速接入数据完成数据可视化分析的?下面就以奥…

基于Python制作一个简单的文章搜索工具

这篇文章主要为大家详细介绍了如何基于Python制作一个简单的文章搜索工具,都是一些基础的应用,文中的示例代码讲解详细,感兴趣的可以了解一下 前言 今天,我无聊的时候做了一个搜索文章的软件,有没有更加的方便快捷不知…

R和python中dataframe读取方式总结

首先我有一个如图所示的文件 如果在python中读取 import pandas as pd df pd.read_csv("./6group_count.csv",index_col0) df而在R中读取的方式如下 df read.csv("./6group_count.csv",row.names 1)

springboot 集成Druid的监控数据库连接池的最佳实践

免费的chatgpt福利送上 http://124.220.104.235:31105/web/chatgpt 1.数据库连接池介绍 1.1JDBC数据库连接池的必要性 在使用开发基于数据库的web程序时,传统的模式基本是按以下步骤 在主程序(如servlet、beans)中建立数据库连接 进行sql…

Mybatis-plus通用查询方法封装

定义DTO package com.lbdj.user.service.dto;import com.lbdj.toolkit.utils.ReturnField; import com.lbdj.toolkit.utils.SFunction; import lombok.Data;/*** 用户DTO** author 作者* since 2023-06-27*/ Data public class LbdjUserDTO {/*** 主键*/private Long id;priva…

Oracle表设计

设计原则 为了建立冗余较小、结构合理的数据库,设计数据库时必须遵循一定的规 则。在关系型数据库中这种规则就称为范式。 范式是符合某一种设计要求的总结。 要想设计一个结构合理的关系型数据库,必须满足一定的范式。在实际开发中最为 常见的设计范式…

Auto.js 填充布局 layout_weight=“1“

当我在编写界面布局时&#xff0c;遇到了一个需求&#xff1a; 顶部和底部有按钮&#xff0c;而中间部分需要填满剩余空间且高度未知。 我通过使用layout_weight"1"完美解决我的问题&#xff0c;在这里记录一下。 "ui"; ui.layout(<vertical><te…

STM32——关于GPIO口的输出方式和输入方式

在STM32中&#xff0c;我们会要使用程序来对I/O口进行控制&#xff0c;当我们使用I/O口时&#xff0c;我们就需要知道在程序中我们需要这个I/O口来实现什么功能&#xff0c;是输入还是输出。 1、使用输出模式 I/O口常用的输出方式有推挽输出和开漏输出。 &#xff08;1&#…

回归预测 | MATLAB实现WOA-CNN-GRU鲸鱼算法优化卷积门控循环单元多输入单输出回归预测

回归预测 | MATLAB实现WOA-CNN-GRU鲸鱼算法优化卷积门控循环单元多输入单输出回归预测 目录 回归预测 | MATLAB实现WOA-CNN-GRU鲸鱼算法优化卷积门控循环单元多输入单输出回归预测预测效果基本介绍模型描述程序设计参考资料 预测效果 基本介绍 回归预测 | MATLAB实现WOA-CNN-GR…

驱动day5

驱动程序 #include <linux/init.h> #include <linux/module.h> #include<linux/fs.h> #include<linux/device.h> #include<linux/cdev.h> #include<linux/slab.h> #include<linux/uaccess.h> #include<linux/of.h> #include&…

11.4.2:DotImage SDK 基于web的扫描功能 cRACK

包含&#xff1a; DDotImage Document ImagingPDF Reader w/ Text ExtractionWingScan with eVRSOffice ReaderDotPDFBarcode Reading and WritingOCR Engines DotImage SDK WingScan 亮点&#xff0c;&#xff0c;WEB WingScan附带了一个简单的HTML5/JavaScript文档查看器…

Postgresql优化器如何使用列统计信息?

对pg_statistic表的查询都是走syscache的&#xff0c;要找到所有使用列统计信息地方&#xff0c;遍历系统表索引即可 enum SysCacheIdentifier {...STATEXTDATASTXOID,STATEXTNAMENSP,STATEXTOID,STATRELATTINH,... }下面是最常用的STATRELATTINH索引场景&#xff0c;即 Sear…

小奇猫物语之产品经理篇(2)

小奇猫物语之产品经理篇&#xff08;2&#xff09; 喵喵提示&#xff1a;小奇的产品经理篇&#xff08;2&#xff09;来咯&#xff0c;预告一下&#xff0c;前面几篇主要是讲产品经理的思维模式以及怎样去从一个学生思维转变成一个能带领一个项目的产品经理思维&#xff0c;所…

DolphinDB 与通联数据达成合作,构建快捷高效的一站式行情数据服务

在此前发布的多篇教程中&#xff0c;我们为大家展示了 DolphinDB 如何为因子投研、实时计算等业务场景加速&#xff0c;并进行了手把手教学&#xff0c;比如&#xff1a; 对接极速行情&#xff0c;真的很简单…… 又比如&#xff1a; 自己动手&#xff0c;搭一套行情回放系统…

Vue 路由跳转

文章目录 前言路由基础子路由路由传参query 传参 path静态传参动态传参 params 传参 name 编程式路由利用JS实现路由跳转 router 路由守卫 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; views里面放的是视图子组件&#xff08;首页、商家列表、商品列…

MySQL(九):MySQL语法-高级

MySQL语法-高级 LIMITLIKEASCREATE UNIQUE INDEX、DROP INDEXCREATE VIEW、DROP VIEWGROUP BYHAVINGMYSQL - JOININNER JOIN、JOINLEFT JOIN、LEFT OUTER JOINRIGHT JOIN、RIGHT OUTER JOINLEFT JOIN ... WHERE ...RIIGHT JOIN ... WHERE ... TRUNCATE TABLEINSERT INTO 表1 (列…

信创电子档案管理单机版系统之档案利用的功能介绍

专久智能信创电子档案管理单机版系统的档案利用&#xff0c;包括对电子档案的网上利用和对档案实体的借阅两种方式&#xff0c;用户对档案的利用都是通过 WEB 方式的档案网站实现的。 用户可以根据系统赋予的权限对电子档案目录进行检索查询&#xff0c;找到所需的档案目录&…

图像分类——图像增强方法

目录 常用的图像增强方法tf.image进行图像增强翻转和裁剪颜色变换 使用ImageDataGenerator(进行图像增强) 常用的图像增强方法 tf.image进行图像增强 离线实现 import tensorflow as tf import matplotlib.pyplot as plt import numpy as npcatplt.imread(./cat.jpg) plt.ims…

【后端面经-架构】RabbitMQ简介

【后端面经-架构】RabbitMQ简介 1. MQ介绍2. RabbitMQ2.1 简介2.2 架构&#xff1a;组件解释2.3 特点2.4 优缺点 面试模拟参考资料 1. MQ介绍 MQ&#xff08;Message Queue&#xff09;用于在应用程序之间相互通信&#xff0c;在消息中发送数据进行通信&#xff0c;而不需要特…