当前位置: 首页 > news >正文

抽象,自定义函数,递归

6.1懒惰是一种美德

如果你 在一个地方编写了一些代码,但需要在另一个地方再次使用,该如何办呢?

假设你编写了一段代码,它计算一些斐波那契数(一种数列,其中每个数都是前两个数的和)。

现在的数列包含10个斐波那契数。

如果要使用这些数字做其他事情,该如何办呢?我们肯定不愿意再重新写一遍代码。我们可以让程序更抽象。要让前面的程序更抽象,可以像下面这样做:

大家可以看见,我在确定num后直接可以打印出fibs。其实如果把整体封装起来,就可以直接调用。

6.2抽象和结构 

抽象可节省人力,但实际上还有个更重要的优点:抽象是程序能够被人理解的关键所在。

人和计算机的差别在于,计算机本身喜欢具体而明确的指 令,但人通常不是这样的。

例如:如果你向人打听怎么去电影院,就不希望对方回答:“向前走10步,向左转90度,接着走5步,再向右转45度,然后走123步。”(这是计算机希望听见的)。“沿这条街往前走,看到过街天桥后走到马路对面,电影院就在你左边。”(这是人希望听见的)。这里的关键是你知道如何沿街往前走,也知道如何过天桥,因此不需要有关这些方面的具体说明。

组织计算机程序时,你也采取类似的方式。程序应非常抽象,如下载网页、计算使用频率、打印每个单词的使用频率。

看到这些代码,任何人都知道这个程序是做什么的。但是其中到底如何做,其中的细节会在其他地方给出。

6.3自定义函数

函数执行特定的操作并返回一个值,你可以调用它(调用时可能需要提供一些参数——放在圆括号中的内容)。一般而言,要判断某个对象是否可调用,可使用内置函数callable。

此时说明x是不可以调用的,y是可以的。(并非所有的函数都返回值)

函数是结构化编程的核心。那么如何定义函数呢?使用def(表示定义函数)语句。

上面两行是对于函数的简单定义,最下面是对函数的调用。

 那现在回到斐波那契数,如果编写一个函数,返回一个由斐波那契数组成的列表呢?

前5行都是对于斐波那契数整个函数的定义,最后一行是对其进行调用。

其实我们不难发现,除了def一直需要外,我们在每个定义def中都有一个return语句。return语 句用于从函数返回值(在前面的hello函数中,return语句的作用也是一样的)。

6.3.1给函数编写文档

要给函数编写文档,以确保其他人能够理解,可添加注释(以#打头的内容)。

放在函数开头的字符串称为文档字符串(docstring),将作为函数的一部分存储起来。

代码前三行是定义,其中包含了我们的注释。最后一行我们先是调用了下函数进行计算,同时也读取了函数定义的文档字符串。(注意 __doc__是函数的一个属性。)

特殊的内置函数help很有用。在交互式解释器中,可使用它获取有关函数的信息,其中包含函数的文档字符串。

6.3.2其实并不是函数的函数

数学意义上的函数总是返回根据参数计算得到的结果。在Python中,有些函数什么都不返回。

什么都不返回的函数不包含return语句,或者包含return语句,但没有在return后面指定值。

这里虽然包含了return,但是其实return部分没有返回任何值,只是为了结束语句(第二个打印的go没有打印出来)(这有点像在循环中使用break,但跳出的是函数)

6.4参数魔法

函数使用起来很简单,创建起来也不那么复杂,但要习惯参数的工作原理就不那么容易了。

6.4.1值从哪里来

定义函数时,你可能心存疑虑:参数的值是怎么来的呢?

编写函数旨在为当前程序(甚至其他程序)提供服务,你的职责是确保它在提供的参数正确时完成任务,并在参数不对时以显而易见的方式失败。参数通常不需要担心。

在def语句中,位于函数名后面的变量通常称为形参,而调用函数时提供的值称为实参。很多情况下我们会将实参称为值,以便将其与类似于变量的形参区分开来。

6.4.2我能修改参数吗

参数不过是变量而已,行为与你预期的完全相同。在函数内部给参数赋值对外部没有任何影响。

在try_to_change内,将新值赋给了参数n,但如你所见,这对变量name没有影响。说到底,这是一个完全不同的变量。

这样可能更加直观,在有返回值的情况下,在定义里面修改参数会导致返回值的变化,但是但是重要的是它不会去修改我们的name。变量n变了,但变量name没变。同样,在函数内部重新关联参数(即给它赋值)时,函数外部的变量不受影响(参数存储在局部作用域内)。

字符串(以及数和元组)是不可变的(immutable),这意味着你不能修改它们(即只能替换为新值)。因此这些类型作为参数没什么可说的。但如果参数为可变的数据结构(如列表)呢?

唉?例子也是在函数内修改了参数,为什么函数外部的names发生变化了?大家先看下面:

这样的情况大家应该都见过,将同一个列表赋给两个变量时,这两个变量将同时指向这个列表。就这么简单。

这就解释了为什么在函数外的结果被修改了。

要避免这样的结果,必须创建列表的副本。对序列执行切片操作时,返回的切片都是副本。因此,如果你创建覆盖整个列表的切片,得到的将是列表的副本。

此时就可以发现,n和names虽然内容相同,但是已经不是同一个列表了。 注意到参数n包含的是副本。

(1)为何要修改参数

在提高程序的抽象程度方面,使用函数来修改数据结构(如列表或字典)是一种不错的方式。

假设你要编写一个程序,让它存储姓名,并让用户能够根据名字、中间名或 姓找人。为此,你可能使用一个类似于下面的数据结构:

每个键下都存储了一个人员列表。在这个例子里,这些列表只包含作者。

现在,要获取中间名为Lie的人员名单,可像下面这样做:

但是,如你所见,将人员添加到这个数据结构中有点繁琐,在多个人的名字、中间名或姓相同时尤其如此,因为在这种情况下需要对存储在名字、中间名或姓下的列表进行扩展。

下面来添加我的妹妹,并假设我们不知道数据库中存储了什么内容。

storage['first']['Anne'] 在第一个代码的第二行给first键对应的‘Anne’键对应的值用my_sister添加,由于之前我们并没有对Anne的键对应相应的值,现在直接添加,形成的结果就是刚刚添加的。对于三行的Lie之前我们有设置过值,现在append一个,最后得到的结果就是第二个代码出现的结果。

可以想见,编写充斥着这种更新的大型程序时,代码将很快变得混乱不堪。

抽象的关键在于隐藏所有的更新细节,为此可使用函数。下面首先来创建一个初始化数据结构的函数。

你所见,这个函数承担了初始化职责,让代码的可读性高了很多。

接下来设计获取人员姓名的函数。

第一个代码就是获取设计人员姓名的函数。第二个代码最后就是对该函数的使用。

下面来编写将人员存储到数据结构中的函数。

运行一下:

如你所见,如果多个人的名字、中间名或姓相同,可同时获取这些人员。

(2)如果参数是不可变的

在很多语言中,经常需要给参数赋值并让这种修改影响函数外部的变量。在Python中,没法直接这样做,只能修改参数对象本身。

但是,如果参数不可变呢?没办法。在这种情况下,应从函数返回所有需要的值(如果需要返回多个值,就以元组的方式返回它们)。

这样没有进过修改参数

如果一定要修改参数,改变外部的值,可以把值放在列表中。

6.4.3关键字参数和默认值

有时候,参数的排列顺序可能难以记住,尤其是参数很多时。

但是当我们改成这样的时候参数的顺序就无关紧要了,但是名称变的很重要。

像这样使用名称指定的参数称为关键字参数,主要优点是有助于澄清各个参数的作用。

虽然这样做的输入量多些,但每个参数的作用清晰明了。另外,参数的顺序错了也没关系。

然而,关键字参数最大的优点在于,可以指定默认值。

像这样,设定完默认值后,调用时不提供它,也可以运行出来。

当然也可以提供默认值。提供1个或者2个都可以。

如你所见,这两个提供的值,其实还是按照位置进行分配的。那如何使用提供的name或者greeting。

还不止这些。你可结合使用位置参数和关键字参数,但必须先指定所有的位置参数,否则解释器将不知道它们是哪个参数(即不知道参数对应的位置)。通常不会结合位置参数和关键字参数。

大家可以自己看一下代码,思考一下与预期是否相同。

直接运行报错,因为name没有设定默认值。

6.4.4收集参数

有时候,允许用户提供任意数量的参数很有用。

每次只能存储一个数据太少了,如果可以同时存储多个数据就比较好:

为此,应允许用户提供任意数量的姓名。请尝试使用下面这样的函数定义:

这里好像只指定了一个参数,但它前面有一个星号。

看,我们引用这个定义,发现最终打印出的是一个元组,因为里面有一个逗号。那继续尝试是否可以打印出更多的项。

看出来,打印多个项目也是可以的。参数前面的星号将提供的所有值都放在一个元组中,也就是将这些值收集起来。这样的行我们在5.2.1节见过:赋值时带星号的变量收集多余的值。它收集的是列表而不是元组中多余的值,但除此之外,这两种用法很像。

和我们预期相同,第一个参数收集一个值(params),第二个参数由于有*号,所以收集剩余的值(1,2,3)。

这段代码,在第一个参数收集完第一个值,没有值了,所以第二个参数返回了一个空的元组。

那此时,我们可能会好奇,那如果说星号的参数在中间,它应该怎么判断剩余的元组呢?我们尝试一下:

星号不会收集管自己参数,如果不给z=6呢?

报错了。

星号不会收集关键字参数。如下。

正常来说,在参数title收集到Hmm...后,剩余内容被星号参数收集,但是事实上没有,因为提供了关键字了,星号不会收集关键字参数。

要收集关键字参数,可使用两个星号。

如你所见,这样得到的是一个字典而不是元组。

将以上的内容全部结合一下,位置,关键字,*,**

现在我们来解决最初的问题,如何在姓名存储示例中使用这种技术?解决方案如下:

6.4.5分配参数

前面介绍了如何将参数收集到元组和字典中,但用同样的两个运算符(*和**)也可执行相反的操作。与收集参数相反的操作是什么呢?假设有如下函数:

现在定义了一个相加的函数,但是给出的两个数据在一个元组里。现在就希望将这两个数据进行相加,但是定义中给的是两个参数。与收集参数相反的操作(不是收集参数,而是分配参数):

当然使用一个*可以,也可以使用两个**。可将字典中的值分配给关键字参数。如下:

大家看下面这一段代码:

对于函数with_stars,我在定义和调用它时都使用了星号,而对于函数without_stars,我在定义和调用它时都没有使用,但这两种做法的效果相同。

因此,只有在定义函数(允许可变数量的参数)或调用函数时(拆分字典或序列)使用, 星号才能发挥作用。

使用这些拆分运算符来传递参数很有用,因为这样无需操心参数个数之类的问题,如下所示:

6.5作用域

变量到底是什么呢?可将其视为指向值的名称。因此,执行赋值语句x = 1后,名称x指向值1。这几乎与使用字典时一样(字典中的键指向值),只是你使用的是“看不见”的字典。

有一个名为vars的内置函数,它返回这个不可见的字典:

警告 一般而言,不应修改vars返回的字典,因为根据Python官方文档的说法,这 样做的结果是不确定的。换而言之,可能得不到你想要的结果。

这种“看不见的字典”称为命名空间或作用域。那么有多少个命名空间呢?除全局作用域外,每个函数调用都将创建一个。

这个地方就有些疑问了,我调用foo了,foo函数内赋值语句x=42,为什么最终x没有变化,依然是1呢?

这是因为调用foo时创建了一个新的命名空间,供foo中的代码块使用。赋值语句x = 42是在这个内部作用域(局部命名空间)中执行的,不影响外部(全局)作用域内的x。在函数内使用的变量称为局部变量(与之相对的是全局变量)。参数类似于局部变量,因此参数与全局变量同名不会有任何问题。

简而言之,就是创建函数foo时,创建了新的命名空间,这个空间里(局部)的x值不会影响到全局作用域中的x值。因此局部变量与全局变量同名也没有问题。

读取全局变量的值通常不会有问题,但还是存在出现问题的可能性。

(1)“遮盖”的问题

如果有一个局部 变量或参数与你要访问的全局变量同名,就无法直接访问全局变量,因为它被局部变量遮住了。(其实就是在局部变量里面使用全局变量时,如果局部变量中有与全局同名的,系统不知道识别哪一个,而因为在定义里面,会先访问局部变量)

那我到底如何让函数里知道我要访问全局变量呢?使用global

看,此时函数里就访问到了全局变量的parameter。

还记得我们在6.5开始的时候,函数里面的值的赋值操作,并没有改变函数外的值。那如何改变呢?

重新关联全局变量(使其指向新值)是另一码事。在函数内部给变量赋值时,该变量默认为局部变量,除非你明确地告诉Python它是全局变量。当然还是使用global。

ok,大家知道了可以这样进行关联全局变量。大家可以思考一下为什么下面这个x还是1呢?

(2)作用域嵌套

Python函数可以嵌套,即可将一个函数放在另一个函数内。

嵌套通常用处不大,但有一个很突出的用途:使用一个函数来创建另一个函数。这意味着可像下面这样编写函数:

在这里,一个函数位于另一个函数中,且外面的函数返回里面的函数。也就是返回一个函数,而不是调用它。重要的是,返回的函数能够访问其定义所在的作用域。换而言之,它携带着自己所在的环境(和相关的局部变量)!

每当外部函数被调用时,都将重新定义内部的函数,而变量factor的值也可能不同。由于Python的嵌套作用域,可在内部函数中访问这个来自外部局部作用域(multiplier)的变量,如下所示:

第一句中的2其实就是multiplier的factor,double中的5,其实就是number。下面两个例子也是类似的。

像multiplyByFactor这样存储其所在作用域的函数称为闭包。

通常,不能给外部作用域内的变量赋值,但如果一定要这样做,可使用关键字nonlocal。这个关键字的用法与global很像,让你能够给外部作用域(非全局作用域)内的变量赋值。

6.6递归

你知道,函数可调用其他函数,但可能让你感到惊 讶的是,函数还可调用自己。

如果你以前没有遇到这种情况,可能想知道递归是什么意思。简单地说,递归意味着引用(这里是调用)自身。(其实完全没有必要明白递归的准确定义)

这就是一个递归式函数的定义,其实什么都没做,与“递归”定义一样傻。

从理论上说,这个程序将 不断运行下去,但每次调用函数时,都将消耗一些内存。因此函数调用次数达到一定的程 度(且之前的函数调用未返回)后,将耗尽所有的内存空间,导致程序终止并显示错误消 息“超过最大递归深度”。

这个函数中的递归称为无穷递归(就像以while True打头且不包含break和return语句的循环被称为无限循环一样),因为它从理论上说永远不会结束。

我们需要的是对我们有帮助的递归,通常包含两个部分:

基线条件(针对最小的问题):满足这种条件时函数将直接返回一个值。

递归条件:包含一个或多个调用,这些调用旨在解决问题的一部分。

6.6.1 阶乘与幂(经典案例)

首先,假设你要计算数字n的阶乘。n的阶乘为n × (n - 1) × (n - 2) × … × 1,在数学领域的用途非常广泛。

首先将result设置为n,再将其依次乘以1到n - 1的每个数字,最后返回result。但如果你愿意,可采取不同的做法。

ok,上面这个方法就一步步的进行计算,但我们也可以采用不同的方法。

①1的阶乘为1。

②对于大于1的数字n,其阶乘为n - 1的阶乘再乘以n。这与阶乘的定义相同。

再来看一个示例。假设你要计算幂,就像内置函数pow和运算符**所做的那样。要定义一个数字的整数次幂,有多种方式,但先来看一个简单的定义:power(x, n)(x的n次幂)是将数字x自乘n - 1次的结果,即将n个x相乘的结果。

同样,也可以将他改成递归式。

①对于任何数字x,power(x, 0)都为1。

②n>0时,power(x, n)为power(x, n-1)与x的乘积。

提示 如果函数或算法复杂难懂,在实现前用自己的话进行明确的定义将大有裨益。以这种“准编程语言”编写的程序通常称为伪代码。

那么使用递归有何意义呢?难道不能转而使用循环吗?答案是肯定的,而且在大多数情况下,使用循环的效率可能更高。然而,在很多情况下,使用递归的可读性更高,且有时要高得多,在你理解了函数的递归式定义时尤其如此。

6.6.2二分查找

例如,对方心里想着一个1~100的数字,你必须猜出是哪个。当然,猜100次肯定猜对,但最少需要猜多少次呢?实际上只需猜7次。首先问:“这个数字大于50吗?”如果答案是肯定的,再问:“这个数字大于75吗?”不断将可能的区间减半,直到猜对为止。你无需过多地思考就能成功。

这样的想法适用于众多其他不同的情形。

一个常见的问题是:指定的数字是否包含在已排序的序列中?如果包含,在什么位置?为解决这个问题,可采取同样的策略:“这个数字是否在序列中央的右边?”如果答案是否定的,再问:“它是否在序列的第二个四分之一区间内(左半部分的右边)?”依此类推。明确数字所处区间的上限和下限,并且每一个问题都将区间分成两半。

这里的关键是,这种算法自然而然地引出了递归式定义和实现。

①如果上限和下限相同,就说明它们都指向数字所在的位置,因此将这个数字返回。

②否则,找出区间的中间位置(上限和下限的平均值),再确定数字在左半部分还是右 半部分。然后在继续在数字所在的那部分中查找。

在这个递归案例中,关键在于元素是经过排序的。找出中间的元素后,只需将其与要查找的数字进行比较即可

当然,上面的代码有一个缺陷,在一我们通常不知道lower和upper(这两个值代表的是列表的下标)所有可以进行修改。

现在进行调用,看是否正确。

结果是正确的,但是你可能会好奇,明明对于列表,我们可以直接index查找,为什么要这样呢?

的确,index是可以的,但是效率太低了,前面说过,要在100个数字中找到指定的数字,只需问7次;但使用循环时,在最糟的情况下需要问100次。(大家看100好像没什么,事实上,在可观察到的宇宙中,包含的粒子数大约为10 87个。要找出其中的一个粒子,只需问大约290次!)

实际上,模块bisect提供了标准的二分查找实现。

相关文章:

抽象,自定义函数,递归

6.1懒惰是一种美德 如果你 在一个地方编写了一些代码,但需要在另一个地方再次使用,该如何办呢? 假设你编写了一段代码,它计算一些斐波那契数(一种数列,其中每个数都是前两个数的和)。 现在的…...

php设计模式之策略模式详解

策略模式(Strategy Pattern)是一种行为设计模式,它使你能在运行时改变对象的行为。在PHP中应用策略模式可以让你轻松地根据需要选择和交换算法或策略,而无需修改使用这些算法的代码。 策略模式的核心概念: 目的&…...

Android在不同层面增加应用

1 App 应用代码一般在开发者的项目目录下,packages/apps/YourApp/,比如app/src/main/java目录下 对于系统应用,源代码可能位于packages/apps/目录下,例如packages/apps/Settings。 用户安装的应用(从Google Play或其…...

【Pycharm】功能介绍

1.Code Reformat Code 格式化代码,可以帮助我们去自动调整空格等,根据python语法规范自动调整 2.Settings 1.创建py文件默认填充模版 3.读写py文件编码格式一致性 顶部代码指定的编码方式作用: 可以保证python2/3解释器在读取文件的时候按…...

安卓手机平板使用JuiceSSH无公网IP远程连接本地服务器详细流程

文章目录 前言1. Linux安装cpolar2. 创建公网SSH连接地址3. JuiceSSH公网远程连接4. 固定连接SSH公网地址5. SSH固定地址连接测试 前言 处于内网的虚拟机如何被外网访问呢?如何手机就能访问虚拟机呢? 本文就和大家分享一下如何使用 cpolarJuiceSSH 实现手机端远程连接Linux…...

告别冗长代码:Java Lambda 表达式如何简化你的编程

在现代软件开发中,高效和简洁的代码变得越来越重要。Java作为一门成熟而广泛使用的编程语言,一直在不断进化,以满足开发者的需求。Java 8的推出标志着一次重要的飞跃,其中最引人注目的特性之一便是Lambda表达式。 Lambda表达式为J…...

不同生成式AI模型的优缺点(GAN,VAE,FLOW)

不同生成式人工智能模型的优缺点 近年来,生成式 AI 模型因其能够创建新的原创内容而备受关注。这些模型旨在生成类似于给定训练数据集的数据,从而产生逼真且富有创意的输出。了解不同类型的生成式 AI 模型及其优缺点对于研究人员、开发人员和用户做出明…...

VMware ESXi 8.0U2c macOS Unlocker OEM BIOS 集成网卡驱动 Marvell AQC 网卡定制版

VMware ESXi 8.0U2c macOS Unlocker & OEM BIOS 集成网卡驱动 Marvell AQC 网卡定制版 VMware ESXi 8.0U2c macOS Unlocker & OEM BIOS 集成网卡驱动和 NVMe 驱动 (集成驱动版) 发布 ESXi 8.0U2 集成驱动版,在个人电脑上运行企业级工作负载 请访问原文链…...

SpringCloud Consul基础入门与使用实践总结

【1】Consul简介 官网地址:https://www.consul.io/intro/index.html 下载地址:https://www.consul.io/downloads.html 中文文档:https://www.springcloud.cc/spring-cloud-consul.html ① 基础概念 Consul 是一套开源的分布式服务发现和…...

pdf拆分成有图和无图的pdf(方便打印)

pdf拆分成有图和无图的pdf(方便打印) 原因 打印图片要彩印,每次都要手动弄,打印的时候很麻烦; 随着打印次数的增加,时间就越来越多 为解决此问题,使用python写一个exe解决这个问题 历程 找一个python的GUI界面找到 t…...

通用树查找算法

想要一个树形控件来显示数据,却发现Racket的GUI库竟然没有提供这个控件。既然没有,那就自己手搓一个吧。没想到,在做这个控件中竟然有了新发现! 树形控件有一个功能是查找树中指定的节点。这就是接下来的故事的起点。 1 找外援 不…...

Flutter 中的 TableCell 小部件:全面指南

Flutter 中的 TableCell 小部件:全面指南 Flutter 是一个功能强大的 UI 框架,由 Google 开发,允许开发者使用 Dart 语言构建跨平台的移动、Web 和桌面应用。在 Flutter 的丰富组件库中,TableCell 是一个用于创建表格单元格的组件…...

clickhouse学习笔记(一)入门与安装

目录 一 、入门 简介 核心特性包括 1.1 列式存储 1.2 原生压缩 1.3 向量化执行引擎 1.4 DBMS 功能 1.5 分布式处理 1.6 高吞吐写入能力 1.7 实时分析 1.8 SQL支持 1.9 高度可扩展 1.10 数据分区与线程级并行 1.11 应用场景 1.12 不适用场景 二、ClickHouse单机版…...

【JavaEE精炼宝库】多线程(4)深度理解死锁、内存可见性、volatile关键字、wait、notify

目录 一、死锁 1.1 出现死锁的常见场景: 1.2 产生死锁的后果: 1.3 如何避免死锁: 二、内存可见性 2.1 由内存可见性产生的经典案例: 2.2 volatile 关键字: 2.2.1 volatile 用法: 2.2.2 volatile 不…...

使用Ollama+OpenWebUI部署和使用Phi-3微软AI大模型完整指南

🏡作者主页: 点击! 🤖AI大模型部署与应用专栏:点击! ⏰️创作时间:2024年6月6日23点50分 🀄️文章质量:96分 欢迎来到Phi-3模型的奇妙世界!Phi-3是由微软…...

k8s的ci/cd实践之旅

书接上回k8s集群搭建完毕,来使用它强大的扩缩容能力帮我们进行应用的持续集成和持续部署,整体的机器规划如下: 1.192.168.8.156 搭建gitlab私服 docker pull gitlab/gitlab-ce:latest docker run --detach --hostname 192.168.8.156 --publ…...

笔记96:前馈控制 + 航向误差

1. 回顾 对于一个 系统而言,结构可以画作: 如果采用 这样的控制策略,结构可以画作:(这就是LQR控制) 使用LQR控制器,可以通过公式 和 构建一个完美的负反馈系统; a a 但是有上…...

延时任务工具类

自定义工具类 package com.sxfoundation.task;import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.task.TaskRejectedException; import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; import org.spri…...

springboot下载grpc编译文件,报错缺少protoc-gen-grpc-java:1.34.1:exe不存在

报错如图所示 [ERROR] Then, install it using the command: [ERROR] mvn install:install-file -DgroupIdio.grpc -DartifactIdprotoc-gen-grpc-java -Dversion1.34.1 -Dclassifierwindows-x86_64 -Dpackagingexe -Dfile/path/to/file [ERROR] [ERROR] Alternatively, if yo…...

【面试干货】 非关系型数据库(NoSQL)与 关系型数据库(RDBMS)的比较

【面试干货】 非关系型数据库(NoSQL)与 关系型数据库(RDBMS)的比较 一、引言二、非关系型数据库(NoSQL)2.1 优势 三、关系型数据库(RDBMS)3.1 优势 四、结论 💖The Begin…...

KubeSphere 容器平台高可用:环境搭建与可视化操作指南

Linux_k8s篇 欢迎来到Linux的世界,看笔记好好学多敲多打,每个人都是大神! 题目:KubeSphere 容器平台高可用:环境搭建与可视化操作指南 版本号: 1.0,0 作者: 老王要学习 日期: 2025.06.05 适用环境: Ubuntu22 文档说…...

测试微信模版消息推送

进入“开发接口管理”--“公众平台测试账号”,无需申请公众账号、可在测试账号中体验并测试微信公众平台所有高级接口。 获取access_token: 自定义模版消息: 关注测试号:扫二维码关注测试号。 发送模版消息: import requests da…...

基于距离变化能量开销动态调整的WSN低功耗拓扑控制开销算法matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.算法仿真参数 5.算法理论概述 6.参考文献 7.完整程序 1.程序功能描述 通过动态调整节点通信的能量开销,平衡网络负载,延长WSN生命周期。具体通过建立基于距离的能量消耗模型&am…...

FastAPI 教程:从入门到实践

FastAPI 是一个现代、快速(高性能)的 Web 框架,用于构建 API,支持 Python 3.6。它基于标准 Python 类型提示,易于学习且功能强大。以下是一个完整的 FastAPI 入门教程,涵盖从环境搭建到创建并运行一个简单的…...

Golang dig框架与GraphQL的完美结合

将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用,可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器,能够帮助开发者更好地管理复杂的依赖关系,而 GraphQL 则是一种用于 API 的查询语言,能够提…...

Linux-07 ubuntu 的 chrome 启动不了

文章目录 问题原因解决步骤一、卸载旧版chrome二、重新安装chorme三、启动不了,报错如下四、启动不了,解决如下 总结 问题原因 在应用中可以看到chrome,但是打不开(说明:原来的ubuntu系统出问题了,这个是备用的硬盘&a…...

ABAP设计模式之---“简单设计原则(Simple Design)”

“Simple Design”(简单设计)是软件开发中的一个重要理念,倡导以最简单的方式实现软件功能,以确保代码清晰易懂、易维护,并在项目需求变化时能够快速适应。 其核心目标是避免复杂和过度设计,遵循“让事情保…...

C++.OpenGL (14/64)多光源(Multiple Lights)

多光源(Multiple Lights) 多光源渲染技术概览 #mermaid-svg-3L5e5gGn76TNh7Lq {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-3L5e5gGn76TNh7Lq .error-icon{fill:#552222;}#mermaid-svg-3L5e5gGn76TNh7Lq .erro…...

LangChain知识库管理后端接口:数据库操作详解—— 构建本地知识库系统的基础《二》

这段 Python 代码是一个完整的 知识库数据库操作模块,用于对本地知识库系统中的知识库进行增删改查(CRUD)操作。它基于 SQLAlchemy ORM 框架 和一个自定义的装饰器 with_session 实现数据库会话管理。 📘 一、整体功能概述 该模块…...

【Android】Android 开发 ADB 常用指令

查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...