python技术分享

文章目录

  • python介绍
  • 应用领域
  • 环境搭建
  • 基础知识
    • 编程工具
    • 变量
    • 基本数据类型
    • 容器数据类型
    • 程序结构
    • 运算符
    • 函数
  • 技巧总结
  • python内存管理
  • python常用技术
  • python的缺陷优化
  • python的编码规范
  • 提升性能总结

python介绍

  1. 弱类型的语言
    声明一个变量,直接赋值即可,简单方便,如 a = 10
    强类型的语言,如C/C++就必须声明类型int a = 10;
  2. 解释型语言
    由python解释器,边解释边执行,将人类可理解的代码转为CPU可处理的0、1。
  3. 简单易学,易上手,高级语言,开发效率高,面向对象(一切皆对象)。
  4. 丰富的扩展库,拿来即用,不用重复的造轮子。

 
 
缺点:

  • 运行效率低,比java慢一点,比C慢很多,但一般人是感知不到的。
  • 代码无法加密,容易泄露核心源码
  • 线程无法利用多核CPU资源
     

应用领域

web: Django/flask
爬虫:requests/scrapy/bs4/urllib等
数据分析:numpy/pandas/matplotlib
机器学习:sklearn
深度学习:tensorflow/pytorch/paddlepaddle
云计算:框架OpenStack
自动化运维、金融分析、量化交易等
谷歌、豆瓣、知乎、百度、apple等公司都在使用python。

环境搭建

  1. 最简单的方式就是安装一个python解释器
    python官网
  2. 最方便的方式就是按照anaconda
    anaconda安装
  3. 拷贝别人安装好的python程序及包,如python38整个程序包,放入C程序目录,配置环境变量
    C:/xxx/xxx/python38;
    C:/xxx/xxx/python38/Scripts;
    C:/xxx/xxx/python38/Include;
    最后记得更新pip,否则可能无法安装扩展包:
# 更新pip
python -m pip install --upgrade pip

 

基础知识

编程工具

  1. VScode
  2. Pycharm
  3. Anaconda

变量

  1. 字母、数字、下划线
  2. 不能使用保留的关键字 --keyword.kwlist
name = "jack"  # 声明变量直接赋值,句尾没有分号;
my_address = "henan province" # 下划线命名法,官方推荐
myAddress = "zhengzhou" # 驼峰命名法,java等常用
NAME = "tom" # 全部大写,认为它是一个常量(其实也可以更改)

#多行注释使用 """ 三引号 """
# 单行注释 # 号
print(NAME)
#python shell中 交互式运行
#python xxx.py   以文件方式,python解释器解释执行

基本数据类型

int 、float、str、bool、None

name = "jack"   # 字符串驻留,
age = 19    # 小整数池
height = 1.73
married = False # java/js/c/c++ true/false
girl_friend = None  # 仅有一个
print("my name is %s, I am %d years old"%(name,age))

查看类型:type( obj )
转换类型:
int(1.4)–>1
int(True)–>1
int(False)–>0
float(2)–>2.0
str(2)–>“2”
str(True)–>“True”
str(None)–>“None”

字符串类型:可以使用单引号、双引号、三引号表示字符串

s1 = "my name"
s2 = "is jack"
print(s1+s2) # 字符串的拼接
print(s1*3) # 打印三遍
print(s1+5) #报错

 

容器数据类型

list/tuple/dict/set/str

  • list列表
    可变数据类型
# 定义一个列表,一系列数据的组合
list1 = ["a",23,True] 
# 通过下标引访问
list1[0]
list1[-1]
list1[start:end:step] #分片复制
#修改
list1[0] = "张三"

#在ipython 下做一些测试、验证
#查看list1的类型
type(list1)
#查看list1 都由哪些属性、方法
dir(list1)
list1.tab键
#列表方法
list1.append() #追加一个元素
list1.extend(["d","e","f"]) #扩展一个列表
list1.insert(idx,e) #在指定索引处,插入数据
list1.pop()# 弹出末尾元素,并返回该元素
list1.pop(idx)#弹出指定索引的元素
list1.remove(e) #删除指定元素,顺序搜索,删除匹配到的第一个e
list1.sort() #默认升序排序列表本身,返回None
list1.reverse() #将所有元素逆序
list1.count(e) #统计列表中,元素e 出现的次数
list1.index(e) #查找e,返回对应的索引,找不到则异常
e in list1  #元素e是否在list1中,返回True/False
b = list1.copy() #复制
list1.clear() #清空元素
  • tuple元组
    不可变 数据类型
#索引操作  与列表相同,但是元组是不可变的
t = ("a","b","d")
#访问
t[0]
t[-1]
t[::1]
#修改
t[0] = "update"  #异常

type(t)
dir(t)
  • dict字典
    key-value 键值对 如,{“name”:“jack”}
    key有三种形式:字符串、数值、元组
#创建空字典
empty = {}
empty1 = dict()

d = {"name":"jack","age":23,"height":173.2,"sex":"Female"}
#查看类型
type(d)
d.keys() #所有的key,类似列表的对象
d.values() #所有的value类列表
d.items() #(key,value)元组项的类列表

#获取数据
d["name"] # key不存在时,报错
d["age"] = 29 #更新值
d.get("name",None) #获取"name"的值,没有这个key则返回None
d.get("addr","China")

#删除数据
d.pop("age") #弹出age 这个键值对,返回其值
d.popitem() #默认弹出最后一个键值对
del d["name"]
#从一个序列中设置key
d1 = {}
d1.fromkeys([1,2,3,"name"],"value")
#返回一个新字典{1:"value",2:"value",3:"value","name":"value"}


#更新,可以更新已有的key-value;也可以将一个新字典更新到d中
d.update({key:value}) 

d.clear() #清空自身
d.copy()  #复制
  • set集合
    无序、去重的容器数据类型
s = set()
s1 = {1,2,3}

#查看类型
type(s)
dir(s)
s.tab键

#增加元素
s.add(e) #
s.remove(e)
s.pop()

#集合的操作
s1 = {1,2,3}
s2 = {2,3,4,5}
s1&s2 #交集 -->{2,3}  s1.intersection(s2)
s1|s2 #并集 -->{1,2,3,4,5} s1.union(s2)
s1 - s2 #差集,属于s1,但不属于s2的元素-->{1}
s.clear()
s.copy()

s1.update(s2) # 将集合s2中的内容,更新到s1中
{23}.issubset(s1) # 是否s1的子集

 

程序结构

顺序、循环、分支结构

  • 循环
# for 循环容器类型
for i in range(10):
	print(i)
	
for i in [1,2,3]:
	print(i)

for i in (1,2,3):
	print(i)

#while
label = 1
while label < 5:
	print("current label is %d"%label)
	label += 1
  • 分支
age = 23
if age > 50:
	print("中老年人")
elif age > 30:
	print("中年人")
else:
	print("青年人")

 

运算符

# 算术运算符
+ - * / **() //(地板除)
+= -= *= /= 
#比较运算符
> >= < <= == != 

# 三目运算符
name = "jack"
a = name if name else "tom"  # []/()/{}/""/None/0 均为False

#逻辑运算符
and or not   # && || !

函数

# sum
def func(p1, p2, p3=None): # 位置参数必须传值, 关键字参数可以不传
	if p3 is None:
		return p1 + p2
	return p1 + p2 + p3

# 收集参数
def func1(*args, **kwargs):
	print("args:", args)
	print("kwargs:", kwargs)
	
	# 隐式返回None

# 定义类
class BenChi(object): # object 是一切类的基类
	def __new__(cls, *args, **kwargs):
		return object.__new__(cls)
		
	def __init__(self, name, color):
		# 实例属性
		self.name = name
		self.color = color
	# 实例方法
	def run(self):
		print("start to run...")
	
	# 静态方法
	@staticmethod
	def tell_brand():
		print("奔驰品牌") 

	# 类方法
	@classmethod
	def cls_method(cls, *args):
		print("当前类:", cls)
  1. __new__、__init__等魔法方法,python内置的用于完成对象的某种操作的方法;
  2. __name等为私有属性、私有方法,只能在类内部使用;
  3. _module等为模组内部受保护的变量,一般只模组内部使用;
  4. class_等命名方式,为了不与内建的关键字冲突;

技巧总结

  • python自省,程序运行时,获取变量的类型与结构,然后决定进一步的操作。
    • type查看类型;如type(a)
    • dir查看属性、方法;如dir(a)
    • id 获取内存地址;如id(a)
    • hasattr(obj, attr)
    • getattr(obj, attr)
    • setattr(obj, attr, val)
    • isinstance(obj, cls) / issubclass(cls1, cls)
    • 强大的inspect自省模块
  • 模块
    • 一个xxx.py文件就是一个模块,import xxx
    • 多个模块 + __init__.py 放入一个目录,形成一个包
    • 导包搜索顺序,【当前目录】-【PYTHONPATH】-【sys.path】
       
  • 函数、类的使用
  • IDE用于python开发,黑窗口用于测试、自省、查看文档;
  • 案例:求1000以内的所有质数,然后逐个打印。
# 判断是否质数
def is_prime(n):
    if n < 2:
        return False

    p = n - 1
    while p >= 2:
        if n % p == 0:
            return False
        p -= 1
    return True


def calc_prime(n):
    primes = []
    for i in range(2, n+1):
        if is_prime(i):
            primes.append(i)

    return primes


if __name__ == '__main__':
    result = calc_prime(100)
    print(result)
	

 

python内存管理

  • 引用计数;
    变量赋值,引用计数+1;
    删除变量,引用计数-1;
import sys
sys.getrefcount(obj)  # 计算引用计数,本函数也会令引用计数+1
  • 垃圾回收,引用计数为0则回收;
  • 分代回收(标记-清除),解决循环应用问题;gc模块
import gc

gc.disable()

# 循环引用
  • 小内存池机制;512字节以内的为小内存块,python独自管理,不返回OS。

  • 内存优化,提高效率

    • 小整数池,
      [-5, 256] / id查看地址 / is判断是否同一个对象
    • 字符串驻留,
      由字母、数字、下划线组成的字符串,优先查找缓存池,找到则引用,未找到则创建并存入缓存池。
    • 生成器 ,保存算法,节约内存
# 求20000内的质数
# 使用内置函数filter优化,使用psutil查看内存差异

 

python常用技术

  • 闭包与装饰器
    • 闭包,函数内部定义了另一个函数,
    • 装饰器,闭包的应用,遵循开闭原则,扩展函数、类的功能。
# 1.创建任务队列,闭包内部函数添加任务
# 2.创建单次消费函数
# 3.装饰器扩展多次消费

import queue
import time


# 闭包,生产者
def outer(task_queue):
    print("get queue:", task_queue)

    def inner(url):
        print(f"add task [{url}]")
        task_queue.put(url)
    return inner


# 多次消费高阶函数
def multi_consumer(func):
    def wrapper(tsk_q):
        while not tsk_q.empty():
            func(tsk_q)
            time.sleep(1)
    return wrapper


# 消费者
@multi_consumer
def consumer(task_queue):
    url = task_queue.get()
    print(f"consuming [{url}]")


if __name__ == '__main__':
    task_queue = queue.Queue(maxsize=10)
    producer = outer(task_queue)
    # 需要添加任务时调用
    urls_list = ["http://www.baidu.com", "http://python.org", "https://cn.vuejs.org/"]
    for url in urls_list:
        producer(url)

    # 消费任务
    consumer(task_queue)

  • 面向对象
    • 单例模式
    • 简单工厂模式
    • 适配器模式
    • 建造者模式
    • 装饰器模式
# 单例模式
class Singleton(object):
    instance = None
    def __new__(cls, *args, **kwargs):
        if cls.instance:
            return cls.instance
        cls.instance = object.__new__(cls)
        return cls.instance

    def __init__(self, name, age):
        if hasattr(self, "init_"):
            return
        self.name = name
        self.age = age
        self.init_ = True

# 适配器模式
class HuaweiPay(object):
    def huawei_pay(self, cash):
        print("huawei pay:", cash)


class XiaomiPay(object):
    def xiaomi_pay(self, cash):
        print("xiaomi pay:", cash)


class PayAdapter(object):
    def __init__(self, pay_method, func):
        self.pay_obj = pay_method()
        self.pay_func = func
        self.check_func()

    def check_func(self):
        if not hasattr(self.pay_obj, self.pay_func):
            raise AttributeError(f"{self.pay_obj} has no {self.pay_func} attr" )

    def pay(self, cash):
        getattr(self.pay_obj, self.pay_func)(cash)
        
  • 线程, threading
    • 轻量级进程,在一个进程内部创建;
    • 操作系统可执行的最小单元;
    • 一个线程可以创建其他子线程,多个子线程并发执行;
    • 子线程基本没有自己的资源,而是共享进程中的内存等资源;
    • cpython中由于GIL存在,多线程无法利用多核CPU;
    • 适用于IO密集型程序,如爬虫;
      多线程案例
在这里插入代码片
  • 协程并发
    • 协程又叫微线程,在单线程内部实现上下文的切换;
    • 单线程的高并发,避免多线程的创建、切换、销毁等资源和性能的消耗;
    • 由程序员开发的,不是操作系统提供的;
    • 适用CPU密集型程序;
    • 无法利用多核CPU;线程内部阻塞,会阻塞整个程序;
      协成案例

# 异步下载图片
import aiohttp
import asyncio
from pathlib import Path


target_dir = Path("download") # 实例化一个path对象
target_dir.mkdir(exist_ok=True)  # 创建目录

image_url = ["https://img0.baidu.com/it/u=695609245,3889806637&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=866",
             "https://img2.baidu.com/it/u=1031222732,3723858324&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=889",
             "https://img1.baidu.com/it/u=1724252144,3040470484&fm=253&fmt=auto&app=138&f=JPEG?w=764&h=500",
             "https://img0.baidu.com/it/u=1195778458,70026656&fm=253&fmt=auto&app=138&f=JPEG?w=480&h=720",
             "https://img2.baidu.com/it/u=1506702021,2130004389&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=749"]


async def fetch(session: aiohttp.ClientSession, url: str, name: str):
    async with session.get(url, verify_ssl=False) as res:
        data = await res.content.read()  # 读取字节数据  耗时  挂起协程
        (target_dir / name).write_bytes(data) # 写入字节数据


async def main():
    # aiohttp.ClientSession 是异步上下文管理器
    # 创建会话
    async with aiohttp.ClientSession() as session:
        # 创建协程对象的任务
        tasks = [asyncio.create_task(fetch(session, url, name)) for url, name in zip(image_url, [f"image_{i + 1}.jpg" for i in range(5)])]
        # 等待所有的任务执行完成
        await asyncio.wait(tasks)


if __name__ == '__main__':
    # 启动 事件循环,并自动关闭事件循环
    loop = asyncio.get_event_loop() # 
    loop.run_until_complete(main()) #

python的缺陷优化

python的弱点就是执行效率低,开源的,不好加密

  • 提高性能
    • 内置函数(优化求质数)
    • IO耗时,多线程&协程 异步 (异步爬虫)
    • 计算耗时,C扩展 (优化斐波那契数列)
      斐波纳契数列以递归的方法定义:
      在这里插入图片描述
      从第三项开始,每一项都等于前两项之和。
      C扩展案例
# python实现
import time


# 斐波那契数列计算
def fibonacci(n):
    if n == 0 or n == 1:
        return 1

    return fibonacci(n - 1) + fibonacci(n - 2)


def calc_perform(n):
    start_time = time.perf_counter()
    
    result = fibonacci(n)

    end_time = time.perf_counter()

    print("fibonacci result:", result)
    print("total time: %.3fs" % (end_time - start_time))


if __name__ == '__main__':
    calc_perform(35)
	# 
	# fibonacci result: 14930352
	# total time: 2.763s


# C实现
#include <stdio.h>  //标准输入输出头文件
#include <time.h>  


int fibonacci(int n) {
	if (n == 0 || n == 1) {
		return 1;
	}
	return fibonacci(n - 1) + fibonacci(n - 2);
}


// 定义一个返回int的主函数
int main() {
	clock_t start_time = 0, end_time = 0;
	start_time = clock();
	int result;
	result = fibonacci(35);
	end_time = clock();
	printf("fibonacci result: %d\n", result);
	printf("total time: %.3f\n", (double)(end_time - start_time) / CLOCKS_PER_SEC);


	// 函数体结束
	return 0;
}

# 编译
gcc -fPIC xxx.c -shared -o xxx.dll

用C 实现计算逻辑,python调用C的函数。

  • 源码保护
    • Cython加密 (演示源码加密)
      Cython加密案例
from setuptools import setup
from Cython.Build import cythonize


setup(ext_modules=cythonize(["coroutine.py", ], language_level=3), script_args=["build_ext", "--inplace"])

然后命令下执行python setup.py

 

python的编码规范

  • 模块名、函数名、变量名,使用小写单词+下划线方式命名;
  • 类名使用大驼峰方式,实例属性定义在构造函数中;
  • 常量全部大写;
  • 获取字典的值使用get;
  • 缩进不能tab/space 混合使用;
  • 导入包、模块不使用*

提升性能总结

  1. 尽量小整数池、字符串驻留等内置的内存优化方案解决问题;
  2. 不用的对象及时清除引用,避免循环引用;
  3. 巧用生成器节约内存。
  4. IO密集型,使用多线程;
  5. CPU密集型,使用协程;
  6. 终极性能提升使用C扩展。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Android强大的原生调试工具adb的常用命令

文章目录 ADB简介常用命令列出链接的设备进入设备的shell环境设备日志安装应用程序卸载应用程序将本地文件复制到调试设备上将设备上的文件拉取到本地启动程序强制停止程序运行截图屏幕录制列出调试设备所有的应用的报名 结语 ADB简介 ADB&#xff08;Android Debug Bridge&am…

【从零开始学习JAVA | 第二十一篇】常见API介绍 System

目录 前言&#xff1a; System&#xff1a; System类中静态方法&#xff1a; 总结&#xff1a; 前言&#xff1a; system 是一个很底层的 API&#xff0c;是一个工具类&#xff0c;提供了一些与系统相关的方法。他在我们写项目的时候提供了一些非常实用的方法&#xff0c;本…

量子机器学习Variational Quantum Classifier (VQC)简介

变分量子分类器&#xff08;Variational Quantum Classifier&#xff0c;简称VQC&#xff09;是一种利用量子计算技术进行分类任务的机器学习算法。它属于量子机器学习算法家族&#xff0c;旨在利用量子计算机的计算能力&#xff0c;潜在地提升经典机器学习方法的性能。 VQC的…

优化--分类树,我从2s优化到0.1s

1.前言 分类树查询功能&#xff0c;在各个业务系统中可以说随处可见&#xff0c;特别是在电商系统中。 但就是这样一个简单的分类树查询功能&#xff0c;我们却优化了5次。 到底是怎么回事呢&#xff1f; 2.背景 我们的网站使用了SpringBoot推荐的模板引擎&#xff1a;Thym…

【Python实战】Python采集情感音频

成年人的世界真不容易啊 总是悲伤大于欢喜 爱情因为懵懂而快乐 却走进了复杂和困惑的婚姻 前言 我最近喜欢去听情感类的节目&#xff0c;比如说&#xff0c;婚姻类&#xff0c;我可能老了吧。我就想着怎么把音乐下载下来了&#xff0c;保存到手机上&#xff0c;方便我们业余时…

Jnpf低代码开发平台

一、写在前面 低代码开发平台&#xff0c;一个号称能在几分钟的时间里开发出一套公司内部都可使用的应用系统开发工具。 很多人或许都隐隐听说过低代码&#xff0c;因为低代码不仅远名国外&#xff0c;国内的腾讯、阿里、华为、网易、百度等科技巨头也纷纷入局&#xff0c;足以…

URL到页面: 探索网页加载的神秘过程

当我们从浏览器的地址栏输入 URL, 按下回车, 再到最后出现需要的网页界面, 这中间究竟发生了什么, 接下来就一步步进行解析. 主要是如下过程: 输入网址DNS 解析客户端发送 HTTP 请求建立 TCP 连接服务器处理请求, 计算响应, 返回响应浏览器渲染页面关闭连接 本篇中只是概述整…

docker 操作手册

名词解释 images&#xff1a;封装了应用程序的镜像 tag&#xff1a;镜像的标记&#xff0c;一个镜像可以创建多个标记 container&#xff1a;装载镜像并运行 常用命令 查看容器 docker ps -a //查看全部镜像 启动容器 docker start mysql //启动mysql容器 停止容器 doc…

Maven(三):Maven的组成详解

文章目录 坐标和依赖坐标详解依赖配置依赖范围传递性依赖依赖调节可选依赖优化排除依赖归类依赖优化依赖 仓库本地仓库远程仓库仓库镜像常用搜索地址 生命周期与插件三套生命周期clean生命周期default生命周期site生命周期 插件 聚合与继承更加灵活的构建常见问题使用jdk来运行…

TuyaOS 开发固件OTA上传固件指南

文章目录 一、产品创建二、TuyaOS设备开发三、固件上传 通过TuyaOS接入涂鸦云的产品全部默认支持固件OTA功能&#xff0c;TuyaOS设备实现固件OTA需要&#xff1a; 自定义产品创建TuyaOS嵌入式开发固件上传固件OTA配置与发布 等步骤实现产品OTA。本文重点讲述TuyaOS开发模式下&…

基于数据驱动 U-Net 模型的大气污染物扩散快速预测,提升计算速度近6000倍

项目背景 当前&#xff0c;常见的大气污染预测模型大多是基于物理机理构建的&#xff0c;比如空气质量预测模型 Calpuff、AERMOD、CMAQ 等。然而&#xff0c;这些模型运算较为复杂&#xff0c;对于输入数据的要求非常高&#xff0c;运算耗时也比较长&#xff0c;适合用于常规固…

如何在 ZBrush 和 UE5 中创建精灵吟游诗人(P1)

小伙伴们大家好&#xff0c;今天 云渲染小编给大家带来的是CG艺术家Hugo Sena关于“精灵吟游诗人”项目背后的工作流程&#xff0c;讨论了角色身体、服装和竖琴的工作流程&#xff0c;并解释了如何在虚幻引擎 5 中设置灯光。篇幅较长&#xff0c;分为上下两篇&#xff0c;大家接…

为摸鱼助力:一份Vue3的生成式ElementPlus表单组件

目录 一、实现背景 二、简介 三、组织架构设计 四、实现方式 五、代码示例 六、示例代码效果预览 七、项目预览地址 & 项目源码地址 目前项目还有诸多待完善的地方&#xff0c;大家有好的想法、建议、意见等欢迎再次评论&#xff0c;或于github提交Issues 一、实现…

【吃透网络安全】2023软考网络管理员考点网络安全(三)计算机系统安全评估

涉及知识点 计算机系统安全评估准则&#xff0c;计算机系统安全评估历史&#xff0c;软考网络管理员常考知识点&#xff0c;软考网络管理员网络安全&#xff0c;网络管理员考点汇总。 后面还有更多续篇希望大家能给个赞哈&#xff0c;这边提供个快捷入口&#xff01; 第一节…

解决vue依赖报错SockJSServer.js出现Cannot read property ‘headers‘ of null

前言 在做新的需求需要变更vue的项目代码时突然出现报错 TypeError: Cannot read property ‘headers’ of null at Server.socket.on (***/node_modules/webpack-dev-server/lib/servers/SockJSServer.js:68:32) 不清楚为什么突然出现了这个问题&#xff0c;之前在这个vue项目…

【安全】使用docker安装Nessus

目录 一、准备docker环境服务器&#xff08;略&#xff09; 二、安装 2.1 搜索镜像 2.2 拉取镜像 2.3 启动镜像 三、离线更新插件 3.1 获取challenge 3.2 官方注册获取激活码 3.3 使用challenge码和激活码获取插件下载地址 3.4 下载的插件以及许可协议复制到容器内 四…

数据结构第六章 图 6.4 图的应用 错题整理

4.A A. 不是简单路径的话&#xff0c;有环&#xff0c;去环路径会更短 B. 适合的 弗洛伊德算法才不适合 C. 本来就是 D 2X2矩阵拓展到3X3矩阵 再扩大 若是子集 即加入新顶点后&#xff0c;最短路径都没有变&#xff0c;错 5.B 本题用弗洛伊德更合适 但这道题只需全部代入求最…

PowerShell系列(七)PowerShell当中的Provider介绍

往期回顾PowerShell系列&#xff08;一&#xff09;&#xff1a;PowerShell介绍和cmd命令行的区别 PowerShell系列&#xff08;二&#xff09;&#xff1a;PowerShell和Python之间的差异介绍 PowerShell系列&#xff08;三&#xff09;&#xff1a;PowerShell发展历程梳理 P…

@DateTimeFormat与@JsonFormat不完全解析

目录 前言测试代码DateTimeFormat不加任何注解的情况普通请求JSON请求 JsonFormat普通请求JSON请求 其他方式&#xff08;InitBinder&#xff09;结论源码地址 前言 一直以来对DateTimeFormat与JsonFormat 比较模糊&#xff0c;容易搞忘&#xff0c;今天就做个笔记&#xff0c…

UE4自定义资产类型编辑器实现

在虚幻引擎中&#xff0c;资产是具有持久属性的对象&#xff0c;可以在编辑器中进行操作。 Unreal 附带多种资源类型&#xff0c;从 UStaticMesh 到 UMetasoundSources 等等。 自定义资源类型是实现专门对象的好方法&#xff0c;这些对象需要专门构建的编辑器来进行高效操作。 …