打开 console 出现如下提示
1
2
3The default interactive shell is now zsh.
To update your account to use zsh, please run `chsh -s /bin/zsh`.
For more details, please visit https://support.apple.com/kb/HT208050.查看系统支持的shell风格命令:
1
cat /etc/shells
解决方法
- 修改默认 shell:
chsh -s /bin/zsh
- 继续使用bash,但又不想出现提示语,则在 ~/.bash_profile 中添加
export BASH_SILENCE_DEPRECATION_WARNING=1
- 修改默认 shell:
VSCode中pylint插件
修改对 django 项目中的错误语法提示
- 安装 pylint-django 的 Python 包
- 在 settings.json 中添加如下配置
1
2
3
4"python.linting.pylintArgs": [
"--load-plugins",
"pylint_django"
],
原因是
1 | It is nice for a Python module to have a docstring, explaining what the module does, what it provides, examples of how to use the classes. This is different from the comments that you often see at the beginning of a file giving the copyright and license information, which IMO should not go in the docstring (some even argue that they should disappear altogether, see eg. |
原因是
1 | As your code is not contained in a class or function it is expecting those variables to be constants and as such they should be uppercase. |
VSCode通过github同步配置
通过 VSCode 的插件 Settings Sync 可以同步配置信息。
在另外的电脑上需要读取配置的话,将如下 gist id 和 token 都输入到新机器就能同步了。
VSCode中调试django项目
在项目的 launch.json 中添加如下配置:
1 | { |
VSCode中添加代码片段
在 Mac 环境下配置:菜单栏 Code -> 首选项 -> 用户代码片段
自行按需添加如下文件
例如 Python 的头文件可设置为
1 | "PY_HEADER": { |
Markdown 的头文件可设置为
1 | "MD_HEADER": { |
可能遇到的问题:在 Markdown 文件中无法使用代码片段
在 settings.json 中添加如下配置
1 | "[markdown]": { |
Mybatis-实现原理-动态代理.md
转自:https://blog.csdn.net/zzti_erlie/article/details/94396113
mybatis 利用动态代理帮我们生成了接口的实现类,这个类就是 org.apache.ibatis.binding.MapperProxy
静态代理
又是一年毕业季,很多小伙伴开始去大城市打拼。来大城市第一件事就是租房,免不了和中介打交道,因为很多房东很忙,你根本找不到他。从这个场景中就可以抽象出来代理模式
- ISubject: 被访问者资源的抽象
- SubjectImpl: 被访问者具体实现类(房东)
- SubjectProxy: 被访问者的代理实现类(中介)
UML图如下
举个例子来理解一下这个设计模式
老板让记录一下用户服务的响应时间,用代理模式来实现这个功能。
1 | public interface IUserService { |
1 | public class UserServiceImpl implements IUserService { |
1 | public class UserServiceProxy implements IUserService { |
一切看起来都非常的美好,老板又发话了,把产品服务的响应时间也记录一下吧。又得写如下 3 个类
- IProductService
- ProductServiceImpl
- ProductServiceProxy
UserServiceProxy 和 ProductServiceProxy 这两个代理类的逻辑都差不多,却还得写 2 次。其实这个还好,如果老板说,把现有系统的几十个服务的响应时间都记录一下吧,你是不是要疯了?这得写多少代理类啊?
动态代理
黑暗总是暂时的,终究会迎来黎明,在 JDK1.3 之后引入了一种称之为动态代理(Dynamic Proxy)的机制。使用该机制,我们可以为指定的接口在系统运行期间动态地生成代理对象,从而帮助我们走出最初使用静态代理实现 AOP 的窘境
动态代理的实现主要由一个类和一个接口组成,即 java.lang.reflect.Proxy 类和 java.lang.reflect.InvocationHandler 接口。
让我们用动态代理来改造一下上面记录系统响应时间的功能。虽然要为 IUserService 和 IProductService 两种服务提供代理对象,但因为代理对象中要添加的横切逻辑是一样的。所以我们只需要实现一个 InvocationHandler 就可以了。代码如下
1 | public class RequestCostInvocationHandler implements InvocationHandler { |
UML 图如下。恭喜你,你现在已经理解了 Spring AOP 是怎么回事了,就是这么简单,今天先不展开谈 Spring
先简单谈谈动态代理在 Mybatis 中是如何被大佬玩的出神入化的
Mybatis 核心设计思路
相信用过 mybatis 的小伙伴都能理解下面这段代码,通过 roleMapper 这个接口直接从数据库中拿到一个对象
1 | Role role = roleMapper.getRole(3L); |
直觉告诉我,一个接口是不能运行的啊,一定有接口的实现类,可是这个实现类我自己没写啊,难道 mybatis 帮我们生成了?你猜的没错,mybatis 利用动态代理帮我们生成了接口的实现类,这个类就是 org.apache.ibatis.binding.MapperProxy,我先画一下 UML 图,MapperProxy 就是下图中的 SubjectProxy 类
和上面的 UML 类图对比一下,发现不就少了一个 SubjectImpl 类吗?那应该就是 SubjectProxy 类把 SubjectImple 类要做的事情做了呗,猜对了。SubjectProxy 通过 SubjectImple 和 SubjectImple.xml 之间的映射关系知道自己应该执行什么 SQL。所以 mybatis 最核心的思路就是这么个意思,细节之类的可以看源码,理清最主要的思路,看源码就能把握住重点。
Mybatis插件原理
mybatis 的插件也用到了动态代理,还用到了责任链模式,我就不从源码角度分析了。说一下大概实现,我们用插件肯定是为了在原先的基础上增加新功能。增加一个插件,mybatis 就在原先类的基础上用动态代理生成一个代理对象,如果有多个插件,就在代理对象的基础上再生成代理对象,形式和如下函数差不多
1 | plugin2( plugin1( start() ) ) |
我再给你写个例子,你再看看相关的源码分析文章(也许我以后会写),很快就能理解了。
在 mybatis 中要想用插件,有如下 2 个步骤
- 在 mybatis-config.xml 中配置插件,如下所示
1
2
3
4<plugins>
<plugin interceptor="org.xrq.mybatis.plugin.FirstInterceptor" />
<plugin interceptor="org.xrq.mybatis.plugin.SecondInterceptor" />
</plugins> - 插件类还得实现 Interceptor 接口
我现在给一个需求,一个应用返回字符串 0,我加一个插件在字符串的左右两边加 plugin1,再加一个插件在字符串的左右两边加 plugin2,开写
返回字符串的接口
1 | public interface IGetStr { |
返回字符串的实现类
1 | public class GetStrImpl implements IGetStr { |
定义拦截器接口
1 | public interface Interceptor { |
看到一个不认识的类Invocation,定义如下
1 | public class Invocation { |
就是简单的封装了一下目标对象,目标方法和目标方法的参数。proceed方法就是执行目标对象的目标方法
Plugin 算是一个工具类,生成代理对象
1 | public class Plugin implements InvocationHandler { |
写第一个插件
1 | public class FirstInterceptor implements Interceptor { |
有 2 个方法
plugin 是为插件生成代理对象,用了我自己写的 Plugin 工具类
intercept 是增加拦截逻辑,invocation.proceed() 是执行目标对象的目标方法,前文说过了哈,这里我们只对输出做了改变
第二个插件和第一个插件类似
1 | public class SecondInterceptor implements Interceptor { |
用一个容器保存插件,这里用到了责任链模式
1 | public class InterceptorChain { |
pluginAll 方法是精髓,为每个插件一层一层的生成代理对象,就像套娃娃一样。
验证一下
1 | public class Main { |
大功告成,可以看到先定义的插件先执行。
类有点多,如果看的有点晕,多看几次,你就很容易理解了,我这里还是精简了很多。
一个 InvocationHandler 接口被大佬玩出了新境界,果然编程这件事还得靠想象力
A基本概念
双线性映射:在数论中,一个双线性映射是由两个向量空间上的元素,生成第三个向量空间上一个元素之函数,并且该函数对每个参数都是线性的。例如矩阵乘法就是一个例子。
- 矩阵乘法是双线性映射 ${\displaystyle M(m,n)\times M(n,p)\rightarrow M(m,p)}$。
- 如果在实数 ${\displaystyle \mathbb {R} }$ 上的向量空间 ${\displaystyle V}$ 承载了内积,则内积是双线性映射 ${\displaystyle V\times V\rightarrow \mathbb {R} }$。
行列式表示空间线性变换后面积缩放的比例。
秩表示变换后的空间维数。更精确的定义是列空间的维数。
变换后落在原点的向量集合被称为所选矩阵的“零空间“(Null space)或”核“(Kernel)。
一个多维空间到一维空间的线性变换的对偶是多维空间中的某个特定向量。
分布式锁-基于MySQL的分布式锁.md
转自:https://blog.csdn.net/zzti_erlie/article/details/102769447
介绍
在分布式系统中,分布锁是一个最基础的工具类。例如,部署了2个有付款功能的微服务中,用户有可能对一个订单发起2次付款操作,而这2次请求可能被发到2个服务中,所以必须得用分布式锁防止重复提交,获取到锁的服务正常进行付款操作,获取不到锁的服务提示重复操作。
我司封装了大量的基础工具类,当我们想使用分布式锁的时候只要做3件事情
- 在数据库中建globallocktable表
- 引入相应的jar包
- 在代码中写上@Autowired GlobalLockComponent globalLockComponent即可使用这个组件
看完这篇文章你也可以用springboot-starter的方式实现一个同样的功能。
建表
1 | CREATE TABLE `globallocktable` ( |
让别人使用的组件
1 | @Component |
锁对象定义如下
1 | public class GlobalLockTable { |
GlobalLockTableDAO定义如下
1 | public interface GlobalLockTableDAO { |
具体加锁和解锁逻辑
1 | public class GlobalLockUtil { |
这个工具类有2个特别有意思的地方,先看注意的地方2(上面代码中标识了)
- 为了避免锁长时间不释放,用Redis实现的话可以设置锁超时时间,超时自动释放(后面会写用Redis实现分布式锁)用MySQL实现的话可以先删除后添加。可以看到删除的时候使用id删的,不是用name删的。为啥呢?先自己想一下
因为如果是通过name删的话,有可能别人删了这个锁后,又通过name加了锁,还没到超时时间,结果你却根据name删除了。通过id删的话,当返回的id=0时,说明别人已经重新加锁了,你需要重新获取。
- GlobalLockTable 对象dao层的其他方法都见名知意,来看一个这个方法。即代码中的注意点1
可以看到每次尝试加锁的时候,并不是先select,而是直接insertSelectiveWithTest,这样就少了一个查询时间,提高了效率
insertSelectiveWithTest的作用是当lockKey存在时不进行插入操作,返回0。当lockKey不存在时进行插入操作,返回1
1 | <insert id="insertSelectiveWithTest" useGeneratedKeys="true" keyProperty="id" parameterType="com.javashitang.middleware.lock.mysql.pojo.GlobalLockTable"> |
使用
当我们想使用时,就只写业务逻辑就行了,非常方便
1 | if (!globalLockComponent.tryLock(name)) { |
协方差矩阵
转自:https://zhuanlan.zhihu.com/p/37609917
协方差矩阵在统计学和机器学习中随处可见,一般而言,可视作方差和协方差两部分组成,即方差构成了对角线上的元素,协方差构成了非对角线上的元素。本文旨在从几何角度介绍我们所熟知的协方差矩阵。
方差和协方差的定义
在统计学中,方差是用来度量单个随机变量的离散程度,而协方差则一般用来刻画两个随机变量的相似程度,其中,方差 的计算公式为
$$
\sigma_{x}^{2}=\frac{1}{n-1} \sum_{i=1}^{n}\left(x_{i}-\overline{x}\right)^{2}
$$
其中,$n$ 表示样本量,符号 $\overline{x}$ 表示观测样本的均值,这个定义在初中阶段就已经开始接触了。
在此基础上,协方差 的计算公式被定义为
$$
\sigma(x, y)=\frac{1}{n-1} \sum_{i=1}^{n}\left(x_{i}-\overline{x}\right)\left(y_{i}-\overline{y}\right)
$$
在公式中,符号 $\overline{x}, \overline{y}$ 分别表示两个随机变量所对应的观测样本均值,据此,我们发现:方差 $\sigma^2$ 可视作随机变量 $x$ 关于其自身的协方差 $\sigma(x, x)$ .
从方差/协方差到协方差矩阵
根据方差的定义,给定 $d$ 个随机变量 $x_k, k=1, 2,…,d$ ,则这些随机变量的方差为
$$
\sigma\left(x_{k}, x_{k}\right)=\frac{1}{n-1} \sum_{i=1}^{n}\left(x_{k i}-\overline{x}{k}\right)^{2}, k=1,2, \ldots, d
$$
其中,为方便书写,$x{ki}$ 表示随机变量 $x_k$ 中的第 $i$ 个观测样本,$n$ 表示样本量,每个随机变量所对应的观测样本数量均为 $n$。
对于这些随机变量,我们还可以根据协方差的定义,求出 两两之间的协方差__,即
$$
\sigma\left(x{m}, x{k}\right)=\frac{1}{n-1} \sum_{i=1}^{n}\left(x_{m i}-\overline{x}{m}\right)\left(x{k i}-\overline{x}{k}\right)
$$
因此,__协方差矩阵_ 为
$$
\Sigma=\left[\begin{array}{ccc}{\sigma\left(x_{1}, x_{1}\right)} & {\cdots} & {\sigma\left(x_{1}, x_{d}\right)} \ {\vdots} & {\ddots} & {\vdots} \ {\sigma\left(x_{d}, x_{1}\right)} & {\cdots} & {\sigma\left(x_{d}, x_{d}\right)}\end{array}\right] \in \mathbb{R}^{d \times d}
$$
其中,对角线上的元素为各个随机变量的方差,非对角线上的元素为两两随机变量之间的协方差,根据协方差的定义,我们可以认定:矩阵 $\Sigma$ 为对称矩阵(symmetric matrix),其大小为 $d \times d$ 。
多元正态分布与线性变换
假设一个向量 $x$ 服从均值向量为 $\mu$ 、协方差矩阵为 $\Sigma$ 的多元正态分布(multi-variate Gaussian distribution),则
$$
p(\boldsymbol{x})=|2 \pi \Sigma|^{-1 / 2} \exp \left(-\frac{1}{2}(\boldsymbol{x}-\boldsymbol{\mu})^{T} \Sigma^{-1}(\boldsymbol{x}-\boldsymbol{\mu})\right)
$$
令该分布的均值向量为 $\mu = 0$,由于指数项外面的系数 $|2 \pi \Sigma|^{-1 / 2}$ 通常作为常数,故可将多元正态分布简化为
$$
p(\boldsymbol{x}) \propto \exp \left(-\frac{1}{2} \boldsymbol{x}^{T} \Sigma^{-1} \boldsymbol{x}\right)
$$
再令 $\boldsymbol{x}=(y, z)^{T}$,包含两个随机变量 $y$ 和 $z$,则协方差矩阵可写成如下形式:
$$
\Sigma=\left[\begin{array}{ll}{\sigma(y, y)} & {\sigma(y, z)} \ {\sigma(z, y)} & {\sigma(z, z)}\end{array}\right] \in \mathbb{R}^{2 \times 2}
$$
用单位矩阵(identity matrix) $I$ 作为协方差矩阵,随机变量 $y$ 和 $x$ 的方差均为1,则生成如干个随机数如图1所示。
(图1 标准的二元正态分布)
在生成的若干个随机数中,每个点的似然为
$$
\mathcal{L}(\boldsymbol{x}) \propto \exp \left(-\frac{1}{2} \boldsymbol{x}^{T} \boldsymbol{x}\right)
$$
对图1中的所有点考虑一个线性变换(linear transformation): $t = Ax$,我们能够得到图2.
(图1 标准的二元正态分布)
图2 经过线性变换的二元正态分布,先将图1的纵坐标压缩0.5倍,再将所有点逆时针旋转30°得到。
在线性变换中,矩阵 $A$ 被称为变换矩阵(transformation matrix),为了将图1中的点经过线性变换得到我们想要的图2,其实我们需要构造两个矩阵:
- 尺度矩阵(scaling matrix):
$$
S=\left[\begin{array}{ll}{s_{y}} & {0} \ {0} & {s_{z}}\end{array}\right]
$$ - 旋转矩阵(rotation matrix)
$$
R=\left[\begin{array}{cc}{\cos (\theta)} & {-\sin (\theta)} \ {\sin (\theta)} & {\cos (\theta)}\end{array}\right]
$$
其中,$\theta$ 为顺时针旋转的度数。
变换矩阵、尺度矩阵和旋转矩阵三者的关系式:$A = RS$
在这个例子中,尺度矩阵为 $S=\left[\begin{array}{cc}{1} & {0} \ {0} & {\frac{1}{2}}\end{array}\right]$ ,旋转矩阵为 $R=\left[\begin{array}{cc}{\cos \left(-\frac{\pi}{6}\right)} & {-\sin \left(-\frac{\pi}{6}\right)} \ {\sin \left(-\frac{\pi}{6}\right)} & {\cos \left(-\frac{\pi}{6}\right)}\end{array}\right]=\left[\begin{array}{cc}{\frac{\sqrt{3}}{2}} & {\frac{1}{2}} \ {-\frac{1}{2}} & {\frac{\sqrt{3}}{2}}\end{array}\right]$ ,故变换矩阵为 $A=R S=\left[\begin{array}{cc}{\frac{\sqrt{3}}{2}} & {\frac{1}{4}} \ {-\frac{1}{2}} & {\frac{\sqrt{3}}{4}}\end{array}\right]$
另外,需要考虑的是,经过了线性变换,$t$ 的分布是什么样子呢?
将 $x = A^{-1}t$ 带入前面给出的似然 $\mathcal{L}(\boldsymbol{t})$ ,有
$$
\begin{array}{l}{\mathcal{L}(\boldsymbol{t}) \propto \exp \left(-\frac{1}{2}\left(A^{-1} \boldsymbol{t}\right)^{T}\left(A^{-1} \boldsymbol{t}\right)\right)} \ {=\exp \left(-\frac{1}{2} \boldsymbol{t}^{T}\left(\boldsymbol{A} \boldsymbol{A}^{T}\right)^{-1} \boldsymbol{t}\right)}\end{array}
$$
由此可以得到,多元正态分布的协方差矩阵为
$$
\Sigma=A A^{T}=\left[\begin{array}{cc}{\frac{\sqrt{3}}{2}} & {\frac{1}{4}} \ {-\frac{1}{2}} & {\frac{\sqrt{3}}{4}}\end{array}\right]\left[\begin{array}{cc}{\frac{\sqrt{3}}{2}} & {-\frac{1}{2}} \ {\frac{1}{4}} & {\frac{\sqrt{3}}{4}}\end{array}\right]=\left[\begin{array}{cc}{\frac{13}{16}} & {-\frac{3 \sqrt{3}}{16}} \ {-\frac{3 \sqrt{3}}{16}} & {\frac{7}{16}}\end{array}\right]
$$
协方差矩阵的特征值分解
回到我们已经学过的线性代数内容,对于任意对称矩阵 $\Sigma$,存在一个特征值分解(eigenvalue decomposition, EVD):$\Sigma = U\Lambda U^T$
其中,$U$ 的每一列都是相互正交的特征向量,且是单位向量,满足 $U^TU=I$,$\Lambda$ 对角线上的元素是从大到小排列的特征值,非对角线上的元素均为0。
当然,这条公式在这里也可以很容易地写成如下形式:
$$
\Sigma=\left(U \Lambda^{1 / 2}\right)\left(U \Lambda^{1 / 2}\right)^{T}=A A^{T}
$$
其中, $A = U\Lambda^{1/2}$ ,因此,通俗地说,任意一个协方差矩阵都可以视为线性变换的结果。
在上面的例子中,特征向量构成的矩阵为
$$
U=R=\left[\begin{array}{cc}{\cos (\theta)} & {-\sin (\theta)} \ {\sin (\theta)} & {\cos (\theta)}\end{array}\right]=\left[\begin{array}{cc}{\frac{\sqrt{3}}{2}} & {\frac{1}{2}} \ {-\frac{1}{2}} & {\frac{\sqrt{3}}{2}}\end{array}\right]
$$
特征值构成的矩阵为
$$
\Lambda=S S^{T}=\left[\begin{array}{cc}{s_{y}^{2}} & {0} \ {0} & {s_{z}^{2}}\end{array}\right]=\left[\begin{array}{cc}{1} & {0} \ {0} & {\frac{1}{4}}\end{array}\right]
$$
到这里,我们发现:多元正态分布的概率密度是由协方差矩阵的特征向量控制旋转(rotation),特征值控制尺度(scale),除了协方差矩阵,均值向量会控制概率密度的位置,在图1和图2中,均值向量为 $0$,因此,概率密度的中心位于坐标原点。
欧几里得空间与希尔伯特空间
以下转自知乎
1 | 作者:qang pan |
什么是赋范线性空间、内积空间,度量空间,希尔伯特空间?
现代数学的一个特点就是以集合为研究对象,这样的好处就是可以将很多不同问题的本质抽象出来,变成同一个问题,当然这样的坏处就是描述起来比较抽象,很多人就难以理解了。既然是研究集合,每个人感兴趣的角度不同,研究的方向也就不同。为了能有效地研究集合,必须给集合赋予一些“结构”(从一些具体问题抽象出来的结构)。
从数学的本质来看,最基本的集合有两类:线性空间(有线性结构的集合)、度量空间(有度量结构的集合)。
对线性空间而言,主要研究集合的描述,直观地说就是如何清楚地告诉地别人这个集合是什么样子。为了描述清楚,就引入了基(相当于三维空间中的坐标系)的概念,所以对于一个 线性空间 来说,只要知道其 基 即可,集合中的元素只要知道其在给定基下的坐标即可。
但线性空间中的元素没有“长度”(相当于三维空间中线段的长度),为了量化线性空间中的元素,所以又在线性空间引入特殊的“长度”,即范数。赋予了 范数 的线性空间即称为 __赋犯线性空间__。
但赋范线性空间中两个元素之间没有角度的概念,为了解决该问题,所以在线性空间中又引入了内积的概念。
因为有度量,所以可以在度量空间、赋范线性空间以及内积空间中引入极限,但抽象空间中的极限与实数上的极限有一个很大的不同就是,极限点可能不在原来给定的集合中,所以又引入了完备的概念,完备的内积空间 就称为 __Hilbert 空间__。
这几个空间之间的关系是:线性空间与度量空间是两个不同的概念,没有交集。
- 赋范线性空间就是赋予了范数的线性空间,也是度量空间(具有线性结构的度量空间)
- 内积空间是赋范线性空间
- 希尔伯特空间就是完备的内积空间。
(线性空间 + 范数 = 赋范空间 + 线性结构) + 内积 = 内积空间 + 完备性 = 希尔伯特空间。
- 线性完备内积空间称作希尔伯特空间
- 线性完备赋范空间称作巴拿赫空间
- 有限维线性内积空间称作欧几里得空间