一. 前言

Django REST framwork 提供的视图的主要作用

1. 控制序列化器的执行(检验、保存、转换数据)
2. 控制数据库查询的执行

二. 两个视图基类

两个视图基类: APIView, GenericAPIView,涉及到数据库和序列化类的操作,尽量用GenericAPIView

1. APIView

继承django原生View,重写方法,去掉csrf验证,用自己的dispatch

models.py
class Book(models.Model):
title = models.CharField(max_length=32)
price = models.DecimalField(max_digits=6, decimal_places=2)
publish = models.CharField(max_length=32) def __str__(self):
return self.title
ser.py
from rest_framework import serializers
from app01.models import Book class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book
fields = '__all__'
urls.py
# 基于APIView
path('books/', views.BooksView.as_view()),
path('book/<int:pk>/', views.BookView.as_view()),
views.py
class BooksView(APIView):
# 查询多条数据
def get(self, request):
my_dic = MyDic()
query_books = models.Book.objects.all()
books_ser = BookSerializer(query_books, many=True)
my_dic.data = books_ser.data
return Response(my_dic.get_dic) # 新增多条数据
def post(self, request):
my_dic = MyDic()
books_ser = BookSerializer(data=request.data)
if books_ser.is_valid():
# 继承的ModelSerializers,不需要重写create方法
books_ser.save()
my_dic.data = books_ser.data
print(books_ser.data)
else:
my_dic.status = 300
my_dic.msg = '校验不通过'
my_dic.data = books_ser.errors
return Response(my_dic.get_dic) class BookView(APIView):
# 获取一条数据
def get(self, request, pk):
my_dic = MyDic()
book_obj = models.Book.objects.filter(pk=pk).first()
book_ser = BookSerializer(book_obj)
my_dic.data = book_ser.data
return Response(my_dic.get_dic) # 修改数据
def put(self, request, pk):
my_dic = MyDic()
book_obj = models.Book.objects.filter(pk=pk).first()
book_ser = BookSerializer(instance=book_obj, data=request.data)
if book_ser.is_valid():
# 序列化器继承ModelSerializer,不用重写update方法
book_ser.save()
my_dic.data = book_ser.data
else:
my_dic.status = 200
my_dic.msg = '校验未通过'
my_dic.data = book_ser.errors
return Response(my_dic.get_dic) def delete(self,pk):
my_dic = MyDic()
models.Book.objects.filter(pk=pk).first()
my_dic.msg = '删除成功'
return Response(my_dic.get_dic)
总结
1. 继承关系: APIView继承View
2. APIView基于View的拓展:
APIView重写了View的dispatch方法, 在该方法中实现了实现了一下功能:
1) 对来的原生请求对象request进行了封装.
2) 提供了对包装过后的请求对象的三段认证: 认证, 权限控制, 频率控制
3) 重写了View中通过本次请求的方式动态的反射到自定义继承APIView类实例化的对象中定义的请求方法
4) 使用异常处理处理2,3步骤中的异常
5) 处理完毕异常以后使用drf的response对象对请求响应
3. 针对路由配置
路由中的有名分组必须指定pk, 视图中使用必须使用相同的关键字参数接受

2. GenericAPIView

GenericAPIView是继承APIView,解决不同的序列化器 ,重复写相同代码的问题,比如有两个序列化器BookSerializer和PublishSerializer,

只需要改动queryset = models.Book.objects.all()和serializer_class = BookSerializer,其他都可以复制。

models.py
from django.db import models

# Create your models here.
class Book(models.Model):
name = models.CharField(max_length=32, null=True)
price = models.DecimalField(max_digits=8, decimal_places=2, null=True)
author = models.CharField(max_length=32, null=True)
publish = models.CharField(max_length=32, null=True)
publish_time = models.DateTimeField(auto_now_add=True)
serializer.py 自定义序列化.py文件
from rest_framework import serializers
from .models import Book class BookModelSerializer(serializers.ModelSerializer):
class Meta:
model = Book
fields = '__all__'
# exclude = ('id', )
# exclude = ['id']
extra_kwargs = {
# 'price': {'write_only': True}
}
read_only_fields = ['id', ]
# 该方式在drf3.2版本以后就被弃用了, 使用ModelSerializer现在使用的的extra_kwargs
# write_only_fields = []
views.py
# 基于GenericaAPIView
from rest_framework.generics import GenericAPIView class Books1View(GenericAPIView):
# queryset要传query对象,查询了所有的图书
queryset = models.Book.objects.all()
# serializer_class使用那个序列化类序列化这堆数据
serializer_class = BookSerializer def get(self, request):
my_dic = MyDic()
query_books = self.get_queryset()
books_ser = self.get_serializer(query_books, many=True)
my_dic.data = books_ser.data
return Response(my_dic.get_dic) # 新增多条数据
def post(self, request):
my_dic = MyDic()
books_ser = self.get_serializer(data=request.data)
if books_ser.is_valid():
# 继承的ModelSerializers,不需要重写create方法
books_ser.save()
my_dic.data = books_ser.data
print(books_ser.data)
else:
my_dic.status = 300
my_dic.msg = '校验不通过'
my_dic.data = books_ser.errors
return Response(my_dic.get_dic) class Book1View(GenericAPIView):
queryset = models.Book.objects.all()
serializer_class = BookSerializer # 获取一条数据
def get(self, request, pk):
my_dic = MyDic()
book_obj = self.get_object()
book_ser = self.get_serializer(book_obj)
my_dic.data = book_ser.data
return Response(my_dic.get_dic) # 修改数据
def put(self, request, pk):
my_dic = MyDic()
book_obj = self.get_object()
book_ser = self.get_serializer(instance=book_obj, data=request.data)
if book_ser.is_valid():
# 序列化器继承ModelSerializer,不用重写update方法
book_ser.save()
my_dic.data = book_ser.data
else:
my_dic.status = 200
my_dic.msg = '校验未通过'
my_dic.data = book_ser.errors
return Response(my_dic.get_dic) def delete(self, request, pk):
my_dic = MyDic()
self.get_object().delete()
my_dic.msg = '删除成功'
return Response(my_dic.get_dic)
urls.py
# 基于GenericaAPIView
path('books1/', views.Books1View.as_view()),
path('book1/<int:pk>/', views.Book1View.as_view()),
GenericAPIView提供的三种方法的源码分析
# 1. self.get_queryset
def get_queryset(self):
# 1) 断言继承GenericAPIView的视图类实例化的对象时候有queryset对象
'''
如果没有: 那么断言成功抛出异常
如果有: 那么将会继续往下执行
因此为什么视图类中要为类新增一个queryset属性的原因就明白了
'''
assert self.queryset is not None, (
"'%s' should either include a `queryset` attribute, "
"or override the `get_queryset()` method."
% self.__class__.__name__
)
# 2) 由自定义视图类实例化出来的对象获取类中定义的queryset对象. 进行判断
''''
如果我们自定义视图类中书写的属性是queryset对象, 那么就会帮我们自动.all(). 因此我们可以不用点all了.
如果不是, 那么就直接返回数据对象
'''
queryset = self.queryset
if isinstance(queryset, QuerySet):
# Ensure queryset is re-evaluated on each request.
queryset = queryset.all()
return queryset # 2. self.get_serializer
def get_serializer(self, *args, **kwargs):
# 1) 获取继承GenericAPIView视图类实例化对象中找get_serializer_class
'''
def get_serializer_class(self):
# ① 断言继承GenericAPIVIew的自定义视图类实例化出来的对象中serializer_class时候为None
'''
为None断言成功, 抛出指定异常
不为None断言失败, 继续往下执行
'''
assert self.serializer_class is not None, (
"'%s' should either include a `serializer_class` attribute, "
"or override the `get_serializer_class()` method."
% self.__class__.__name__
)
# ② 发现本质就是获取视图类中定义的serializer_class序列化器类, 因此从这里我们就明白为什么视图类中要写序列化器类了.
return self.serializer_class
'''
# 2) get_serializer_class方法就是获取到了我们自定义视图类中定义的serializer_classes属性
serializer_class = self.get_serializer_class()
# 3) 内部就是return, 获取我们自定义视图类中的上下文一些信息
'''
def get_serializer_context(self):
return {
'request': self.request,
'format': self.format_kwarg,
'view': self
}
'''
kwargs['context'] = self.get_serializer_context()
# 4) 这里的serializer_class就是自定义视图类中的类属性, 通过类属性调用传值
return serializer_class(*args, **kwargs) # 3. self.get_object
def get_object(self):
# 1) 执行过滤操作, 默认没有配置过滤类. 因此queryset还是queryset
queryset = self.filter_queryset(self.get_queryset()) # 2) 运用短路运算, lookup_url_kwarg默认就是None, lookup_field默认就是pk, 因此返回值就是pk
'''
提示: 继承GenericAPIView的自定义视图类中没有定义以下参数. 默认使用的是GenericAPIView类中配置的
lookup_field = 'pk'
lookup_url_kwarg = None
'''
lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field # 3) 断言刚刚的pk时候在self.kwargs中
'''
查找顺序: 视图对象 -> 视图类 -> GenericAPIView -> APIView -> dispatch.
kwargs就是路由匹配来了, 走到APIVIew中的dispatch方法中将传入的关键字参数形式的key:value对到kwargs字典中,
再存到的对象当中, 直至此刻拿出来进行判断.
本质就是必须安装关键字pk=xxx的形式传参, 路由中必须指定又名分组pk, 视图中必须指定接受的关键字参数是pk
'''
assert lookup_url_kwarg in self.kwargs, (
'Expected view %s to be called with a URL keyword argument '
'named "%s". Fix your URL conf, or set the `.lookup_field` '
'attribute on the view correctly.' %
(self.__class__.__name__, lookup_url_kwarg)
)
# 4) 这里就是获取默认定义lookup_field充当字典的key, 又从self.kwargs这个dispatch方法就赋值的字典中, 将通过key取值, lookup_url_kwarg就是第2步分析出来的值
filter_kwargs = {self.lookup_field: self.kwargs[lookup_url_kwarg]}
# 5) get_object_or_404的功能就是获取对象 或者 抛出抛出404异常
'''
**filter_kwargs就是步骤4的字典. 字典的结构{'pk': value},
**就将字典拆散, 以关键字的形式传参, 传给了get_object_or_404方法 def get_object_or_404(queryset, *filter_args, **filter_kwargs):
try:
# _get_object_or_404内部就是从闯传进来的queryset对象中使用get以关键字的形式查询,但是get方法会在2种情况下, 会抛出异常, 因此内部也做了异常处理
return _get_object_or_404(queryset, *filter_args, **filter_kwargs)
except (TypeError, ValueError, ValidationError):
# 这里就获取到了_get_object_or_404中抛出异常, 由Http404实例化类实例化出来的对象返回到上一层
raise Http404 拓展: 修改必须使用pk作为有名分组!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
本质就是通过get将传过来的字段拆散, 以关键字的形式获取对应的数据对象
因此在自定义的视图类中重写 lookup_url_kwarg 就可以实现, 修改路由中, 对应的又名分组必须取名是pk了.
例如: 有名分组是(?P<num>), 关键字必须num接受
那么self.kwargs在给视图对象中方法传参的时候就是{'num': param}而,
self.kwargs[lookup_url_kwarg]这一步操作直接获取到的就是param了.
'''
obj = get_object_or_404(queryset, **filter_kwargs) # 5) 这一步是APIView中dispatch方法中定义的三段认证中的权限认证. 在drf的认证中会讲到
self.check_object_permissions(self.request, obj) return obj
总结
1. 继承GenericAPIView的视图类, 当需要修改接口指定操作的模型类, 以及序列化的模型类直接在视图类中修改即可了.其他都不用动就可以实现偷换模型类以及序列化类
2. GenericAPIView提供了3个主要的方法
self.get_object() 获取单条数据
self.get_queryset() 获取多条数据
self.serializer_classes(参数同原来即可) 执行自定义视图类中定义的序列化类进行序列化, 将ORM对象的数据转换成python的对象
3. GenericAPIView提供了可修改路由又名分组的指定不再是默认的pk
自定义的视图类

三. 五个视图扩展类

基于mixins,提供了几种后端视图(对数据资源进行曾删改查)处理流程的实现,如果需要编写的视图属于这五种,

则视图可以通过继承相应的扩展类来复用代码,减少自己编写的代码量。减少五中方法的相同代码重用。

这五个扩展类需要搭配GenericAPIView父类,因为五个扩展类的实现需要调用GenericAPIView提供的序列化器与数据库查询的方法。

models.py
from django.db import models

# Create your models here.
class Book(models.Model):
name = models.CharField(max_length=32)
price = models.DecimalField(max_digits=8, decimal_places=2)
author = models.CharField(max_length=32) # 这里的定义可以让序列化类中当作序列化字段来处理, return的结果是什么就是什么.
@property
def current_time(self):
import time
return time.strftime("%Y-%m-%d %X") publish = models.ForeignKey(to='Publish') class Publish(models.Model):
name = models.CharField(max_length=32)
email = models.EmailField()
serializer.py 自定义序列化.py文件
from rest_framework import serializers

from .models import Book
from .models import Publish class PublishModelSerializer(serializers.ModelSerializer):
class Meta:
model = Publish
fields = '__all__' class BookModelSerializer(serializers.ModelSerializer):
publish = PublishModelSerializer()
'''
publish = serializers.SerializerMethodField(read_only=True, source='publish')
# publish = serializers.CharField()
def get_publish(self, instance):
print('instance:', instance)
fields_list = ['name', 'email']
fields_dict = {}
for field in fields_list:
if hasattr(instance.publish, field):
fields_dict[field] = getattr(instance.publish, field)
return fields_dict
'''
# 这里不做任何格外的校验处理, 只是看看校验成功以后的结果
def validated_price(self, data):
# print('data:', data)
return data # 这里也是
def validate(self, validate_data):
# print('validate validate_data:', validate_data)
return validate_data class Meta:
model = Book
# fields = ['id', 'name', ...]
# exclude = ['id']
fields = '__all__'
extra_kwargs = {
'price': {'max_value': 10000, 'min_value': 0}
} def create(self, validated_data):
publish_dict = validated_data.pop('publish')
publish_obj = Publish.objects.create(**dict(publish_dict)) Book.objects.create(**validated_data, publish=publish_obj)
validated_data.update({'publish': publish_dict}) return validated_data def update(self, instance, validated_data):
print('validated_data:', validated_data)
publish_dict = validated_data.pop('publish')
Publish.objects.filter(book__pk=instance.pk).update(**publish_dict) Book.objects.filter(pk=instance.pk).update(**validated_data)
validated_data.update({'publish': publish_dict})
return validated_data
urls.py
# 基于mixins的视图类
path('books2/', views.Books2View.as_view()),
path('book2/<int:pk>/', views.Book2View.as_view()),
views.py
from rest_framework.generics import GenericAPIView
from rest_framework.mixins import CreateModelMixin, DestroyModelMixin, ListModelMixin, RetrieveModelMixin, \
UpdateModelMixin class Books2View(GenericAPIView, ListModelMixin, CreateModelMixin):
# queryset要传query对象,查询了所有的图书
queryset = models.Book.objects.all()
# serializer_class使用那个序列化类序列化这堆数据
serializer_class = BookSerializer def get(self, request):
return self.list(request) # 新增多条数据
def post(self, request):
return self.create(request) class Book2View(GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin):
queryset = models.Book.objects.all()
serializer_class = BookSerializer # 获取一条数据
def get(self, request, pk):
return self.retrieve(request, pk) # 修改数据
def put(self, request, pk):
return self.update(request, pk) def delete(self, request, pk):
return self.destroy(request, pk)
总结
提示: 以下的5种视图扩展类必须和GenericAPIView连用
ListModelMixin 内部封装了list方法, 实现了查询所有数据
CreateModelMixin 内部封装了create方法, 实现了新增数据
RetrieveModelMixin 内部封装了retrieve方法, 实现了查询一条数据
UpdateModelMixin 内部封装了update方法, 实现了更新一条数据
DestroyModelMixin 内部封装

四. GenericAPIView的9个视图子类

继承于GenericAPIView和mixins,进一步把五个方法封装到类中,并五个类组合其他四个,共九个。不需要写方法 函数

ListAPIView源码

9个GenericAPIView的视图子类快速介绍

提示: 以下都是基与对应的5种不同的视图扩展类ModelMixin和GenericAPiView. 在原来的基础之上剔除了对应的上一个节需要定义的重复的方法
CreateAPIView
DestroyAPIView
UpdateAPIView
ListAPIView
RetrieveAPIView
ListCreateAPIView
RetrieveDestroyAPIView
RetrieveUpdateDestroyAPIView
RetrieveUpdateAPIView

ListAPIView源码

class ListAPIView(mixins.ListModelMixin,
GenericAPIView):
"""
Concrete view for listing a queryset.
"""
def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs) # 继承了GenericAPIView和mixins

urls.py

# GenericAPIView和mixins的视图之类 9个
path('books3/', views.Books3View.as_view()),
path('book3/<int:pk>/', views.Book3View.as_view()),

views.py

# 基于GenericAPIView的视图之类 9个
from rest_framework.generics import CreateAPIView, ListAPIView, UpdateAPIView, RetrieveAPIView, DestroyAPIView, \
ListCreateAPIView, RetrieveDestroyAPIView, RetrieveUpdateAPIView, RetrieveUpdateDestroyAPIView # 后面四个是两两组合 class Books3View(CreateAPIView, ListAPIView): # 获取所有,新增一个
queryset = models.Book.objects.all()
serializer_class = BookSerializer class Book3View(RetrieveAPIView, UpdateAPIView, DestroyAPIView): # 获取一条,修改一条,删除一条
queryset = models.Book.objects.all()
serializer_class = BookSerializer

五 基于ModelViewSet(视图集),也就是ViewSetMixin

ModelViewSet继承GenericViewSet,GenericViewSet继承ViewSetMixin,重写了as_view方法,

通过循环路由字典,传给dispatch方法,从而实现一个写一个视图类,实现五个方法。

ViewSetMixin的源码

class ModelViewSet(mixins.CreateModelMixin,
mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
mixins.DestroyModelMixin,
mixins.ListModelMixin,
GenericViewSet): class GenericViewSet(ViewSetMixin, generics.GenericAPIView): # ViewSetMixin的源码
@classonlymethod
# 重写了as_view方法
def as_view(cls, actions=None, **initkwargs):
def view(request, *args, **kwargs):
self = cls(**initkwargs) if 'get' in actions and 'head' not in actions:
actions['head'] = actions['get'] # actions视图路由的方法字典
# actions={'get': 'list', 'post': 'create'}
self.action_map = actions for method, action in actions.items():
# 取出字典中value的值
handler = getattr(self, action)
# 字典中value的值设置成key的值,比如get请求来了,就执行list方法
setattr(self, method, handler) self.request = request # And continue as usual
return self.dispatch(request, *args, **kwargs)

urls.py

# 基于ModelViewSet编写的5个接口
path('books4/', views.Book4View.as_view(actions={'get': 'list', 'post': 'create'})),
path('book4/<int:pk>/', views.Book4View.as_view(actions={'get': 'retrieve', 'put': 'update', 'delete': 'destroy'})),

views.py

# 基于ModelViewSet编写的5个接口
from rest_framework.viewsets import ModelViewSet class Book4View(ModelViewSet):
queryset = models.Book.objects.all()
serializer_class = BookSerializer

视图集补充一个ReadOnlyModelViewSet,获取一条或多条,ModelViewSet的一个子集。

class ReadOnlyModelViewSet(mixins.RetrieveModelMixin,
mixins.ListModelMixin,
GenericViewSet):

六 基于ViewSetMixin的视图集

iewSetMixin类只重写了路由关系,没有继承序列化器的类,所有要配合使用

APIView类,ViewSetMixin也是视图集的一个类,其他都是继承ViewSetMixin

urls.py

# 继承ViewSerMixin的视图类,通过改变视图的路由,直接执行自定义方法get_all_book
path('books5/', views.Book5View.as_view(actions={'get': 'get_all_book'})),

views.py

# 继承ViewSerMixin的视图类
from rest_framework.viewsets import ViewSetMixin class Book5View(ViewSetMixin, APIView): # 就是视图集ViewSet,一定要写在APIView之前,两个继承类,都用共同的方法,需调用第一个的方法。
# ViewSetMixin重写了as_view方法,APIView也是重写了了as_view方法,继承顺序查找关系,ViewSetMixin必须写第一个
def get_all_book(self, request):
my_dic = MyDic()
query_books = models.Book.objects.all()
books_ser = BookSerializer(query_books, many=True)
my_dic.data = books_ser.data
return Response(my_dic.get_dic)
视图集再补充:

源码:

class ViewSet(ViewSetMixin, views.APIView):

class GenericViewSet(ViewSetMixin, generics.GenericAPIView):

class ReadOnlyModelViewSet(mixins.RetrieveModelMixin,
mixins.ListModelMixin,
GenericViewSet):
class ModelViewSet(mixins.CreateModelMixin,
mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
mixins.DestroyModelMixin,
mixins.ListModelMixin,
GenericViewSet):

七 总结

介绍: ModelViewSet继承关系非常多, 通过一层层的继承, 只需要很少的代码就能实现API的5中视图接口
它, 还可以和路由组件使用, 这样就直接使用路由直接生成对应功能的路由接口, 以及在不指定路由的基础之上默认帮我们书写了路由中在as_view()类方法中添加的actions参数了 庞大的继承可实现的功能:
1. APIView提供的
request封装
三段认证
全局异常处理
response响应格式
2. GenericAPIView提供的
视图类中声明queryset 和 serializer_classes 类属性
self.get_object ()
self.get_queryset()
self.get_serializer()
3. 五个基本视图扩展类ModelMixin系列提供的
self.list()
self.create()
self.update()
self.retrieve()
self.destroy()
   4. 九个子类,继承GenericAPIView和ModelMixin
     进一步封住5个视图接口和数据库操作的方法

5. ViewSetMixin提供的
修改路由中ac_view()类方法的actions参数
如:
路由配置: url(r'index/', BookView.as_view(actions={'get': 'get_list'}))
视图使用:
class BookView(ViewSetMixin, APIView):
def get_list(self, request):
...

drf(视图组件)的更多相关文章

  1. DRF视图组件

    DRF视图组件: CVB模式继承----五层 from django.views import View # Django的View from rest_framework.views import ...

  2. DRF 视图组件

    目录 DRF 视图组件 视图组件大纲 两个视图基本类 五个扩展类 九个子类视图 视图集 常用视图集父类 魔法类 一览表 DRF中视图的"七十二变" 第一层:基于APIview的五个 ...

  3. drf视图组件、认证组件

    视图组件 1.基本视图 url(r'^publish/$', views.PublishView.as_view()), url(r'^publish/(?P<pk>\d+)/$', vi ...

  4. DRF 视图组件,路由组件

    视图组件  -- 第一次封装   -- GenericAPIView(APIView):    queryset = None    serializer_class = None    def ge ...

  5. DRF 视图组件代码

    序列化器代码 # 声明序列化器from rest_framework import serializersfrom djangoDome.models import Book class Publis ...

  6. DRF之视图组件

    不断的优化我们写的程序,是每个程序员必备的技能和职业素养,也是帮助我们成长的非常重要的手段. 使用serializer进行put接口设计 根据规范,PUT接口用来定义用户对数据修改的逻辑,也就是upd ...

  7. 【DRF框架】视图组件

    基于mixins视图类 from rest_framework import mixins # 创建视图 class CreateModelMixin(object) def create(self, ...

  8. DRF的视图组件

    目录 DRF的视图组件 两大视图类 六大视图工具类 九大工具视图类 两大视图集基类 DRF的视图组件 DRF的视图组件大概分以下几类 两大视图类 APIView.GenericAPIView from ...

  9. DRF - 序列化组件(GET/PUT/DELETE接口设计)、视图优化组件

    一.序列化组件 基于上篇随笔的表结构 , 通过序列化组件的ModelSerializer设计如下三个接口 : GET 127.0.0.1:8000/books/{id} # 获取一条数据,返回值:{} ...

  10. DRF Django REST framework 之 视图组件(四)

    引言 在我们有几十上百的视图类,都有get,post等方法,在功能类似时,会导致大量的重复代码出现,显然还有很多可以优化的地方.这也就有了视图组件,它的功能非常强大,能很好的优化接口逻辑. 视图组件 ...

随机推荐

  1. 5.字典--《Python编程:从入门到实践》

    5.1 字典   在 Python 中,字典是一系列键-值对.键不能重复,否则对应的值是后面一个. 5.1.1 键-值队的添加与修改 alien_0 = {'color': 'green', 'poi ...

  2. 详解 & 0xff 的意义及作用

    首先我们要都知道, &表示按位与,只有两个位同时为1,才能得到1, 0x代表16进制数,0xff表示的数二进制1111 1111 占一个字节.和其进行&操作的数,最低8位,不会发生变化 ...

  3. NC50615 取石子游戏 2

    题目链接 题目 题目描述 有一种有趣的游戏,玩法如下: 玩家:2人: 道具:N堆石子,每堆石子的数量分别为 \(X_1,X_2,...,X_n\) ​: 规则: ​ 游戏双方轮流取石子: ​ 每人每次 ...

  4. NC24416 [USACO 2013 Nov G]No Change

    题目链接 题目 题目描述 Farmer John is at the market to purchase supplies for his farm. He has in his pocket K ...

  5. Python中保存字典类型数据到文件

    三种方法: 1.在 Python 中使用 pickle 模块的 dump 函数将字典保存到文件中import pickle my_dict = { 'Apple': 4, 'Banana': 2, ' ...

  6. python 学习随笔1121

    Python 数据处理几个好用又简单的库: json re string pandas 与系统交互: subprocess os

  7. 老王电子的拆机 ESP32-SOLO-1 填坑报告

    ESP32-SOLO-1 拆装 都是带板的, 长这个样子 需要用热风枪从背面吹, 因为中间有焊点, esp32朝下, 用280度大概2到3分钟, 四周需要均匀着风, 用镊子试探天线部分是否松动, 将外 ...

  8. 使用winhex查看FAT16格式结构

    winhex介绍 winhex可以直接查看磁盘二进制信息, 可以比较直观地查看到各种文件系统格式的区别. winhex使用 查看硬盘要管理员权限, 即启动的时候要用邮件管理员权限启动 点击Tools- ...

  9. Springboot+Vue+ElementUI实现的宿舍管理系统

    项目说明 doman是一个基于Springboot+Vue实现的前后端分离的宿舍管理系统.项目为本人亲手打造,需要的朋友可以拿去做个修改也是不错的.大神请忽略:) 项目功能 详细请看功能演示: Spr ...

  10. Vue+SpringBoot+ElementUI实战学生管理系统-8.班级管理模块

    1.章节介绍 前一篇介绍了专业管理模块,这一篇编写班级管理模块,需要的朋友可以拿去自己定制.:) 2.获取源码 源码是捐赠方式获取,详细请QQ联系我 :)! 3.实现效果 班级列表 修改班级 4.模块 ...