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

3、DRF实战总结:基于类的视图APIView, GenericAPIView和GenericViewSet视图集(附源码)

前面介绍了什么是符合RESTful规范的API接口,以及使用了基于函数的视图(FBV)编写了对文章进行增删查改的API。在本篇文章将使用基于类的视图(Class-based View, CBV)重写之前的接口。

参考:

1、Django开发总结:Django MVT与MVC设计模式,请求过程与代码示例(附源码)_SteveRocket的博客-CSDN博客如果要开发一个好的网站或网络应用,就必需了解经典的软件开发所遵循的MVC 设计模式。本篇详细总结软件开发所遵循的MVC (Model-View-Controller, 模型-视图-控制器) 设计模式以及Django的MVT设计模式(Model-View-Template)如何遵循这种设计理念。Django Model(模型), URL(链接), View(视图) 和Template(模板)又是如何遵循MVC软件设计模式的。https://blog.csdn.net/zhouruifu2015/article/details/129648966

https://blog.csdn.net/zhouruifu2015/article/details/129761750icon-default.png?t=N2N8https://blog.csdn.net/zhouruifu2015/article/details/129761750

工程路径及APP:django_framework\django_rest_framework_pro\drf_pro

基于类的视图(CBV)

一个中大型的Web项目代码量通常是非常大的,如果全部使用函数视图写,那么代码的复用率是非常低的。而使用类视图,就可以有效的提高代码复用,因为类是可以被继承的,可以拓展的。特别是将一些可以共用的功能抽象成Mixin类或基类后可以减少重复造轮子的工作。

DRF推荐使用基于类的视图(CBV)来开发API, 并提供了4种开发CBV开发模式。

  • 使用基础APIView类
  • 使用Mixins类和GenericAPI类混配
  • 使用通用视图generics.*类, 比如generics.ListCreateAPIView
  • 使用视图集ViewSet和ModelViewSet

类视图的比较

DRF提供了4种编写CBV类API的方式,到底哪种CBV开发模式更好? 答案是各有利弊

  • 基础的API类可读性最高,代码最多,灵活性最高。当需要对API行为进行个性化定制时,建议使用这种方式。
  • 通用generics.*类可读性好,代码适中,灵活性较高。当需要对一个模型进行标准的增删查改全部或部分操作时建议使用这种方式。
  • 使用视图集viewset: 可读性较低,代码最少,灵活性最低。当需要对一个模型进行标准的增删查改的全部操作且不需定制API行为时建议使用这种方式。
  • mixin类和GenericAPI的混用,这个和generics.*类没什么区别,不看也罢。

Django视图集viewset代码最少,但这是以牺牲了代码的可读性为代价的,因为它对代码进行了高度地抽象化。另外urls由router生成,不如自己手动配置的清楚。

使用CBV类可以简化代码,增加代码重用,在很多情况下还需要重写父类的方法,比如get_queryset, get_serializer_class方法以实现特殊的功能。

使用APIView

DRF的APIView类继承了Django自带的View类, 一样可以按请求方法调用不同的处理函数,比如get方法处理GET请求,post方法处理POST请求。不过DRF的APIView要强大得多。它不仅支持更多请求方法,而且对Django的request对象进行了封装,可以使用request.data获取用户通过POST, PUT和PATCH方法发过来的数据,而且支持插拔式地配置认证、权限和限流类

使用APIView类重写之前的函数视图

# drf_pro/views.py

# 基础APIView类
from rest_framework import status
from rest_framework.views import APIView
from rest_framework.response import Response
from django.http import Http404
from .models import Article
from .serializers import ArticleSerializer2class ArticleList(APIView):"""List all articles, or create a new article."""def get(self, request, format=None):articles = Article.objects.all()serializer = ArticleSerializer2(articles, many=True)return Response(serializer.data)def post(self, request, format=None):serializer = ArticleSerializer2(data=request.data)if serializer.is_valid():# 注意:手动将request.user与author绑定serializer.save(author=request.user)return Response(serializer.data, status=status.HTTP_201_CREATED)return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)class ArticleDetail(APIView):"""Retrieve, update or delete an article instance."""def get_object(self, pk):try:return Article.objects.get(pk=pk)except Article.DoesNotExist:raise Http404def get(self, request, pk, format=None):article = self.get_object(pk)serializer = ArticleSerializer2(article)return Response(serializer.data)def put(self, request, pk, format=None):article = self.get_object(pk)serializer = ArticleSerializer2(instance=article, data=request.data)if serializer.is_valid():serializer.save()return Response(serializer.data)return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)def delete(self, request, pk, format=None):article = self.get_object(pk)article.delete()return Response(status=status.HTTP_204_NO_CONTENT)

或许已经注意到,这段代码跟之前基于函数的视图差别并不大。最大不同的是不需要在对用户的请求方法进行判断。该视图可以自动将不同请求转发到相应处理方法,逻辑上也更清晰。

修改url配置, 让其指向新的基于类的视图

# drf_pro/urls.py

from django.urls import re_path
from rest_framework.urlpatterns import format_suffix_patterns
from . import views, views_cbvurlpatterns = [re_path(r'^articles/$', views.article_list),re_path(r'^articles/(?P<pk>[0-9]+)$', views.article_detail),# 基于类的视图re_path(r'^articles_cbv/$', views_cbv.ArticleList.as_view()),# http://localhost/v1/articles_cbv/re_path(r'^articles_cbv/(?P<pk>[0-9]+)$', views_cbv.ArticleDetail.as_view()),
]urlpatterns = format_suffix_patterns(urlpatterns=urlpatterns)

发送GET请求到v1/articles_cbv/将看到跟上文一样的效果

发送GET请求到v1/articles_cbv/4/ 根据id查看详情

使用Mixin类和GenericAPI类混配

使用基础APIView类并没有大量简化代码,与增删改查操作相关的代码包括返回内容对所有模型几乎都是一样的。比如现在需要对文章类别Category模型也进行序列化和反序列化,只需要复制Article视图代码,将Article模型改成Category模型, 序列化类由ArticleSeralizer类改成CategorySerializer类就行了。

对于这些通用的增删改查行为,DRF已经提供了相应的Mixin类。Mixin类可与generics.GenericAPI类联用,灵活组合成所需要的视图。

使用Mixin类和generics.GenericAPI类重写的类视图

# drf_pro/views.py

# 使用Mixin类和generics.GenericAPI类重写的类视图
from rest_framework import mixins
from rest_framework import generics
class ArticleList2(mixins.ListModelMixin, mixins.CreateModelMixin, generics.GenericAPIView):"""GenericAPIView 类继承了APIView类,提供了基础的API视图。"""queryset = Article.objects.all()serializer_class = ArticleSerializer2def get(self, request, *args, **kwargs):return self.list(request, *args, **kwargs)def post(self, reqeust, *args, **kwargs):return self.create(reqeust, *args, **kwargs)

GenericAPIView 类继承了APIView类,提供了基础的API视图。它对用户请求进行了转发,并对Django自带的request对象进行了封装。不过它比APIView类更强大,因为它还可以通过queryset和serializer_class属性指定需要序列化与反序列化的模型或queryset及所用到的序列化器类。

这里的 ListModelMixin 和 CreateModelMixin类则分别引入了.list() 和 .create() 方法,当用户发送get请求时调用Mixin提供的list()方法,将指定queryset序列化后输出,发送post请求时调用Mixin提供的create()方法,创建新的实例对象。

DRF还提供RetrieveModelMixin, UpdateModelMixin和DestroyModelMixin类,实现了对单个对象实例的查、改和删操作,如下所示:

class ArticleDetail2(mixins.RetrieveModelMixin, mixins.UpdateModelMixin, mixins.DestroyModelMixin, generics.GenericAPIView):queryset = Article.objects.all()serializer_class = ArticleSerializer2def get(self, request, *args, **kwargs):return self.retrieve(request, *args, **kwargs)def put(self, request, *args, **kwargs):return self.update(request, *args, **kwargs)def delete(self, request, *args, **kwargs):return self.destroy(request, *args, **kwargs)

已经有了get, post, delete等方法,为什么mixin类引入的方法要以list, create, retrieve, destroy方法命名?

因为请求方法不如操作名字清晰,比如get方法同时对应了获取对象列表和单个对象两种操作,使用list和retrieve方法后则很容易区分。另外post方法接受用户发过来的请求数据后,有时只需转发不需要创建模型对象实例,所以post方法不能简单等于create方法。

新的ArticleList视图类看似正确,但其实还有一个问题。 定义的序列化器ArticleSeralizer类并不包含author这个字段的,这是因为希望在创建article实例时将author与request.user进行手动绑定。在前面的例子中使用serializer.save(author=request.user)这一方法进行手动绑定。

现在使用mixin类后的操作方法是重写perform_create方法,如下所示:

class ArticleList2(mixins.ListModelMixin, mixins.CreateModelMixin, generics.GenericAPIView):"""GenericAPIView 类继承了APIView类,提供了基础的API视图。"""queryset = Article.objects.all()serializer_class = ArticleSerializer2def get(self, request, *args, **kwargs):return self.list(request, *args, **kwargs)def post(self, reqeust, *args, **kwargs):return self.create(reqeust, *args, **kwargs)# 将request.user与author绑定def perform_create(self, serializer):serializer.save(author=self.request.user)

perform_create这个钩子函数是CreateModelMixin类自带的,用于执行创建对象时需要执行的其它方法,比如发送邮件等功能,有点类似于Django的信号。类似的钩子函数还有UpdateModelMixin提供的.perform_update方法和DestroyModelMixin提供的.perform_destroy方法。

urls.py中新定义URL

# 使用Mixin类和generics.GenericAPI类重写的类视图
re_path(r'^articles_cbv2/$', views_cbv.ArticleList2.as_view()),
re_path(r'^articles_cbv2/(?P<pk>[0-9]+)/$', views_cbv.ArticleDetail2.as_view()),

浏览器请求文章列表

浏览器请求单篇文章详情

使用通用视图generics.*

将Mixin类和GenericAPI类混配,已经帮助减少了一些代码,但还可以做得更好,比如将get请求与mixin提供的list方法进行绑定感觉有些多余。DRF还提供了一套常用的将 Mixin 类与 GenericAPI类已经组合好了的视图,开箱即用,可以进一步简化的代码,如下所示:

from rest_framework import generics
class ArticleList3(generics.ListCreateAPIView):queryset = Article.objects.all()serializer_class = ArticleSerializer2# 将request.user与author绑定def perform_create(self, serializer):serializer.save(author=self.request.user)class ArticleDetail3(generics.RetrieveUpdateAPIView):queryset = Article.objects.all()serializer_class = ArticleSerializer2

generics.ListCreateAPIView类支持List、Create两种视图功能,分别对应GET和POST请求。generics.RetrieveUpdateDestroyAPIView支持Retrieve、Update、Destroy操作,其对应方法分别是GET、PUT和DELETE。

urls.py中新定义URL

# generic class-based views
re_path(r'articles_cbv3/$', views_cbv.ArticleList3.as_view()),
re_path(r'articles_cbv3/(?P<pk>[0-9]+)/$', views_cbv.ArticleDetail3.as_view()),


短短几行代码实现了所有想要的功能,代码更简洁,其它常用generics.*类视图还包括ListAPIView, RetrieveAPIView, RetrieveUpdateAPIView等等。

使用视图集(viewset)

使用通用视图generics.*类后视图代码已经大大简化,但是ArticleList和ArticleDetail两个类中queryset和serializer_class属性依然存在代码重复。使用视图集可以将两个类视图进一步合并,一次性提供List、Create、Retrieve、Update、Destroy这5种常见操作,这样queryset和seralizer_class属性也只需定义一次就好, 如下所示:

# drf_pro/views.py

# 视图集(viewset)
from rest_framework import viewsets
class ArticleViewSet(viewsets.ModelViewSet):# 用一个视图集替代ArticleList和ArticleDetail两个视图queryset = Article.objects.all()serializer_class = ArticleSerializer2# 自行添加,将request.user与author绑定def perform_create(self, serializer):serializer.save(author = self.request.user)

使用视图集后,需要使用DRF提供的路由router来分发urls,因为一个视图集现在对应多个urls的组合,而不像之前的一个url对应一个视图函数或一个视图类。

# drf_pro/urls.py

# 使用视图集后,需要使用DRF提供的路由router来分发urls,因为一个视图集现在对应多个urls的组合
from rest_framework.routers import DefaultRouterrouter = DefaultRouter()
router.register(r'articles4', viewset=views_cbv.ArticleViewSet)
urlpatterns = [
]
urlpatterns += router.urls

 

浏览器访问

一个视图集对应List、Create、Retrieve、Update、Destroy这5种操作。有时候只需要其中的几种操作,该如何实现?答案是在urls.py中指定方法映射即可,如下所示:

# drf_pro/urls.py

from django.urls import re_path
from rest_framework.urlpatterns import format_suffix_patterns
from . import views, views_cbv# 针对只需要其中的几种操作 使用方法映射
article_list = views_cbv.ArticleViewSet.as_view({'get': 'list','post': 'create'
})
article_detail = views_cbv.ArticleViewSet.as_view({'get': 'retrieve'  # 只处理get请求,获取单个记录
})urlpatterns = [# 视图集(viewset)re_path(r'^articles5/$', article_list),re_path(r'^articles5/(?P<pk>[0-9]+)/$', article_detail),
]

 

另外DRF还提供了ReadOnlyModelViewSet这个类,仅支持list和retrive这个操作。

代码示例:https://download.csdn.net/download/zhouruifu2015/87611605

输入才有输出,吸收才能吐纳。——码字不易

相关文章:

3、DRF实战总结:基于类的视图APIView, GenericAPIView和GenericViewSet视图集(附源码)

前面介绍了什么是符合RESTful规范的API接口&#xff0c;以及使用了基于函数的视图(FBV)编写了对文章进行增删查改的API。在本篇文章将使用基于类的视图(Class-based View, CBV)重写之前的接口。 参考&#xff1a; 1、Django开发总结&#xff1a;Django MVT与MVC设计模式&…...

AutoSAR PduR -AutoSAR PDU常用的使用方式【发送,接收,网关】

总目录链接==>> AutoSAR入门和实战系列总目录 @学前问答: AutoSAR PDU在哪里全局定义的? AutoSAR PDU涉及到哪些模块? AutoSAR PDU网关怎么使用? 文章目录 1 AutoSAR PDU发送2 AutoSAR PDU接收3 AutoSAR PDU网关转发4 答疑解析AutoSAR PDU 怎么样通过PduR 实现与其…...

瑟瑟发抖吧~OpenAI刚刚推出王炸——引入ChatGPT插件,开启AI新生态

5分钟学会使用ChatGPT 插件&#xff08;ChatGPT plugins&#xff09;——ChatGPT生态建设的开端ChatGPT插件是什么OpenAI最新官方blog资料表示&#xff0c;已经在ChatGPT中实现了对插件的初步支持。插件是专门为以安全为核心原则的语言模型设计的工具&#xff0c;可帮助ChatGPT…...

脉诊(切脉、诊脉、按脉、持脉)之法——入门篇

认识脉诊何谓脉诊&#xff1f;脉诊的渊源脉诊重要吗&#xff1f;脉诊确有其事&#xff0c;还是故弄玄虚&#xff1f;中医科学吗&#xff1f;如何脉诊&#xff1f;寸口脉诊法何谓脉诊&#xff1f; 所谓脉诊&#xff0c;就是通过把脉来诊断身体健康状况的一种必要手段。 …...

【十二天学java】day09常用api介绍

1.API 1.1API概述 什么是API API (Application Programming Interface) &#xff1a;应用程序编程接口 java中的API 指的就是 JDK 中提供的各种功能的 Java类&#xff0c;这些类将底层的实现封装了起来&#xff0c;我们不需要关心这些类是如何实现的&#xff0c;只需要学习这…...

软件测试 - 测试用例常见面试题

1.测试用例的要素测试用例是为了实施测试而向被测试的系统提供的一组集合, 这组集合包含 : 测试环境, 操作步骤, 测试数据, 预期结果等要素.例如 : 在 B 站输入框输入一个空格, 检查结果测试用例标题 : 输入框输入空格测试环境 : Windows 系统, 谷歌浏览器-版本 111.0.5563.65&…...

几种常见的API接口分页方案

文章目录1 概述2 分页方案2.1 基于偏移量2.2 基于游标3 重复数据处理3.1 基于时间3.2 基于热度3.3 基于推荐1 概述 列表是互联网产品中很常见的一种内容排列形式&#xff0c;而且列表的数据集往往成千上万&#xff0c;一次性返回全量数据集的场景几乎不存在&#xff0c;所以出…...

【Object 类的方法】

在 Java 中&#xff0c;所有类都继承了 Object 类&#xff0c;因此 Object 类中的方法可以在所有 Java 对象中使用。下面是 Object 类中的一些常用方法介绍&#xff1a; equals(Object obj): 用于判断两个对象是否相等。默认情况下&#xff0c;该方法比较的是两个对象的地址是…...

留用户、补内容,在线音乐暗战不停

在线音乐在人们的日常生活中扮演着愈发重要的角色&#xff0c;尤其是在面临巨大压力时&#xff0c;人们往往更倾向于通过倾听一段音乐来缓解内心的紧张与焦虑。而随着在线音乐用户数量的增长以及付费意愿的增强&#xff0c;在线音乐行业也实现了稳步发展。 经过多年的发展&…...

python--exec

在Python中&#xff0c;eval和exec都是用来执行动态代码的内置函数&#xff0c;但它们的作用和使用方式有所不同。 eval(): 将字符串作为Python表达式进行求值&#xff0c;并返回结果。 exec(): 将字符串作为Python语句进行执行&#xff0c;没有返回值。 eval()的使用范围通常限…...

干货分享!这6个高效率办公软件,总有一个值得你收藏!

分享6款高效办公软件&#xff0c;可以解决你很多需求&#xff0c;职场人一定要知道。每一款都是精挑细的&#xff0c;可能有的已经很大众了&#xff0c;但肯定还有小伙伴不知道&#xff0c;废话不多说&#xff0c;直接看&#xff01;&#xff01; 1、Flomo笔记&#xff1a;记录…...

代码随想录刷题-链表总结篇

文章目录链表理论基础单链表双链表循环链表其余知识点链表理论基础单链表双链表循环链表其余知识点移除链表元素习题我的解法虚拟头结点解法设计链表习题我的解法代码随想录代码反转链表习题双指针递归两两交换链表中的节点习题我的解法代码随想录解法删除链表的倒数第N个节点习…...

C++:指针:什么是野指针

野指针目录1&#xff1a;定义2&#xff1a;野指针常见情形2.1 &#xff1a;未初始化的野指针2.2 所指的对象已经消亡2.3 指针释放之后未置空3&#xff1a;避免野指针1&#xff1a;定义 指向非法的内存地址的指针叫做野指针&#xff08;Wild Pointer&#xff09;&#xff0c;也…...

一线大厂高并发Redis缓存架构

文章目录高并发缓存架构设计架构设计思路完整代码开发规范与优化建议键值设计命令使用客户端的使用扩展布隆过滤器redis的过期键的清除策略高并发缓存架构设计 架构设计思路 首先是一个基础的缓存架构&#xff0c;对于新增、修改操作set会对缓存更新&#xff0c;对于查询操作…...

剑指offer-二维数组中的查找

文章目录题目描述题解一 无脑暴力循环题解二 初始二分法&#x1f315;博客x主页&#xff1a;己不由心王道长&#x1f315;! &#x1f30e;文章说明&#xff1a;剑指offer-二维数组中的查找&#x1f30e; ✅系列专栏&#xff1a;剑指offer &#x1f334;本篇内容&#xff1a;对剑…...

怎么设计一个秒杀系统

1、系统部署 秒杀系统部署要单独区别开其他系统单独部署&#xff0c;这个系统的流量肯定很大&#xff0c;单独部署。数据库也要单独用一个部署的数据库或者集群&#xff0c;防止高并发导致整个网站不可用。 2、防止超卖 100个库存&#xff0c;1000个人买&#xff0c;要保证不…...

程序参数解析C/C++库 The Lean Mean C++ Option Parser

开发中我们经常使用程序参数&#xff0c;根据参数的不同来实现不同的功能。POSIX和GNU组织对此都制定了一些标准&#xff0c;为了我们程序更为通用标准&#xff0c;建议遵循这些行业内的规范&#xff0c;本文介绍的开源库The Lean Mean C Option Parser就可以很好满足我们的需求…...

Java中的深拷贝和浅拷贝

目录 &#x1f34e;引出拷贝 &#x1f34e;浅拷贝 &#x1f34e;深拷贝 &#x1f34e;总结 引出拷贝 现在有一个学生类和书包类&#xff0c;在学生类中有引用类型的书包变量&#xff1a; class SchoolBag {private String brand; //书包的品牌private int size; //书…...

大文件上传

上图就是大致的流程一、标题图片上传课程的标题图片Ajax发送请求到后端后端接收到图片使用IO流去保存图片&#xff0c;返回图片的信息对象JS回调函数接收对象通过$("元素id").val(值)&#xff0c;方式给页面form表达img标签src属性值&#xff0c;达到上传图片并回显二…...

Python每日一练(20230327)

目录 1. 最大矩形 &#x1f31f;&#x1f31f;&#x1f31f; 2. 反转链表 II &#x1f31f;&#x1f31f; 3. 单词接龙 II &#x1f31f;&#x1f31f;&#x1f31f; &#x1f31f; 每日一练刷题专栏 &#x1f31f; Golang每日一练 专栏 Python每日一练 专栏 C/C每日…...

unix/linux,sudo,其发展历程详细时间线、由来、历史背景

sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...

pikachu靶场通关笔记22-1 SQL注入05-1-insert注入(报错法)

目录 一、SQL注入 二、insert注入 三、报错型注入 四、updatexml函数 五、源码审计 六、insert渗透实战 1、渗透准备 2、获取数据库名database 3、获取表名table 4、获取列名column 5、获取字段 本系列为通过《pikachu靶场通关笔记》的SQL注入关卡(共10关&#xff0…...

全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比

目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec&#xff1f; IPsec VPN 5.1 IPsec传输模式&#xff08;Transport Mode&#xff09; 5.2 IPsec隧道模式&#xff08;Tunne…...

Mobile ALOHA全身模仿学习

一、题目 Mobile ALOHA&#xff1a;通过低成本全身远程操作学习双手移动操作 传统模仿学习&#xff08;Imitation Learning&#xff09;缺点&#xff1a;聚焦与桌面操作&#xff0c;缺乏通用任务所需的移动性和灵活性 本论文优点&#xff1a;&#xff08;1&#xff09;在ALOHA…...

Java 二维码

Java 二维码 **技术&#xff1a;**谷歌 ZXing 实现 首先添加依赖 <!-- 二维码依赖 --><dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.5.1</version></dependency><de…...

A2A JS SDK 完整教程:快速入门指南

目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库&#xff…...

Python Einops库:深度学习中的张量操作革命

Einops&#xff08;爱因斯坦操作库&#xff09;就像给张量操作戴上了一副"语义眼镜"——让你用人类能理解的方式告诉计算机如何操作多维数组。这个基于爱因斯坦求和约定的库&#xff0c;用类似自然语言的表达式替代了晦涩的API调用&#xff0c;彻底改变了深度学习工程…...

【 java 虚拟机知识 第一篇 】

目录 1.内存模型 1.1.JVM内存模型的介绍 1.2.堆和栈的区别 1.3.栈的存储细节 1.4.堆的部分 1.5.程序计数器的作用 1.6.方法区的内容 1.7.字符串池 1.8.引用类型 1.9.内存泄漏与内存溢出 1.10.会出现内存溢出的结构 1.内存模型 1.1.JVM内存模型的介绍 内存模型主要分…...

【LeetCode】3309. 连接二进制表示可形成的最大数值(递归|回溯|位运算)

LeetCode 3309. 连接二进制表示可形成的最大数值&#xff08;中等&#xff09; 题目描述解题思路Java代码 题目描述 题目链接&#xff1a;LeetCode 3309. 连接二进制表示可形成的最大数值&#xff08;中等&#xff09; 给你一个长度为 3 的整数数组 nums。 现以某种顺序 连接…...

pycharm 设置环境出错

pycharm 设置环境出错 pycharm 新建项目&#xff0c;设置虚拟环境&#xff0c;出错 pycharm 出错 Cannot open Local Failed to start [powershell.exe, -NoExit, -ExecutionPolicy, Bypass, -File, C:\Program Files\JetBrains\PyCharm 2024.1.3\plugins\terminal\shell-int…...