功能
合并前景与背景两张图片,可设置图片前景的透明度,缩放因子,位置,可自适应调整背景大小并且输出图片所在边界框位置,用于标注数据
实现
利用PIL包,将两张图片进行 paste
通过修改图片 alpha 值,对图片透明度进行修改
对图片的大小处理,获取最终的图片尺寸
根据调整后的前景图片尺寸,调整背景的尺寸
对前景边界框进行处理,得到合理的边界坐标
代码
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263def xywh2xyxyxyxy(x,y,w,h): return [[x,y],[x+w,y],[x+w,y+h],[x,y+h]]def merge_image(fore_image, back_image, pos=(0,0),alpha=1.0,factor=1.0,padding=False,func=lambda x:x): """将两个图片 ...
更新2022-10-26-CUDA11.8
注:当前所有版本要求均为CUDA官方提供
CUDA 11.8 组件版本
Table 1. CUDA 11.8 Component Versions
Component Name
Version Information
Supported Architectures
CUDA C++ Core Compute Libraries
11.8.89
x86_64, POWER, AArch64
CUDA Compatibility
11.8.31339915
AArch64
CUDA Runtime (cudart)
11.8.89
x86_64, POWER, AArch64
cuobjdump
11.8.86
...
《提高C++性能的编程技术》这本书是2011年出版的,书中有些内容的介绍可能已经过时,已不再适用于现在的C++编程中,但大部分内容还是很有参考意义的。
笔记列表
《提高C++性能的编程技术》笔记:总结
《提高C++性能的编程技术》笔记:跟踪
《提高C++性能的编程技术》笔记:构造函数、析构函数
《提高C++性能的编程技术》笔记:临时对象
《提高C++性能的编程技术》笔记:内存池(单线程、多线程)
《提高C++性能的编程技术》笔记:内联
《提高C++性能的编程技术》笔记:STL
《提高C++性能的编程技术》笔记:引用计数
《提高C++性能的编程技术》笔记:编码优化
《提高C++性能的编程技术》笔记:设计优化/可扩展性/系统体系结构
跟踪实例
最理想的跟踪性能优化的方法应该能够完全消除性能开销,即把跟踪调用嵌入在#ifdef块内。使用这种方法的不足在于必须重新编译程序来打开或关闭跟踪。
影响C++性能的因素:I/O的开销是高昂的;函数调用的开销是要考虑的一个因素,因此我们应该将短小的、频繁调用的函数内联;复制对象的开销是高昂的,最好选择传递引用,而不是传递值。
内联对大 ...
笔记列表
《提高C++性能的编程技术》笔记:总结
《提高C++性能的编程技术》笔记:跟踪
《提高C++性能的编程技术》笔记:构造函数、析构函数
《提高C++性能的编程技术》笔记:临时对象
《提高C++性能的编程技术》笔记:内存池(单线程、多线程)
《提高C++性能的编程技术》笔记:内联
《提高C++性能的编程技术》笔记:STL
《提高C++性能的编程技术》笔记:引用计数
《提高C++性能的编程技术》笔记:编码优化
《提高C++性能的编程技术》笔记:设计优化/可扩展性/系统体系结构
设计优化
我们可以粗略地将性能优化分为两种类型:编码优化和设计优化。编码优化定义为不需要完整理解要解决的问题或者应用程序的执行流程就能实施的优化。通过定义看出,编码优化用于局部代码,同时该过程不牵涉周围的代码。除了这些容易实现的优化之外,剩下的所有优化都可以归结为设计优化。这些优化是系统性的----它们依赖于其它组件甚至一些关联度很低的模块的代码。设计优化贯穿于所有代码。
设计灵活性:软件库是通用的,但应用程序却不是。将关注的焦点集中于代码的细节将会产生更高效的代码。可以通过降低灵活性 ...
笔记列表
《提高C++性能的编程技术》笔记:总结
《提高C++性能的编程技术》笔记:跟踪
《提高C++性能的编程技术》笔记:构造函数、析构函数
《提高C++性能的编程技术》笔记:临时对象
《提高C++性能的编程技术》笔记:内存池(单线程、多线程)
《提高C++性能的编程技术》笔记:内联
《提高C++性能的编程技术》笔记:STL
《提高C++性能的编程技术》笔记:引用计数
《提高C++性能的编程技术》笔记:编码优化
《提高C++性能的编程技术》笔记:设计优化/可扩展性/系统体系结构
缓存:在现代处理器中,缓存经常与处理器中的数据缓存和指令缓存联系在一起。缓存主要用来存储使用频繁而且代价高昂的计算结果,这样就可以避免对这些结果的重复计算。如,循环内对常量表达式求值是一种常见的低性能问题。
预先计算:预先计算和缓存联系紧密。当缓存某个计算的结果时,需要付出的代价是在对性能有重大影响的关键路径上完成一次计算。如果采用预先计算,那么甚至连这一次计算也可免了。将预先计算放置在影响性能的关键路径之外(例如初始化阶段),就可以避免在性能关键路径上进行代价高昂的计算。
降低灵活性:使 ...
笔记列表
《提高C++性能的编程技术》笔记:总结
《提高C++性能的编程技术》笔记:跟踪
《提高C++性能的编程技术》笔记:构造函数、析构函数
《提高C++性能的编程技术》笔记:临时对象
《提高C++性能的编程技术》笔记:内存池(单线程、多线程)
《提高C++性能的编程技术》笔记:内联
《提高C++性能的编程技术》笔记:STL
《提高C++性能的编程技术》笔记:引用计数
《提高C++性能的编程技术》笔记:编码优化
《提高C++性能的编程技术》笔记:设计优化/可扩展性/系统体系结构
引用计数(reference counting):基本思想是将销毁对象的职责从客户端代码转移到对象本身。对象跟踪记录自身当前被引用的数目,在引用计数达到零时自行销毁。换句话说,对象不再被使用时自行销毁。
引用计数和执行速度之间的关系是与上下文紧密关联的。该关系取决于以下几个因素:
(1). 目标对象的资源消耗量集中于哪些方面?如果目标对象使用过多内存,比如未保护内存,将使可用内存受限,并导致显著的性能损失,表现为缓存命不中和页面错误。
(2). 分配(释放)目标对象所使用资源的代价有多高? ...
笔记列表
《提高C++性能的编程技术》笔记:总结
《提高C++性能的编程技术》笔记:跟踪
《提高C++性能的编程技术》笔记:构造函数、析构函数
《提高C++性能的编程技术》笔记:临时对象
《提高C++性能的编程技术》笔记:内存池(单线程、多线程)
《提高C++性能的编程技术》笔记:内联
《提高C++性能的编程技术》笔记:STL
《提高C++性能的编程技术》笔记:引用计数
《提高C++性能的编程技术》笔记:编码优化
《提高C++性能的编程技术》笔记:设计优化/可扩展性/系统体系结构
标准模板库(Standard Template Library, STL)是容器和通用算法的强效组合。
渐近复杂度:算法的渐近复杂度是对算法性能的近似估计。它是算法集到特定性能标准集的映射。如果需要对包含N个整数的向量的所有元素求和,那么每个整数必须且仅需检查一次,因此该算法的复杂度约为N,我们将其称为O(N)。另一方面,假设需要创建一个包含N个元素的向量,由于某种原因,你需要将这些元素插入到该向量的前端。然而,在向量的前端每插入一个元素便会迫使所有已存在的元素移动1个位置。这就导致了(1 ...
笔记列表
《提高C++性能的编程技术》笔记:总结
《提高C++性能的编程技术》笔记:跟踪
《提高C++性能的编程技术》笔记:构造函数、析构函数
《提高C++性能的编程技术》笔记:临时对象
《提高C++性能的编程技术》笔记:内存池(单线程、多线程)
《提高C++性能的编程技术》笔记:内联
《提高C++性能的编程技术》笔记:STL
《提高C++性能的编程技术》笔记:引用计数
《提高C++性能的编程技术》笔记:编码优化
《提高C++性能的编程技术》笔记:设计优化/可扩展性/系统体系结构
内联类似于宏,在调用方法内部展开被调用方法,以此来代替方法的调用。一般来说表达内联意图的方式有两种:一种是在定义方法时添加内联保留字的前缀;另一种是在类的头部声明中定义方法。
虽然内联方法的调用方式和普通方法相同,但其编译过程却相差甚远。由于内联方法的代码必须内联展开,这就要求调用内联方法的代码段必须有权访问该内联方法的定义。而内联方法的定义需要整合到其调用方法之中,这就使得任何针对内联方法的更改,都将引起所有调用该方法模块的重新编译。所以,内联在显著提升性能的同时,也增加了编译时间。编译 ...
笔记列表
《提高C++性能的编程技术》笔记:总结
《提高C++性能的编程技术》笔记:跟踪
《提高C++性能的编程技术》笔记:构造函数、析构函数
《提高C++性能的编程技术》笔记:临时对象
《提高C++性能的编程技术》笔记:内存池(单线程、多线程)
《提高C++性能的编程技术》笔记:内联
《提高C++性能的编程技术》笔记:STL
《提高C++性能的编程技术》笔记:引用计数
《提高C++性能的编程技术》笔记:编码优化
《提高C++性能的编程技术》笔记:设计优化/可扩展性/系统体系结构
单线程内存池
频繁地分配和回收内存会严重地降低程序的性能。性能降低的原因在于默认的内存管理是通用的。应用程序可能会以某种特定的方式使用内存,并且为不需要的功能付出性能上的代价。通过开发专用的内存管理器可以解决这个问题。对专用内存管理器的设计可以从多个角度考虑。我们至少可以想到两个方面:大小和并发。
从大小的角度分为以下两种:
(1)、固定大小:分配固定大小内存块的内存管理器。
(2)、可变大小:分配任意大小内存块的内存管理器。所请求分配的大小事先是未知的。
类似的,从并发的角度也分为以下两 ...
笔记列表
《提高C++性能的编程技术》笔记:总结
《提高C++性能的编程技术》笔记:跟踪
《提高C++性能的编程技术》笔记:构造函数、析构函数
《提高C++性能的编程技术》笔记:临时对象
《提高C++性能的编程技术》笔记:内存池(单线程、多线程)
《提高C++性能的编程技术》笔记:内联
《提高C++性能的编程技术》笔记:STL
《提高C++性能的编程技术》笔记:引用计数
《提高C++性能的编程技术》笔记:编码优化
《提高C++性能的编程技术》笔记:设计优化/可扩展性/系统体系结构
类型不匹配:一般情况是指当需要X类型的对象时提供的却是其它类型的对象。编译器需要以某种方式将提供的类型转换成要求的X类型。这一过程可能会产生临时对象。
按值传递:创建和销毁临时对象的代价是比较高的。倘若可以,我们应该按指针或者引用来传递对象以避免生成临时对象。
按值返回:如果编写的函数是按值返回对象(与引用或者指针相对),就很可能生成临时对象。
可以使用operator=()消除临时对象。
临时对象会以构造函数和析构函数的形式降低一半的性能。
将构造函数声明为explicit,可以阻止编译 ...
笔记列表
《提高C++性能的编程技术》笔记:总结
《提高C++性能的编程技术》笔记:跟踪
《提高C++性能的编程技术》笔记:构造函数、析构函数
《提高C++性能的编程技术》笔记:临时对象
《提高C++性能的编程技术》笔记:内存池(单线程、多线程)
《提高C++性能的编程技术》笔记:内联
《提高C++性能的编程技术》笔记:STL
《提高C++性能的编程技术》笔记:引用计数
《提高C++性能的编程技术》笔记:编码优化
《提高C++性能的编程技术》笔记:设计优化/可扩展性/系统体系结构
虚函数:在以下几个方面,虚函数可能会造成性能损失:构造函数必须初始化vptr(虚函数表);虚函数是通过指针间接调用的,所以必须先得到指向虚函数表的指针,然后再获得正确的函数偏移量;内联是在编译时决定的,编译器不可能把运行时才解析的虚函数设置为内联。
无法内联虚函数造成的性能损失最大。
某些情况下,在编译期间解析虚函数的调用是可能的,但这是例外情况。由于在编译期间不能确定所调用的函数所属的对象类型,所以大多数虚函数调用都是在运行期间解析的。编译期间无法解析对内联造成了负面影响。由于内联是在编 ...
笔记列表
《提高C++性能的编程技术》笔记:总结
《提高C++性能的编程技术》笔记:跟踪
《提高C++性能的编程技术》笔记:构造函数、析构函数
《提高C++性能的编程技术》笔记:临时对象
《提高C++性能的编程技术》笔记:内存池(单线程、多线程)
《提高C++性能的编程技术》笔记:内联
《提高C++性能的编程技术》笔记:STL
《提高C++性能的编程技术》笔记:引用计数
《提高C++性能的编程技术》笔记:编码优化
《提高C++性能的编程技术》笔记:设计优化/可扩展性/系统体系结构
对象的创建和销毁往往会造成性能的损失。在继承层次中,对象的创建将引起其先辈的创建。对象的销毁也是如此。其次,对象相关的开销与对象本身的派生链的长度和复杂性相关。所创建的对象(以及其后销毁的对象)的数量与派生的复杂度成正比。
并不是说继承根本上就是代码性能的绊脚石。我们必须区分全部计算开销、必须开销和计算损失(computional penalty). 全部计算开销是一次计算中所执行的全部指令的总和。必须开销是全部指令的子集,它的结果是必要的。这部分计算是必需的,其余部分即为计算损失。计算损 ...
笔记列表
《提高C++性能的编程技术》笔记:总结
《提高C++性能的编程技术》笔记:跟踪
《提高C++性能的编程技术》笔记:构造函数、析构函数
《提高C++性能的编程技术》笔记:临时对象
《提高C++性能的编程技术》笔记:内存池(单线程、多线程)
《提高C++性能的编程技术》笔记:内联
《提高C++性能的编程技术》笔记:STL
《提高C++性能的编程技术》笔记:引用计数
《提高C++性能的编程技术》笔记:编码优化
《提高C++性能的编程技术》笔记:设计优化/可扩展性/系统体系结构
当提高性能时,我们必须记住以下几点:
(1). 内存不是无限大的。虚拟内存系统使得内存看起来是无限的,而事实上并非如此。
(2). 内存访问开销不是均衡的。对缓存、主内存和磁盘的访问开销不在同一个数量级之上。
(3). 我们的程序没有专用的CPU,只能间歇地获得一个时间片。
(4). 在一台单处理器的计算机上,并行的线程并不是真正地并行执行,它们是轮询的。
“性能”可以有几种衡量标准,最常见的两种是空间效率和时间效率。空间效率标准寻求占用最小内存的软件解决方案。相似的,时间效率标准寻求占用 ...
TVM 学习指南
0x0. 前言
最近粗略的看完了天奇大佬的MLC课程(顺便修了一些语法和拼写错误,也算是做了微弱的贡献hh),对TVM的近期发展有了一些新的认识。之前天奇大佬在《新一代深度学习编译技术变革和展望》一文中讲解了TVM Unify也即统一多层抽象的概念。这里的统一多层抽象具体包括AutoTensorization用来解决硬件指令声明和张量程序对接,TVM FFI(PackedFunc)机制使得我们可以灵活地引入任意的算子库和运行库函数并且在各个编译模块和自定义模块里面相互调用。TensorIR负责张量级别程序和硬件张量指令的整合。Relax (Relax Next) 引入relay的进一步迭代,直接引入first class symbolic shape的支持 (摘抄自《新一代深度学习编译技术变革和展望》一文)。然后这些抽象可以相互交互和联合优化来构造深度学习模型对应的最终部署形式。我个人感觉TVM Unify类似于MLIR的Dialect,但是这几个抽象的直接交互能力相比于MLIR的逐级lower我感觉是更直观方便的,毕竟是Python First(这个只是我最近看ML ...
在 jupyter notebook 中显示图片,推荐用 plt.imshow() ,读取正常使用 opencv 即可
对于RGB图像显示,结果要加[:,:,::-1],将opencv的 bgr 转为 rgb
灰度图直接显示即可
安装依赖库
12pip install matplotlib -qpip install opencv-python -q
使用
123456789import cv2from matplotlib import pyplot as plt%matplotlib inlineim = cv2.imread(IMG_PATH,1) # load image as bgrim2 = im[:,:,::-1] # transform image to rgbplt.imshow(im2)plt.show()
演示结果
问题
Jupyter Notebook使用过程中,突然就停掉了
Jupyter Notebook上面的代码部分无法显示,无法执行操作
问题来源
在安装python库过程中会安装 pyzmq 的库,由于 pyzmq 对python版有限制导致jupyter notebook奔溃
解决方案
替换 pyzmq 库,过程中会涉及到其他库不能使用也需要替换其他版本,以下命令直接覆盖原有库,装完之后就可以正常使用。
1234pip install jupyter-console==6.4.0 -qpip install jupyter-client==6.1.12 -qpip install pyzmq==19.0.2 -q
参考
https://blog.csdn.net/weixin_52096278/article/details/126568679
设计模式与范式:创建型
单例设计模式(Singleton Design Pattern)
单例的定义
单例设计模式(Singleton Design Pattern)理解起来⾮常简单。⼀个类只允许创建⼀个对象(或者叫实例),那这个类就是⼀个单例类,这种设计模式就叫作单例设计模式,简称单例模式。
单例的⽤处
从业务概念上,有些数据在系统中只应该保存⼀份,就⽐较适合设计为单例类。⽐如,系统的配置信息类。除此之外,我们还可以使⽤单例解决资源访问冲突的问题。
单例存在哪些问题
单例对 OOP 特性的⽀持不友好
单例会隐藏类之间的依赖关系
单例对代码的扩展性不友好
单例对代码的可测试性不友好
单例不⽀持有参数的构造函数
单例有什么替代解决⽅案?
为了保证全局唯⼀,除了使⽤单例,我们还可以⽤静态⽅法来实现。不过,静态⽅法这种实现思路,并不能解决我们之前提到的问题。如果要完全解决这些问题,我们可能要从根上,寻找其他⽅式来实现全局唯⼀类了。⽐如,通过⼯⼚模式、IOC 容器(⽐如 Spring IOC 容器)来保证,由程序员⾃⼰来保证(⾃⼰在编写代码的时候⾃⼰保证不要创建两个类对象)。
有⼈把单例当 ...
规范与重构
为什么要重构
⾸先,重构是时刻保证代码质量的⼀个极其有效的⼿段,不⾄于让代码腐化到⽆可救药的地步。项⽬在演进,代码不停地在堆砌。如果没有⼈为代码的质量负责任,代码总是会往越来越混乱的⽅向演进。当混乱到⼀定程度之后,量变引起质变,项⽬的维护成本已经⾼过重新开发⼀套新代码的成本,想要再去重构,已经没有⼈能做到了。
其次,优秀的代码或架构不是⼀开始就能完全设计好的,就像优秀的公司和产品也都是迭代出来的。我们⽆法100% 遇⻅未来的需求,也没有⾜够的精⼒、时间、资源为遥远的未来买单,所以,随着系统的演进,重构代码也是不可避免的。
重构是避免过度设计的有效⼿段。在我们维护代码的过程中,真正遇到问题的时候,再对代码进⾏重构,能有效避免前期投⼊太多时间做过度的设计,做到有的放⽮。
除此之外,重构对⼀个⼯程师本身技术的成⻓也有重要的意义。
从前⾯我给出的重构的定义来看,重构实际上是对我们学习的经典设计思想、设计原则、设计模式、编程规范的⼀种应⽤。重构实际上就是将这些理论知识,应⽤到实践的⼀个很好的场景,能够锻炼我们熟练使⽤这些理论知识的能⼒。除此之外,平时堆砌业务逻辑,你可能总觉得没啥成⻓ ...
前言
本文使用的YOLOv5版本为v6.1,根据不同的了解情况查看对应的文章。
Post not found: yolo系列/简单谈谈yolov5-6-x-网络模型(含代码) 简单谈谈yolov5-6-x-网络模型(含代码)
Post not found: yolo系列/yolov5魔改教程之backbone yolov5魔改教程之backbone
Post not found: yolo系列/yolov5魔改教程之注意力机制 yolov5魔改教程之注意力机制
另外,本文所使用的实验环境为1个GTX 1080 GPU,数据集为 VOC2007,超参数为 hyp.scratch-low.yaml,训练200个epoch,其他参数均为源码中默认设置的数值。
YOLOv5中修改网络结构的一般步骤:
models/common.py:在common.py文件中,加入要修改的模块代码
models/yolo.py:在yolo.py文件内的 parse_model函数里添加新模块的名称
models/new_model.yaml:在models文件夹下新建模块对应的.yaml文件
...
前言
本文使用的YOLOv5版本为v6.1,对YOLOv5-6.x网络结构还不熟悉的同学们,可以移步至:【YOLOv5-6.x】网络模型&源码解析
本文使用的YOLOv5版本为v6.1,根据不同的了解情况查看对应的文章。
Post not found: yolo系列/简单谈谈yolov5-6-x-网络模型(含代码) 简单谈谈yolov5-6-x-网络模型(含代码)
Post not found: yolo系列/yolov5魔改教程之backbone yolov5魔改教程之backbone
Post not found: yolo系列/yolov5魔改教程之注意力机制 yolov5魔改教程之注意力机制
另外,本文所使用的实验环境为1个GTX 1080 GPU,数据集为 VOC2007,超参数为 hyp.scratch-low.yaml,训练200个epoch,其他参数均为源码中默认设置的数值。
YOLOv5中修改网络结构的一般步骤:
models/common.py:在 common.py文件中,加入要修改的模块代码
models/yolo.py:在yolo.p ...
前言
本文使用的YOLOv5版本为v6.1,根据不同的了解情况查看对应的文章。
Post not found: yolo系列/简单谈谈yolov5-6-x-网络模型(含代码) 简单谈谈yolov5-6-x-网络模型(含代码)
Post not found: yolo系列/yolov5魔改教程之backbone yolov5魔改教程之backbone
Post not found: yolo系列/yolov5魔改教程之注意力机制 yolov5魔改教程之注意力机制
YOLOv5是Ultralytics公司的开源项目,点击查看项目地址,更新速度非常快,最新版的v6.1于2022年2月22日发布,目前star数22.7k。
YOLOv5更新日志:
2020年6月26日发布v1.0
… … …
2021年4月12日发布v5.0
2021年10月12日发布v6.0
2022年2月22日发布v6.1
下面对v6.x版本的网络模型及各个组件,结合源码和网络框图进行解析。
整体网络结构
v5.x网络结构
v6.x网络结构
可以看出,相比于之前v5.x,最新版的v6.x网络结构更加精简 ...
os and os.path
pathlib
os.path.abspath()
Path.resolve()
绝对路径
os.chmod()
Path.chmod()
os.mkdir()
Path.mkdir()
创建目录
os.rename()
Path.rename()
重命名
os.replace()
Path.replace()
替换
os.rmdir()
Path.rmdir()
删除目录
os.remove(),os.unlink()
Path.unlink()
os.getcwd()
Path.cwd()
获取当前目录
os.path.exists()
Path.exists()
判断路径存在
os.path.expanduser()
Path.expanduser()andPath.home()
os.path.isdir()
Path.is_dir()
判断目录
os.path.isfile()
Path.is_file()
判断文件
os.path.islink()
Path.is_symli ...
公式识别
1. 具有计数感知的手写数学公式识别算法
ECCV 2022
Title: When Counting Meets HMER:Counting-Aware Network for Handwritten Mathematical Expression Recognition
Paper: https://arxiv.org/pdf/2207.11463.pdf
Code: https://github.com/LBH1024/CAN
视频OCR
基于基于对比学习和多信息表征的端到端视频OCR模
ECCV2022
Title: Real-time End-to-End Video Text Spotter with Contrastive Representation Learning
Paper: https://arxiv.org/abs/2207.08417
Code: https://github.com/weijiawu/CoText
设计原则
SOLID 原则
单⼀职责(Single Responsibility Principle)
单⼀职责(SRP):Single Responsibility Principle,⼀个类只负责完成⼀个职责或者功能。不要设计⼤⽽全的类,要设计粒度⼩、功能单⼀的类。单⼀职责原则是为了实现代码⾼内聚、低耦合,提⾼代码的复⽤性、可读性、可维护性。
JAVAPYTHONC++1234567891011121314public class UserInfo { private long userId; private String username; private String email; private String telephone; private long createTime; private long lastLoginTime; private String avatarUrl; private String provinceOfAddress; // 省 private String cityOfAddress; // 市 ...
⾯向对象
编程范式
⾯向过程
⾯向对象
函数式编程
什么是⾯向对象编程?
⾯向对象编程的英⽂缩写是 OOP,全称是 Object Oriented Programming。对应地,⾯向对象编程语⾔的英⽂缩写是 OOPL,全称是 Object Oriented Programming Language。
⾯向对象编程中有两个⾮常重要、⾮常基础的概念,那就是类(class)和对象(object)。这两个概念最早出现在1960 年,在 Simula 这种编程语⾔中第⼀次使⽤。⽽⾯向对象编程这个概念第⼀次被使⽤是在 Smalltalk 这种编程语⾔中。Smalltalk 被认为是第⼀个真正意义上的⾯向对象编程语⾔。
如果⾮得给出⼀个定义的话,我觉得可以⽤下⾯两句话来概括
⾯向对象编程是⼀种编程范式或编程⻛格。它以类或对象作为组织代码的基本单元,并将封装、抽象、继承、多态四个特性,作为代码设计和实现的基⽯ 。
⾯向对象编程语⾔是⽀持类或对象的语法机制,并有现成的语法机制,能⽅便地实现⾯向对象编程四⼤特性(封装、抽象、继承、多态)的编程语⾔。
⾯向对象编程是⼀种编程范式或编程⻛格。它以类或 ...
前⾔
什么是设计模式
设计模式讲的是如何写出可扩展、可读、可维护的⾼质量代码,所以,它们跟平时的编码会有直接的关系,也会直接影响到你的开发能⼒。
为什么要学习设计模式
应对⾯试中的设计模式相关问题。
告别写被⼈吐槽的烂代码。我⻅过太多的烂代码,⽐如命名不规范、类设计不合理、分层不清晰、没有模块化概念、代码结构混乱、⾼度耦合等等。这样的代码维护起来⾮常费劲,添加或者修改⼀个功能,常常会牵⼀发⽽动全身,让你⽆从下⼿,恨不得将全部的代码删掉重写!
提⾼复杂代码的设计和开发能⼒。
让读源码、学框架事半功倍。
为你的职场发展做铺垫
如何评价代码质量的⾼低?
仔细看前⾯罗列的所有代码质量评价标准,你会发现,有些词语过于笼统、抽象,⽐较偏向对于整体的描述,⽐如优雅、好、坏、整洁、清晰等;有些过于细节、偏重⽅法论,⽐如模块化、⾼内聚低耦合、⽂档详尽、分层清晰等;有些可能并不仅仅局限于编码,跟架构设计等也有关系,⽐如可伸缩性、可⽤性、稳定性等。
为了做到有的放⽮、有重点地学习,我挑选了其中⼏个最常⽤的、最重要的评价标准,来详细讲解,其中就包括:可维护性、可读性、可扩展性、灵活性、简洁性(简单、复杂) ...
开发过程难免需要使用到不同的系统,一种方式是使用虚拟机创建系统,实现在一个机器上操作多个系统,但这种方式一个明显不足就是,因为硬件配置不够高,导致系统流畅度下降,反而影响开发效率;另一种也就是这篇文章重点讲解的内容,使用 SSH连接多台电脑,多个虚拟机,相比较第一种方式在流畅度和体验上堪称完美。
接下来,讲一下 ssh连接的作用吧!
使用ssh连接vmware的虚拟机,不管是连接windows还是linux,都比直接在界面上操作更加流畅,本人使用过程基本没遇到卡死的情况。
ssh 除了可以连接本地的,还可以连接远程服务器
ssh 能够让你在一台机器上操作“无数"个系统,不用在来回切换不同的系统了,真香啊。
开启SSH
Windows
安装OpenSSH服务器
开始 → 设置 → 应用 →可选功能,确保已经装好OpenSSH服务器,一般来说默认安装OpenSSH客户端。如果没有安装,则需要在“添加功能”里搜到并安装。
检查 SSH
右键Windows → Windows PowerShell (管理员) → 出现命令行窗口,如下图
在命令行中输入 ssh 以及 n ...
操作系统
未读MacOS
Code
获取系统版本
关于MacOS更多系统版本号,可参照Post not found: Xcode与MacOS版本对应 Xcode与MacOS版本对应
12345678910111213char* getSystemInfo(){ char buf[1024]; unsigned buflen = 0; char line[256]; FILE *sw_vers = popen("sw_vers", "r"); while (fgets(line, sizeof(line), sw_vers) != NULL) { int l = snprintf(buf + buflen, sizeof(buf) - buflen, "%s", line); buflen += l; assert(buflen < sizeof(buf)); } pclose(sw_vers); return b ...
转念一想,其实工程中需要的操作系统的宏定义是这样的,更多的硬件宏定义就到对应的硬件手册查查。
1234567891011121314151617181920212223242526272829#ifdef _WIN32 //define something for Windows (32-bit and 64-bit, this part is common) #ifdef _WIN64 //define something for Windows (64-bit only) #else //define something for Windows (32-bit only) #endif#elif __APPLE__ #include "TargetConditionals.h" #if TARGET_IPHONE_SIMULATOR // iOS Simulator #elif TARGET_OS_IPHONE // iOS device #elif TARGET_OS ...