CPP_头文件互相包含

CPP_头文件互相包含

[!Error]+
编写 C++ 代码时偶尔会遇到两个类需要相互引用的情况,如果在 h 文件中相互包含会导致 “has not been declared” 等声明问题,此时需要使用前置声明的方式来解决该问题

Code Example

以一个实际场景为例:假设有工具类 Search Helper 提供一系列搜索功能,还有另一个 ObjectAttr 定义一系列操作对象的属性,在 ObjectAttr 中需要引用 SearchHelper 提供的某个基础函数,而 SearchHelper 中部分针对 ObjectAttr 设计的某些功能则需要将 ObjectAttr 中的类作为入参,此时我们可能会在 h 文件中相互引用;

在 obj_definition.h 中有 GetSelfNearObj 函数,其过程中需要调用 search_helper 中的 GetDistObj 函数进行辅助运算

1
2
3
4
5
6
7
8
9
10
11
#include "util/search_helper.h"
namespace object_info{
class ObjectAttr{
public:
LocationType location;
int ObjId;
int NearObjId;
private:
void GetSelfNearObj();
};
}

在 search_helper.h 中有以下函数定义

1
2
3
4
5
6
7
#include "base/obj_definition.h"
namespace search_helper{
class SearchHelper{
public:
int GetDistObj(const object_info::ObjectAttr & obj1, const object_info::ObjectAttr & obj2);
};
}

这种情况下编译会出现未定义,未声明,not a type 之类缺少类型说明符的错误。

1
error: ... has not been declared

Fix & Analysis

上述错误是由于两个文件构成了循环依赖,类 SearchHelper 依赖于 ObjectAttrObjectAttr 又依赖于 SearchHelper;因此编译器会报错导致无法通过编译;

在这种情况下,可以通过前向声明的方式来解决这种问题,即不去进行循环引用,在search_helper 中不 #include obj_definition.h,但是对需要的 ObjectAttr 进行一个空声明,然后在 .cpp 中 #include obj_definition.h 具体如下,将 H 文件修改为;

1
2
3
4
5
6
7
8
9
10
namespace objct_info{
class ObjectAttr;
}

namespace search_helper{
class SearchHelper{
public:
int GetDistObj(const object_info::ObjectAttr & obj1, const object_info::ObjectAttr & obj2);
};
}

在对应的 .cpp 文件中添加对 obj_definition 的包含,这样在编译过程中,ObjectAttr 会被自动链接到正确的定义;

1
2
3
4
#include "base/obj_definition.h"

// origin cpp file below...
// ...

上述例子展示了不同命名空间下的情况,这里秉持的原则就是不同文件中对类的前置声明要保持一致,无论是命名空间、参数、类型等,在同一个命名空间中的情况要更简单,可以以此类推,这里不再赘述;

Reference

  1. c++ 头文件互相包含问题
  2. c++ 类声明 类前置声明范例

NumpyConcatenate加速

NumpyConcatenate加速

多次循环进行 Numpy Concentrate 操作后,当原始数组变得过大的时,单步处理时间会逐渐变长,处理大量数据的时候时间成本极高。

解决思路

这里简单的讲一下问题的定位过程,通过装饰器 Check 每个函数的执行时间,重点关注执行时长逐渐变长的部分。

1
2
3
4
5
6
7
8
9
10
11
from time import time

def timer(func):
def func_wrapper(*args, **kwargs):
time_start = time()
result = func(*args, **kwargs)
time_end = time()
res = time_end - time_start
print("{} cost time: {} s".format(func.__name__, res))
return result
return func_wrapper

就会发现当 np.Concatenate 导致 Array 很大之后,运行就会逐渐减缓。由于运行缓慢是由于对大数组操作导致的,因此这里考虑将大数组切分成多个小数组,然后再最后进行合并。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
with open(file, 'r') as rf:
for line in rf:
...
new_row_array = ...
key = ...
if len(res_list[key][-1]) == 0 :
res_list[key][-1] = new_row_array
else:
if len(res_list[key][-1]) >= MAX_LENGTH:
res_list[key].append(new_row_array)
else:
res_list[key][-1] = np.concatenate([
res_list[key][-1], new_row_array
])
for i in range(len(res_list)):
res_list[i] = np.concatenate(res_list[i], axis=0)

可以看上述这段代码,通过对-1 的使用,来自动的切分 Array,最后再整体合并,这样就能避免每个数组过大的问题。

本地实验测试也成功,将原本耗时 400s 的处理过程减少到了 30s

Fi


Python00 Conda 与 Pip

Python00 Conda 与 Pip

@Aikenhong 的旧笔记翻新完善 1.0

Python 的灵活和广泛应用场景来自于众多的第三方库,由于强大的可拓展性和众多的库,使得 Python 的使用简单灵活,且应用面极广。

但是不同库之间的相互依赖关系,对版本的不同要求等等因素,使得”环境配置”成为了开发者闻之变色的一词,对一个新的库和项目环境的配置尝尝会花去大量的时间,这可能也是 Docker、Venv(虚拟环境)必须存在的原因之一。

这里不对 Docker 及其相关技术,进行说明,会另开章节进行学习。

才疏学浅的本菜鸡希望从 python 开发者避不开的 conda 和 pip 出发介绍一下关于库安装的一些事情,以及这两个 CLI 的关系。


Bash Notebook 01

Bash Notebook 01

整理脚本编写的一些最基本语法,包括参数传递,赋值,循环等基本语句,方便后续的脚本编写和改动。

语句注释

单行注释:# ,多行注释:

1
2
3
4
:'
多行注释用冒号加单引号即可
'
echo 'legal'

命令行参数传递

命令行传递参数的方式极其简单,$1$9 可分别代表输入的 9 个参数,第 10 个参数则使用 ${10} 表示,可以将其赋予变量后便于使用。

一些特殊参数:

  1. $0 脚本本身的名称
  2. $# 输入参数的数量
  3. $$$$ 进程 ID
  4. $* | $@ 所有参数(从第一个开始
  5. $(PWD) | `pwd` 都能输出当前的工作路径

举个脚本例子如下:

1
2
3
4
5
6
7
8
9
10
11
12
# we accept args from commandline and print it to the screen
# define
args1=$1
args2=$2

# print
echo "using $ { } to get the value of val, what we receive is : ${args1} and ${args2}"
echo "$ can also show : $args1 and $args2"

# we can make those statement in a string, which may transfer to its value
echo "using $ / {} in a string can also get the value like $args1 and $args2"
echo 'using $ / {} in a string single quotes cannot get the value like $args1 and $args2'

Nodejs、yarn、npm关系辨析
Python Unittest 单元测试的编写与执行

Python Unittest 单元测试的编写与执行

该文章将介绍 Python 中的单元测试之 Unittest 模块,及其在 VsCode 中的集成和使用,主要参考的链接有以下的三个:

  1. Unittest的基本用法Python官方文档
  2. VsCode运行Unittest,其对应 VsCode 侧边栏中的“测试”模块,该部分就由本文来自行补充
  3. 使用Unittest模拟input的输入,便于测试基于命令行输入的代码

SQL Chapter5 mysql与事务

SQL Chapter5 mysql与事务

廖雪峰的SQL教程的学习笔记

mySQL

how to connect mysql? Using CMD(or MySQL Client) to carry out

1
2
3
4
# local, default port is 3306
mysql -u root -p
# remote
mysql -h <ip> -u root -p

root here is the <username>, we may using other name in specific situation.

mysql实际上时MySQL的客户端,真正的MySQL服务器程序时mysqld在后台运行。


SQL Chapter4  增删改相关操作

SQL Chapter4 增删改相关操作

基本操作无非就是增删改查,查询在上一章Select已经学习完毕,而剩下的增、删、改对应的关键词分别是:

  • INSERT:插入新纪录
  • UPDATE:更新现有记录
  • DELETE:删除已有记录

接下来具体讨论各种用法:

插入

使用关键字INSERT进行数据和记录的插入,其基本语法如下:

1
INSERT INTO <表名>(字段1,字段2,...) VALUES(值1,值2,...)

例如向students表中插入一条新数据,先列出需要添加数据的字段,然后按照字段的次序添加值

1
2
-- 添加记录
INSERT INTO students (class_id, name, gender, score) value(2,'大牛','M',80);

自增字段(id)或者其他有默认值的字段可以省略。其中需要注意的是:

  • 字段顺序不必和数据库表的字段顺序一致
  • 但是值的顺序必须和字段顺序一致

同时插入多条记录的写法如下:

1
2
3
INSERT INTO students (class_id, name, gender, score) VALUES
(1, '大宝', 'M', 87),
(2, '二宝', 'M', 81);

SQL Chapter3 查询命令

SQL Chapter3 查询命令

该章节介绍SQL中的查询命令,根据廖雪峰网站进行一步步的测试和学习即可。

  • 其中为sql语言中的注释符号。
  • 关键词不区分大小写

基本查询

查询表中的所有数据主要使用关键词SELECT

1
SELECT * FROM <表名>
  • SELECT表明要执行查询
  • *代表“所有列”
  • FROM表明要从哪个表查询

当指定特定列名的时候(也就是所谓的投影查询)格式如下:

1
2
SELECT <KEY1>,<KEY2>, FROM <表名>
-- 注释

此外,许多工具会使用SELECT 1;来测试数据库链接的有效性;SELECT 100+200也可以用来做简单的计算。


SQL Chapter2 安装和基本概念

SQL Chapter2 安装和基本概念

本章节从MySQL的安装到基础使用,MySQL本身只是一个SQL接口,它内部还包含多种数据引擎,常用的包括:

  • InnoDB:支持事务的数据库引擎(不知道选啥的时候选他就好)
  • MyISAM:早期默认,不支持事务

接口和引擎的关系好比浏览器和浏览器引擎,切换MySQL引擎不影响自己写的应用程序使用MySQL的接口,由于其开源,也衍生出了各种开源版本(包括针对各种云存储中托管数据库的版本等)

安装MySQL

Windows直接官网下载对应的版本就好了,Community Version在该超链接进行下载,其他版本就按需下载,按需付费就行。


SQL Chapter1 Introduce

SQL Chapter1 Introduce

SQL相关参考资料:尊重一下菜鸟教程 ,该教程中的文档相对简练和入门,W3School的资料好像就是菜鸟教程的;其次,廖雪峰的SQL教程网站,也应该比较适合入门,对比后选择一个进行学习。

围绕SQL是什么、有什么用、和怎么用来学习。

利用廖雪峰的教程来进行学习,因为其具备在线运行和测试的功能。

SQL是什么

SQL:Structured Query Language(结构化查询语言)用于访问和操作数据库系统:查询、添加、更新、删除、管理、维护。不同的数据库,都支持SQL。

“SQL就是访问和处理关系数据库的计算机标准语言“,无论使用什么编程语言编写程序,当我们涉及到操作关系数据库之时,就需要使用SQL,其中,最流行的开源数据库为MySQL。

同时,现今还存在非SQL的数据库,也就是NoSQL数据库,例如:MongoDB、Cassandra、Dynamo都属于非关系数据库。

而SQL在当今仍然承担各种应用程序的核心数据存储,与NoSQL(作为SQL数据库的补充)相辅相成。


PyTorch Handbook 00 (Archive)
Cherno的cpp教程笔记

Cherno的cpp教程笔记

this notebook is based on Cherno‘s Video Class in YouTube;if there is sth get confused,I can recheck the video which talk about it, or just google it.

  • this is not totally for newbie, so some basic information we should search it
  • And this is a important websize to tell us basic info about C++.

python 与标记语言的交互

python 与标记语言的交互

对于各种形式的标记文档(markup)和数据集的处理进行一个整合,还有一些python中的相关模块(比比如glob,后续可能会迁移到别的文档中),主要包括:yaml,json,csv,xml,这些可拓展的标记语言.

TODO:

  • [ ] csv,xml:这一部分可以看一下吉仲师兄那边是怎么存和取文件的,继承一下代码减少我这一部分的工作量
  • [ ] 按照csv文件对数据集进行本地的文件夹切分。实际上很多数据集,像mini-imageNet这类的是需要我们下载下来之后按照csv文件对训练集和测试集进行切分的
  • [ ] 使用sklearn对完整的未切分数据进行切分。

Python: Glob

文件操作相关模块,用于简单的路径匹配的模块,用来查找路径中的相关文件,基本的正则匹配规则如下:

“*”: 匹配0哥或多个字符

“?” : 匹配单个字符

“[ ]”: 匹配指定范围内的字符,如[0-9]匹配所有的数字

glob.glob:

返回所有匹配的路径列表,只有一个参数pathname,定一乐文件路径的匹配规则,可以是绝对路径或者是相对路径,具体的使用可以参考如下的方式:

1
2
3
4
5
6
7
8
9
10
11
12
for xmlpath in glob.glob('media/all/DATAPART/' + "*")
# xmlpath 遍历文件夹下的所有文件和文件夹

for xmlpath in glob.glob(xmlpath + "/*/*")
# xmlpath 遍历文件夹下所有文件夹中的文件夹中的文件:按照层数自由设定

img_path = sorted(glob.glob(os.path.join(images, '*.npy')))
# 遍历文件夹下的所有npy文件,说实话感觉这个怪离谱的,晚点试一下

import glob
print(glob.glob(r"E:/imgdir/*/*.jpg"))


C++的常见数据类型和操作

C++的常见数据类型和操作

主要介绍一些常用数据类型的一些method,区别还有一些特殊的定义;

priority_queue 默认是大顶堆,great的话是小顶堆,less的话是大顶堆,自定义的话不知道是不是一致的

set默认top是小顶,这个大小我就不知道了,自定义的话,好像和我想得是一致的

所有的动态容器都是存放在heap上的,像是什么Vector,String,unordered_map之类的

指定精度的输出和计算

在腾讯的笔试中出现的需要指定精度和指定的计算精度的分析,在使用常数的时候一定要使用.0去修正一个方法。

Vector 动态数组

Vector中的一些常用的函数,方法,以及一些属性介绍和辨析

emplace_back & push_back(在末尾添加元素)

empalce_back直接在数组的末尾进行构造,而push_back借助于构造的临时变量再将其加入数组末尾,所以在一些操作中empalce_back对于空间时间的效率是会更高的,但是如果我们有重复构筑的数据的话,可能就需要使用push_back

要注意实际上vector中并没有append的方法。


(转)What the Fuck Python! 一些python特性

(转)What the Fuck Python! 一些python特性

What the f*ck Python! 🐍

一些有趣且鲜为人知的 Python 特性.

English | 中文


WTFPL 2.0 Commit id 996.icu

Python, 是一个设计优美的解释型高级语言, 它提供了很多能让程序员感到舒适的功能特性. 但有的时候, Python 的一些输出结果对于初学者来说似乎并不是那么一目了然.

这个有趣的项目意在收集 Python 中那些难以理解和反人类直觉的例子以及鲜为人知的功能特性, 并尝试讨论这些现象背后真正的原理!

虽然下面的有些例子并不一定会让你觉得 WTFs, 但它们依然有可能会告诉你一些你所不知道的 Python 有趣特性. 我觉得这是一种学习编程语言内部原理的好办法, 而且我相信你也会从中获得乐趣!

如果您是一位经验比较丰富的 Python 程序员, 你可以尝试挑战看是否能一次就找到例子的正确答案. 你可能对其中的一些例子已经比较熟悉了, 那这也许能唤起你当年踩这些坑时的甜蜜回忆 :sweat_smile:

PS: 如果你不是第一次读了, 你可以在这里获取变动内容.

那么, 让我们开始吧…


Fluent Python 01 数据模型与结构

Fluent Python 01 数据模型与结构

Chapter 1 数据模型

Se1 magic method

数据模型在这里的定义是对python框架的描述,他规范了python构建模块的接口;这些接口对应解释器中对一些特殊句法(常用句法)的激活和使用.本章节的核心就在于对这些特殊句法的理解和使用.
特殊方法带来的一些主要交互场景:

  • 迭代
  • 属性访问
  • 集合类
  • 函数和方法的调用
  • 对象的创建和销毁
  • 字符串的表示形式和格式化
  • 上下文管理模块(with模块)

这些特殊方法的存在实际上,是为了让python的解释器调用,除非我们有大量的元编程,否则我们一般不调用他,通过内置的len等函数进行调用的话,他们的速度更快

下面我们通过最典型的__getitem____len__对其有简单的介绍, 并介绍各个魔术方法的使用场景

Se2 using it and show more

最常用也最典型的magic method 不外乎__getitem____len__;

  • len即对当前对象提供对于通用的len()方法的接口,通常用于查看对象的length or size
  • getitem除了提供obj[index]的索引方式的同时,
    • 他也会对python内置的那些迭代方法提供支持for i in range(b)
    • 对于依托于这些迭代的方法也能够得以支持from random import choice
    • 切片操作

Se2.1 overwrite operator


Python01 数据模型和常用数据结构

Python01 数据模型和常用数据结构

个人的《Python Cookbook》 && 《Fluent Python》阅读笔记。

数据模型(Python结构的通用范式)

(Magic method)dunder method:Python特有的双下划线方法,这些方法能够支持Python进行特殊的调用,实现通用方法在新定义的数据结构上的使用,比如最典型的:

  • __len__()后可以支持len(),获得结构的长度
  • __getitem__()后可以支持data[index]来获取相应的元素,切片,等等数组的操作;

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    # 也可以支持类似如下的一些操作
    # 从数据结构中随机选出一个items
    from random import choice
    choice(datas)
    # 也可以支持迭代方法和反迭代方法
    for data in datas:
    ...
    for data in reversed(datas):
    ...
    # 也可以支持sort函数

到这里也就说明了,只要我们在数据结构(class)中定义了相应的dunder method,该class就能支持相应的一系列操作,getitems就可以类比为列表,相应的操作都能够在python解释器下自动的赋予支持。

还有一些好用但不常用的方法:

  • __contain__实现的是in ,当没有实现contain的方法的时候会按照顺序在list中进行搜索
  • __abs__
  • __repr__实现的是输出的format设置,也就是print的时候的输出形式
  • __eq__ 实现的是 == 命令,同时in调用的是eq

下面附上一张特殊方法表:


Markdown Handbook

Markdown Handbook

参考资料

一些关于markdown语法的参考资料,但是实际上如果用Typora的话,有很多的语法是不需要记忆的,只需要稍微了解就可以了,更需要学习的其实是Latex的公式编写。

  1. 基本语法:https://www.jianshu.com/p/191d1e21f7ed
  2. 进阶语法:https://blog.csdn.net/m0_37925202/article/details/80461714
  3. 其他语法:https://blog.csdn.net/cuishizun/article/details/80311673

目录:

Editor:

  • Obsidian、Nvim、Typora:Notes的主力编写工具
  • VsCode:Readme文档
  • Jupyter:代码笔记编写的时候

Some daily usage:

操作名称 Typora VsCode
跳转 [button] (#name)-># [button] (#name)-> \
复选框 - [ ] - [ ]