【深度学习】如何封装可维护的restiful api

news2024/11/15 21:54:37

这篇文章是用一个案例的形式尝试解决字段入参多了,在python这种风格的语言下如何维护的问题!

文章目录

  • 前言
  • 1. json 是个好东西
  • 2. json 是个坏东西
  • 3. json维护数据的适用范围总结
  • 4.解决
    • 4.1 基础版
    • 4.2 进阶版
      • 4.2.1 行动
      • 4.2.2 精进
    • 4.3 另一种选择
  • 总结

前言

我们提供算法的服务,如果入参很少,比如图像识别的,input:image,camera_id, business_id, event_id 图片资源、摄像头id、业务线id、事件id ,搭建restiful api的时候可以不那么讲究,怎么写下一个人也能看懂。但是若是数理计算模型,入参很多,可能是一组参数

[ {field1: xxx,field2:xxx, field3:xxx ......}, {field1: xxx,field2:xxx, field3:xxx ......}]

还要二次处理,id列对推理计算没用, 经纬度要转成 温带、热带、寒带的温带信息。这个时候,在json_map上操作就要死人了。来一个新人接手就完蛋了,row 有 30个item, 二次处理后有50个。对应关系就得3天,没熬过去跑路了。

前任又没写注释,(50个字段我也不想写), 再加上进入不同的方法、处理不同的字段。后面来的人怎么玩,主导开发的人都hold不住了。
这篇文章是用一个案例的形式尝试解决字段入参多了,在python这种风格的语言下如何维护的问题!


1. json 是个好东西

以同步用户做统一用户为例,6个字段用json传挺好,因为key语义明确

user_list  = [ 
{ 'username' : 'zs', 'password' : 123456, 'email' : 'zs@qq.com', 'mobile' : 15210420000, 'gender' : '男' },
{ 'username' : 'ls', 'password' : 123456, 'email' : 'ls@qq.com', 'mobile' : 15210420000, 'gender' : '女' } ]

后续需要增加字段encrypt_mobile, encrypt_password,也就是把手机号和密码加密一下再做交互传输或者其它业务。
这个场景下用json是没问题,字段一眼看到底,不需要走下面的流程。

2. json 是个坏东西

美好的时光总是短暂, json 不是只有好处,它的key的维护太过随意。

user_info = {
'username' : 'zs', 
'password' : 123456, 
'email' : 'zs@qq.com', 
'mobile' : 15210420000, 
'gender' : '男'
}
# 新增(覆盖)一个key 
user_info ['id'] = 1
# 读取key
id = user_info ['id']
# 删除key
del user_info['id'] 

以上代码或让人觉得,本来就是这样的啊,这不也挺简单么。

# 类型注解compare_field 函数使用
from typing import List,Dict

user_info = {
	'username' : 'zs', 
	'password' : 123456, 
	'email' : 'zs@qq.com', 
	'mobile' : 15210420000, 
	'gender' : '男'
}
# 某个时间要增加 encrypt_mobile 和 encrypt_password 的字段
def add_encrypt_field(user_info:json)->json:
	# get from config
	md5_salt = "xxx" 
	mobile = user_info["mobile"]
	password = user_info["password"]
	user_info["encrypt_mobile"] = md5(md5_salt+str(mobile))
	user_info["encrypt_password"] = md5(md5_salt+str(mobile))
	return user_info
# 对比用户是否为相同用户
def compare_field(user_info1:json, user_info_list[user_info]:List[Dict])->bool:
   # 两个user_info的 mobile相同者为统一用户
   for user_info in user_info_list:
   	   if user_info1.get("mobile") == user_info["mobile"]:
   	   		return True
   return False

分函数写,问题出现了, 在compare_field和add_encrypt_field的两个方法中,你咋知道入参是存在mobile和password 属性的呢? 上面一行定义了啊, 那要是在其它文件定义的呢, 那要是在其它方法要用encrpy_mobile 呢,这个时候,你就要做代码追踪看看在哪维护了呢,万一还有bug,在其它方法根据数据特征某个else分支给删了这个字段呢

3. json维护数据的适用范围总结

好,问题明确了,json对字段的维护有两大缺点:

  1. 太随意,
  2. 没有智能提示
    这两个缺点在业务模块在一屏以内或者字段少,见名知意的3,5个字段的时候可以忽略。
    但是你面对的入参可能是这样的:
    input_params = [
    {
        'small_class_no':1, # 小班号
        'tree_name':'杨树',
        'avarage_age':2,    # 平均年龄
        'average_stand_height':1, # 平均高度
        'stand_density_index':123, # 林分密度指数
        'stand_break_area':20, # 林分断面积
        'stand_volume':16, # 蓄积量
        'biomass':20, # 生物量
        'altitude':200, # 海拔
        'slope_direction':30, # 坡向
        'slope_degree':5, # 坡度
        'slope_pose':"上坡", # 坡位
        'soil_thickness':3, # 土壤厚度
        'litter_thickness':2, # 枯落物厚度
        'small_class_area':600, # 小班面积
        'humus_layer_thickness':1,
        'climate_zoo':"热带", #   亚热带山地丘陵、热带, 亚热带高山、暖温带、温带、寒温带
    },
    
    {
        'small_class_no':2, # 小班号
        'tree_name':'杨树',
        'avarage_age':5,    # 平均年龄
        'average_stand_height':10, # 平均高度
        'stand_density_index':123, # 林分密度指数
        'stand_break_area':30, # 林分断面积
        'stand_volume':20, # 蓄积量
        'biomass':50, # 生物量
        'altitude':220, # 海拔
        'slope_direction':40, # 坡向
        'slope_degree':15, # 坡度
        'slope_pose':"下坡", # 坡位
        'soil_thickness':5, # 土壤厚度
        'litter_thickness':2, # 枯落物厚度
        'humus_layer_thickness':10,
        'small_class_area':600, # 小班面积
        'climate_zoo':"热带", #   亚热带山地丘陵、热带, 亚热带高山、暖温带、温带、寒温带
    }
    ]

入参之后需要转化一些字段:

  1. 平均年龄要以5年为单位分级:1代表 [0-5)年 2代表 [5-10)年…
  2. 海拔高度要以200m为单位分级: 1代表 [0-200) 2 代表 [200-400)…
  3. 坡位:1. 脊部;2.上坡;3.中坡;4.下坡;5.山谷(或山洼);6.平地 要转成枚举
  4. climate_zoo 要分成两个 1 亚热带山地丘陵、热带, 2 亚热带高山、暖温带、温带、寒温带
  5. 土壤厚度:土壤厚度:
    a 亚热带山地丘陵、热带
    厚 ≥80cm
    中 40cm~79cm
    薄 <40cm
    b 亚热带高山、暖温带、温带、寒温带
    厚 ≥60cm
    中 30~59cm
    薄 <30cm
  6. 腐殖质层厚度:1. 薄:<2cm 2. 中:2cm~5cm 3. 厚:>5cm
  7. small_class_area 小班面积 >= 600 m^2 才有效
  8. 坡向要转成枚举:北坡:方位角 338°~22° 东北坡:方位角 23°~ 67° 东坡:方位角 68°~ 112° 东南坡:方位角 113°~157° 南坡:方位角 158°~202° 西南坡:方位角 203°~247° 西坡:方位角 248°~292° 西北坡:方位角 293°~337° 无坡向:坡度<5°的地段

后续业务有时需要原始字段,有时需要转换字段,json维护的方式就暴露无疑。

4.解决

4.1 基础版

当然你可以先设置json的数据模版,来解决第一个问题。

param_template = {
        'small_class_no':"", # 小班号
        "tree_name":"", # 树种名字
        # 测树因子
        'avarage_age':"",    # 平均年龄
        'average_stand_height':"", # 平均高度
        'stand_density_index':"", # 林分密度指数
        'stand_break_area':"", # 林分断面积
        'stand_volume':"", # 蓄积量
        'biomass':"", # 生物量
        # 立地因子
        'altitude':"", # 海拔
        'slope_direction':"", # 坡向
        'slope_degree':"", # 坡度
        'slope_pose':"", # 坡位
        'soil_thickness':"", # 土壤厚度
        'litter_thickness':"", # 枯落物厚度
        'humus_layer_thickness':"", # 腐殖质层厚度
        'small_class_area':"", # 小班面积
        'climate_zoo':"", #   亚热带山地丘陵、热带, 亚热带高山、暖温带、温带、寒温带
        # 转换过后的数据
        'int_humus_layer_thickness':"", # 腐殖质层厚度
        'int_slope_pose':"",
        'int_soil_thickness':"",
        'int_litter_thickness':"",
        'int_altitude':"", # 海拔等级 200m一个等级
        'int_climate_zoo':"",  # 亚热带山地丘陵、热带 1  亚热带高山,暖温带,温带,寒温带 2
}

原始字段17个,一共23个,而且都是不熟悉的字段, 数据模版解决了字段维护的问题,初始化就在那里等着,只需要覆盖,不用新加。
但没解决智能提示的问题

4.2 进阶版

任务:需找一个带智能提示的数据类型:nametuple 有名元祖

4.2.1 行动

In [2]: from collections import  namedtuple
    # 定义一个User的有名元祖,熟悉包括 name,age,gender
   ...: User = namedtuple('User', ['name', 'age', 'gender'])
   # 初始化
   ...: u = User('villa', 33, 'male')
   # 这里的获取就带智能提示了,一定要自己试一下,博客文章没法演示
   ...: print(u.name)
   ...: print(u.age)
   ...: print(u.gender)
   ...: print(u)
villa
33
male
User(name='villa', age=33, gender='male')
# 也可以在适当的时候转回每个人都很喜欢的json
In [5]: u._asdict()
Out[5]: {'name': 'villa', 'age': 33, 'gender': 'male'}

修改属性要这样操作:

# 这样修改会报错
In [6]: u.age = 33
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-6-bea52c69315f> in <module>
----> 1 u.age = 33

AttributeError: can't set attribute
# 正确的修改方式
In [8]: u = u._replace(age=32)
In [9]: u
Out[9]: User(name='villa', age=32, gender='male')
正确的修改方式,还需要赋值回来,还是挺麻烦的,而且要记住age属性(不用 u. 可以智能提示发现它叫age了,嘿嘿) 
 u = u._replace(age=32)

我要是一般的博主,介绍有名元组到这里其实已经结束了…等等,智能提示的问题解决了,那初始化占位怎么办?

from collections import  namedtuple
    # 定义一个User的有名元祖,熟悉包括 name,age,gender
User = namedtuple('User', ['name', 'age', 'gender'])

u = User('villa', 33, 'male')
u
u1 = User('villa', 33)
u1
u2 = User('villa', 33, '')
In [10]: User = namedtuple('User', ['name', 'age', 'gender'])
    ...: 
    ...: u = User('villa', 33, 'male')
    ...: u
    ...: u1 = User('villa', 33)
    ...: u1
    ...: u2 = User('villa', 33, '')
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-10-3344fd3bd5a4> in <module>
      3 u = User('villa', 33, 'male')
      4 u
----> 5 u1 = User('villa', 33)
      6 u1
      7 u2 = User('villa', 33, '')

TypeError: __new__() missing 1 required positional argument: 'gender'

不赋值不行啊,报错了,u2是可以过的,提示一下,我们赋值不需要记住属性顺序,ide的智能提示会提示,一图胜千言。
在这里插入图片描述
缺点:暂时没有gender字段的信息,需要在每次初始化的时候给“”或者None (python阉割版强类型其实无所谓嘿嘿)
而且我们不能新增属性,需要在定义user有名元祖类的时候写好!

4.2.2 精进

针对4.2.1的缺点:暂时没有gender字段的信息,需要在每次初始化的时候给“”或者None
你可能会问? 我觉得也没问题啊,难道不应该这样么,在初始化的时候给默认值。
每次初始化给默认值没问题,槽点在于每次初始化你都需要手动赋值,用一次赋值一次!!!
设计理念是接收定义的复杂但不接受调用的复杂,采用4.2.1 每次调用都变得复杂
解决方案:定义复杂一些(继承nametuple,改写他的初始化函数__new__),而避免每次调用都手动负责。(为什么不是__init__, 有这个问题的同学,要查一下两者的区别,init 依赖__new__, new 更底层,以及尝试一下__init__下重写到底行不行,欢迎评论区留言, 同时也可以看下__slot__属性)

from collections import namedtuple
class Color(namedtuple("Color", ["r", "g", "b", "alpha"])):
    def __new__(cls, r, g, b, alpha=None):
        return super().__new__(cls, r, g, b, alpha)
>>> c = Color(r=0, g=0, b=0)
>>> c
Color(r=0, g=0, b=0, alpha=None)

通过这种修改,alpha属性就不需要每次初始化都指定了
ps: init 改完之后输出报错,报错信息也输出下

from collections import namedtuple
class Color(namedtuple("Color", ["r", "g", "b", "alpha"])):
    def __init__(cls, r, g, b, alpha=None):
        return super().__init__(cls, r, g, b, alpha)


c = Color(r=0, g=0, b=0)
print(c)
# -------------------------------------------------------------------
(py38_18) [jianming_ge@localhost forest_site_quality_evaluation]$ python aaa.py 
Traceback (most recent call last):
  File "aaa.py", line 7, in <module>
    c = Color(r=0, g=0, b=0)
TypeError: __new__() missing 1 required positional argument: 'alpha'

4.3 另一种选择

4.2已经足够好了,但是我还说又臭又长的再给一个方案:类对象初始化
代码一镜到底oh yeah!版本

 class SmallClassNoParams(object):
        __slots__ = [
        'small_class_no', # 小班号
        "tree_name", # 树种名字
        # 测树因子
        'avarage_age',    # 平均年龄
        'average_stand_height', # 平均高度
        'stand_density_index', # 林分密度指数
        'stand_break_area', # 林分断面积
        'stand_volume', # 蓄积量
        'biomass', # 生物量
        # 立地因子
        'altitude', # 海拔
        'slope_direction', # 坡向
        'slope_degree', # 坡度
        'slope_pose', # 坡位
        'soil_thickness', # 土壤厚度
        'litter_thickness', # 枯落物厚度
        'humus_layer_thickness', # 腐殖质层厚度
        'small_class_area', # 小班面积
        'climate_zoo', #   亚热带山地丘陵、热带, 亚热带高山、暖温带、温带、寒温带
        # 转换过后的数据
        'int_humus_layer_thickness', # 腐殖质层厚度
        'int_slope_pose',
        'int_soil_thickness',
        'int_litter_thickness',
        'int_altitude', # 海拔等级 200m一个等级
        'int_climate_zoo',  # 亚热带山地丘陵、热带 1  亚热带高山,暖温带,温带,寒温带 2
    ]

        def __init__(self, small_class_no, tree_name, avarage_age, average_stand_height, stand_density_index, stand_break_area, stand_volume, biomass, 
            altitude, slope_direction, slope_degree, slope_pose, soil_thickness, litter_thickness,humus_layer_thickness, small_class_area, climate_zoo,int_altitude=None,int_climate_zoo=None):
            # 林班面积必须大于600 m^2
            if small_class_area < 600:
                raise Exception("small_class_area < 600m^2")

            if climate_zoo not in ["亚热带山地丘陵","热带","亚热带高山","暖温带","温带","寒温带"]:
                raise Exception("climate_zoo must be one of 亚热带山地丘陵,热带,亚热带高山,暖温带,温带,寒温带")
            self.int_climate_zoo = Soil_Type.SUBTROPICAL_MOUNTAIN_HILL_AND_TROPICAL.value if "亚热带山地丘陵、热带".find(row["climate_zoo"]) >=0 else Soil_Type.SUBTROPICAL_MOUNTAIN_WARM_TEMPERATE_TEMPERATE_COLD_TEMPERATE_ZONE.value
            self.int_soil_thickness = get_soil_thickness_level(soil_thickness,self.int_climate_zoo).value
            self.humus_layer_thickness = humus_layer_thickness
            self.int_humus_layer_thickness = get_humus_thickness_level(humus_layer_thickness)
            int_slope_pose = map_slope_pose.get(slope_pose)
            if not int_slope_pose:
                raise Exception("slope_pose must be one of 1. 脊部;2.上坡;3.中坡;4.下坡;5.山谷(或山洼);6.平地")

            self.int_litter_thickness = get_litter_thickness_level(litter_thickness)
            self.int_slope_pose = int_slope_pose
            self.small_class_no = small_class_no
            self.tree_name = tree_name
            self.avarage_age = avarage_age
            self.average_stand_height = average_stand_height
            self.stand_density_index = stand_density_index
            self.stand_break_area = stand_break_area
            self.stand_volume = stand_volume
            self.biomass = biomass
            self.altitude = altitude
            self.slope_direction = slope_direction
            self.slope_degree = slope_degree
            self.slope_pose = slope_pose
            self.soil_thickness = soil_thickness
            self.litter_thickness = litter_thickness
            self.small_class_area = small_class_area
            self.climate_zoo = climate_zoo
            self.int_altitude =  math.ceil(altitude/200)
            
       
        def to_json(self):
            a = {}
            for field in self.__slots__:
                a.__setitem__(field,getattr(self,field))
            return a

使用

  import json
    handle_params = []
    # step 1: 验证参数并转换成有名元祖
    for row in input_params:
       ## 完成初始化的时候同时验证参数了, **row是什么意思自行百度
       a = SmallClassNoParams(**row)
       ## 我是存的json,村对象也可以,主要是为了转成pandas,为后续并行计算打基础
       handle_params.append(a.to_json())
     
        X = pd.DataFrame(handle_params,columns=['avarage_age','average_stand_height','stand_density_index','stand_break_area','stand_break_area','stand_volume','altitude','slope_direction','int_humus_layer_thickness','int_slope_pose','int_soil_thickness','int_litter_thickness','int_altitude','int_climate_zoo',])
    print(X)
    # X = np.array([[1, 2], [1, 4], [1, 0],
    #            [4, 2], [4, 4], [4, 0]])
    clustering = AgglomerativeClustering(2).fit(X)
    print(clustering.labels_)

优点:

  1. **slot**属性用来定义哪些属性应该暴露出来
  2. 在初始化的同时做参数转化维护,而且只在init里面做参数转化,预期是获取到参数对象后,你的参数一定是对的,报错是计算业务出错了!!!
  3. to_json 方法用来将对象转成json,哪些属性能转出来取决于1.的定义
  4. to_json的方法用到了getattr(对象,属性名)内置方法,这是我第一次把它用到生产中,之前我肤浅的认为,这是脱了裤子放屁,对象.属性名的方式不香么
  5. 其实我还用__getitem__魔术方法实现过,不过死循环了,列出来你可以想一下为啥读属性的时候会死循环
  6. __setitem__也是魔术方法,你可以自己练习一下,看看他的调用时机
  7. 我知道在sqlalchemy或者flask中有个column属性也能实现,但偷个懒不查了。

这样以来,就分层了,等等~我实现的这个参数对象类不就是restiful 框架的参数验证层么!

总结

其实以上代码若一直用list[json]的维护方式,2个小时可以实现,但这篇文章的方法,我实现了超过5个小时,有了思路,不一定能改对,再真正落地思考的同时,会报错,有助于理解魔术方法在什么场景下适合。啰⑦⑧嗦,各位见笑!

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

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

相关文章

立根铸魂 崛起数智时代 GBASE受邀出席操作系统产业峰会2022

2022年12月28日&#xff0c;由openEuler开源社区发起举办的操作系统产业峰会2022/openEuler Summit 2022正式召开。GBASE荣幸受邀参加统信软件“深耕数字化”主题论坛&#xff0c;分享GBase 8c基于鲲鹏生态的创新实践历程和经验。 操作系统产业峰会2022 -南大通用GBase 8c基于鲲…

使用Nordic的nrf52832控制指定从机(一主多从)

一主多从1. 想要实现的功能2. 从机3. 主机3.1 主从机连接个数设置3.2 扫描过滤3.3 连接和断开连接3.4 按键处理3.5 从机读写3.5.1 写3.5.1 读4运行效果1. 想要实现的功能 1.主机能连接多个从机&#xff08;主机作为控制器&#xff0c;从机作为节点&#xff09;。 2.主机能使用…

Java跨域问题

目录 1、跨域问题说明 ​2、跨域解决方案 2.1、局部跨域解决方案 2.1.1、CrossOrigin注解跨域 2.1.2、手动设置响应头 2.2、全局跨域解决方案 2.2.1、实现WebMvcConfigurer接口设置跨域 2.2.2、定义CorsFilter Bean实现跨域 2.2.3、重写ResponseBodyAdvice接口中的bef…

ros的launch文件知识

_node标签&#xff1a; 在指定机器上启动节点respawn"true|false"(可选) 如果节点退出&#xff0c;是否自动重启respawndelay"N"(可选) 如果 respawn 为 true,那么延迟N秒后启动节点required"true|false"(可选) 该节点是否必须&#xff0c;如果…

ZooKeeper 避坑实践:SnapCount 设置不合理导致磁盘爆满,服务不可用

作者&#xff1a;子葵 背景 在 ZooKeeper 的日常使用过程中&#xff0c;一个令人头疼的问题就是节点的磁盘容量问题&#xff0c;如果由于过大的 TPS 或者不适当的清理策略会导致集群中数据文件&#xff0c;日志文件的堆积&#xff0c;最终导致磁盘爆满&#xff0c;Server 宕机…

在线客服系统部署配置邮箱消息通知功能 - 唯一客服(v1kf.com) -开源私有化独立部署在线客服系统源码...

为在线客服系统设置邮件通知具有以下几个好处&#xff1a; 改善客户体验&#xff1a;邮件通知可以让客户实时收到新消息或更新通知&#xff0c;这有助于提高他们对您的服务的整体体验。 提高效率&#xff1a;邮件通知可以帮助提高客服团队的效率&#xff0c;因为它们会在新消息…

非专业人士如何完成数据采集?纯干货,一文看懂

写在前面&#xff1a; 本教程能够解决大部分人的数据采集及分析需求&#xff0c;实用、简单&#xff0c;尤其适合Excel大户、办公族、业务人员&#xff0c;或者不会编程、不懂数据分析理论的技术小白…… 来不及看的可以先点赞收藏&#xff01; 01 点对点的采集&#xff1a;…

吴恩达《机器学习》——欠拟合与过拟合

欠拟合与过拟合1. 方差与偏差模型的容量、过拟合和欠拟合2. Python代码实践2.1 拟合直线2.2 拟合多项式数据集、源文件可以在Github项目中获得 链接: https://github.com/Raymond-Yang-2001/AndrewNg-Machine-Learing-Homework 1. 方差与偏差 在数学上&#xff0c;估计的偏差…

Java基础漏洞(二)

继续填补自己的知识漏洞 1.&、&&、|、||之间的区别 &是逻辑与&#xff0c;而&&则是短路与。&和&&之间的区别是&#xff0c;在短路与&&的情况下&#xff0c;两个条件当第一个条件为假时&#xff0c;则不再执行第二个条件&#xf…

java学习之类方法

目录 一、基本介绍 二、类方法的调用 三、类方法的应用实例 代码 内存分析 运行结果 四、类方法的经典使用场景 五、类方法使用细节 第一条 第二条 第三条 第四条 第五条 第六条 六、练习 第一题 考察点 分析 结果 第二题 代码 考察点 结果 第三题 类方法 …

LeetCode498. 对角线遍历

LeetCode刷题记录 文章目录&#x1f4dc;题目描述&#x1f4a1;解题思路⌨C代码&#x1f4dc;题目描述 给你一个大小为 m x n 的矩阵 mat &#xff0c;请以对角线遍历的顺序&#xff0c;用一个数组返回这个矩阵中的所有元素。 示例1 输入&#xff1a;mat [[1,2,3],[4,5,6],[…

VUE2使用浏览器缓存的方法

分两种&#xff1a;localStorage和sessionStorage&#xff0c;它两统称webStorage 注意点1&#xff1a;localStorage对象和sessionStorage对象都是window对象下的&#xff0c;且方法都是一样的&#xff0c;默认”window.”可以省略,添加可用setItem(K,V)&#xff0c;查询可用ge…

数据库|scMethBank:单细胞全基因组 DNA 甲基化图谱数据库

甲基化是DNA的一种重要化学修饰&#xff0c;可调节基因的表达和关闭&#xff0c;与癌症、衰老、老年痴呆等许多疾病密切相关&#xff0c;是表观遗传学的重要研究内容之一。测序技术的发展&#xff0c;极大促进了单细胞DNA甲基化研究。然而大量数据的不断积累&#xff0c;对单细…

《HTTP权威指南》----HTTP报文

目录 报文流 报文的组成部分 报文语法 1.起始行 2.首部 通用首部&#xff0c;既可以出现在请求报文中也可以出现在响应报文中。 请求首部&#xff0c;提供更多有关请求的信息。 响应首部&#xff0c;提供更多有关响应的信息。 实体首部&#xff0c;描述主题的长度和内…

2022年,一个技术账号的年终独白,满篇都写着2个字:真难。

2022年&#xff0c;梦想橡皮擦这个账号经历了成长&#xff0c;突破&#xff0c;回归 2023年&#xff0c;适应改变 文章目录序2022年&#xff0c;梦想橡皮擦账号整体汇总原创博客KPI计划与完成总排名KPI计划与完成2022年&#xff0c;橡皮擦获得的荣誉2022年&#xff0c;做技术博…

日志收集系统架构

背景 应用服务器多&#xff0c;日志文件被分散在各个应用服务器上&#xff0c;需要依次登录每台设备才能查看日志&#xff0c;效率低下&#xff0c;且不利于服务器安全管控&#xff0c;加大生产服务器的风险&#xff1b;日志文件不统一&#xff0c;各项目日志没有统一的规范&a…

Python Django教程之实现天气应用程序

基本设置 将目录更改为天气 cd weather启动服务器 python manage.py runserver要检查服务器是否正在运行&#xff0c;请转到 Web 浏览器并输入为 URL。现在&#xff0c;您可以通过按以下命令停止服务器http://127.0.0.1:8000/ ctrl-c 实现 python manage.py startapp main…

Vehicle Speed Forecasting Based On GCN-LSTM Combined Model

GCN-LSTM模型预测道路交通车辆速度 Vehicle Speed Forecasting Based On GCN-LSTM Combined Model Summary This research offers a multistep traffic flow forecasting framework relying on interest spatial-temporal-graph neural network-long short-term memory neura…

【阅读】《MYSQL技术内幕:innodb》索引

概念 索引的类型 聚集索引&#xff1a;叶子节点包含行记录的全部数据辅助索引&#xff1a;叶子节点不包含行记录的全部数据&#xff0c;除了键值以外&#xff0c;还包含指向索引行的书签。 堆表和索引组织表 堆表 无论是主键索引还是普通索引都是辅助索引。数据是按照插入…

​力扣解法汇总2042. 检查句子中的数字是否递增

目录链接&#xff1a; 力扣编程题-解法汇总_分享记录-CSDN博客 GitHub同步刷题项目&#xff1a; https://github.com/September26/java-algorithms 原题链接&#xff1a;力扣 描述&#xff1a; 句子是由若干 token 组成的一个列表&#xff0c;token 间用 单个 空格分隔&…