jingyier

小白,火影男,普通男大

0%

本月林林总总尝试了一些新东西(对我而言),整体完成度还是不高。我的能力还是太欠缺了,当务之急恐怕是先提升自己的代码能力吧。

比较遗憾的是期末考试在即,已经无暇去学习数据结构了,只好把cs61b的课程先放一放。同样的,从现在开始到期末考试结束,任务安排都将会基于考试需求。

下面总结本月的各种尝试:

opencv-python

opencv是计算机视觉经典的专用库,我简单学习了其语法,并自己通过学习教程做了一个小项目。可惜前端基础不够,无法自主构建美观的页面,于是使用AI用gradio构建了一个UI界面。但不知为何,一共有两个UI界面,其中一个始终无法呈现摄像头的拍摄内容,一直处于空白状态,因而该问题暂存(想了挺长时间,可还是无法解决),只能先暂时保留问题了。

这个项目我放在了github中:

github

基于qwen大模型的智能问答小助手

实际上这个以我的水平是做不出来的,但是这是高中同学的小组作业,我对此感觉挺感兴趣,于是准备探索一下。比较好的一点是,像我这样的小白,无论探索什么都好像发现了什么不得了的东西,这当然对我而言也是事实中的事实。

环境配置

实际上我最终失败了,但是我觉得还是有必要记录一下过程,万一以后有能力给解决了呢。

开始在我的印象里,完成这个只需要在我的pycharm环境里安装pytorch的库,然后继续根据需求添加各种需要的东西就好了,事实证明这个想法过于愚蠢了哈哈哈。

主体过程如下:

安装CUDA,cuDNN,Anaconda,pytorch,pycharm,VSCode

安装cuda

首先我用这个命令了解系统此时所支持的CUDA最大版本是12.6

1
nvidia-smi.exe

然后我下载了11.4版本,完成了安装流程

安装cudnn

注册并且下载完成后,打开cudnn后里面有bin,include,lib三个文件夹;而打开上面安装好的CUDA目录,里面也存在bin,include,lib三个文件夹,只要将cudnn中bin,include内的文件全选复制到CUDA中的bin,include内即可

对于cdnn里的lib文件夹,里面还存在一个x64文件夹,而CUDA中lib文件中存在Win32和x64文件,于是这时把cudnn中lib里打开x64文件夹,拷贝x64文件夹里所有内容到CUDA里lib中x64文件夹中去。

验证cuda是否安装成功,首先win+R启动cmd,进入到CUDA安装目录下的 …\extras\demo_suite,然后分别运行bandwidthTest.exe和deviceQuery.exe,返回Result=PASS表示cuda安装成功。

安装Anaconda

在镜像源下载的,网址如下:
anaconda

打开

1
anaconda prompt

创建环境

1
conda create --name torch python==3.7

激活环境

1
conda activate torch
pytorch安装

这一步好像就死了。。。

辗转conda和pip命令多次,辗转各个版本多次,辗转csdn和stackoverflow多次,依旧收获了各种各样的报错,可恶,当时没有吧报错内容记录下来。

至于pycharm和vscode之前已经安好,不做赘述。
很惭愧没有解决问题,最后也只是把ai写的代码提交到github,然后把网址给了我同学,毕竟他们在学校官网上面做这个项目,环境什么的应该没有问题。。。

就是这个,唉


话说回来,感觉无用功居多吧哈哈,只能以失败是成功之母聊以慰藉了,but还是得脚踏实地,总感觉现在路子有点偏,还是先要以提升基础能力为主。

期末考试小小安排

现在大部分课程已经接近尾声,现在只好高数线代大物白天刷网课过知识点,晚上做题巩固,Java 看看有没有机会向学长要到前几年真题,看看题型即可。

现在开始了CS61b的学习,go go go~

对于“=”,以往的理解是将右值赋值给左值,现在有了新的理解,就是左值指向一个地址

1
2
int a=5;
a=b;

a,b指向相同的地址。

本次假期不知道去哪玩,所以选择了留校,第四天的时候狠狠玩了一天,另外每天都是十点起床,这对于平时的日子简直是极大的奢望了。

在假期内,我主要做了以下工作:

  1. 学习python基本语法;
  2. 学习Java继承和多态(接口练习的不多,还要练),异常处理;
  3. 了解了yolo算法,学习了opencv的基本用法;
  4. 开始学习数据结构,并着力于群友推荐的cs61b。
  5. 初步学习了CSS,HTML
  6. 尝试了MySQL,下载的5.7.32,但是初始密码明明是对的,可是输入后却一直报error 1045 28000 using password yes的错误,在浏览了stack overflow
    并且使用了ai的操作下,我依旧没能解决问题,便萌生了卸载重新配置的想法,但出于工作量巨大,我准备在暑假完成这个任务。

讲真我看到太多同龄人有着极高的学习效率,也看了好多他们的总结报告,真的感觉差距非常大。
我的迷茫期太长了,我甚至没有利用到上学期寒假和本学期前半学期,时至今日还是小白中的小白。
比较尴尬的是我发现cs61b课程卡的要死,而我甚至不会科学上网,于是我就赶紧学了一下,终于在今天早上解决了这个别人那里不算问题的问题。

在cs学习上,我的天赋并不高。但我会去努力学习,向同辈的佼佼者学习,向优秀的前辈们学习,努力开拓自己的道路。

exercises 笔记

IOU

1
2
3
4
5
6
def calculate_iou(box1, box2):
# 计算交集区域的坐标
x_left = max(box1[0], box2[0])
y_top = max(box1[1], box2[1])
x_right = min(box1[2], box2[2])
y_bottom = min(box1[3], box2[3])

box是一个矩形,其四个参数两两一组,(box[0],box[1])是矩形左上角的坐标,(box[2],box[3])是矩形右下角的坐标,
用max,min函数得到

1
2
3
4
5
# 计算交集区域的面积
intersection_width = max(0, x_right - x_left)
intersection_height = max(0, y_bottom - y_top)
intersection_area = intersection_width * intersection_height

wight与height为负时box1和box2无交集,用max将其置为0,这样得到的交集面积也为0

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 计算两个框各自的面积
area1 = (box1[2] - box1[0]) * (box1[3] - box1[1])
area2 = (box2[2] - box2[0]) * (box2[3] - box2[1])

# 计算并集面积
union_area = area1 + area2 - intersection_area

# 处理并集面积为0的情况(避免除以0)
if union_area == 0:
return 0.0

# 计算IoU
iou = intersection_area / union_area
return iou

异常处理

一、异常语句块处理

1.自己异常处理

try cathc语句

2.单个异常处理

1
2
3
4
5
6
7
try{
//防止肯出现异常的代码
}catch(异常类型 异常名称){
//放置处理异常的代码
}finally{
//释放资源
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
ublic class Exception {

public static void main(String[] args) {
System.out.println("第一段码");
int i=5;
try {
System.out.println(i/0);
}catch (ArithmeticException e){
System.out.println("除数为0");
}


System.out.println("第二段码");
}
}

catch捕获的异常要和实际抛出的异常要么一致,要么有继承关系

3.多个异常处理

  • try 块中有多行代码,都有可能出现异常信息,程序执行的时候是从上往下执行的,当碰到异常情况的时候就会跳出try块,
    从而剩下的就不会执行了
  • printStackTrace()方法可以给出详细的异常信息

二、将异常抛出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class Exception {

public static void main(String[] args) {

try{
calc();
}catch (ArithmeticException e){
e.printStackTrace();
}

System.out.println("第一段码");


}

public static int calc() throws ArithmeticException{
int a = 10;
int b = 0;
int result = a / b;
return result;
}
}

throws的使用格式

1
2
[修饰符]返回值类型 方法名(参数列表)[throws 异常1,异常2...]{   }

  1. 注意:
  • 如果一个方法声明的是编译时异常,则在调用这个方法之处必须处置这个异常(谁调用,谁处理)
  • 异常子类可以抛给父类,父类不能抛给子类
  1. throws作用:在定义一个方法的时候可以使用throws关键字声明,使用throws关键字声明的方法表示此方法不处理异常,而交给方法的调用者进行处理

三、throw关键字

  • throw用在方法名后面,跟的是异常类名,throw是用在方法体中,跟的是异常对象。
  • throws可以跟多个异常类名,用逗号隔开,throw只能抛出一个异常对象
  • throws表示抛出异常,由该方法的调用者处理,throw表示抛出异常,由方法体内的语句处理
  • throws表示出现异常的可能性,并不一定真的发生这些异常,throw则是抛出了具体的异常,真的产生了一个Expection对象。

四、finally关键字

finally修饰的代码一定会执行,除非在finally之前程序异常退出或者调用了系统的退出方法。

4.27

今天继续学习了Java的继承、多态等等,同时学到了几个好用的快捷键,下面总结一下(ps:继承其实就是共性抽取):

1.快捷键

在idea的开发环境中,可以用这个快捷方式弹出一个交互界面,可以帮助我们直接构造方法、创建setter、getter等等,感觉挺好用的。

1
alt + insert

如果要对构造方法合并表示,可以直接全选:(好吧确实有点傻,但我确实不知道)

1
ctrl + a

批量修改:对相同的变量名统一修改

1
shift + f6

搜索想要找的类,方法等等:

1
ctrl + n

idea环境中自动纠错:

1
alt + enter

自动显示参数

1
ctrl + p

2.java知识点

<1>final 修饰符

  • 修饰方法:方法不能重写,是最终方法

  • 修饰类: 类不能被继承,是最终类

  • 修饰变量:叫做常量,只能被赋值一次


  • 修饰基本数据类型:记录的值不发生改变

  • 修饰引用数据类型:记录的地址值不发生改变,内部属性值可以改变

<2>权限修饰符的使用规则
  • 成员变量私有
  • 方法公开
  • 特例:如果方法中的代码是抽取到其他代码中的共性代码,这个方法一般也私有。
<3>抽象

作用:抽取共性时,无法确定方法体,就把方法定义为抽象的。

  • 抽象方法:将共性的方法抽取到父类之后,由于每一个子类执行的内容不一样,所以在父类中不能确定具体的方法体,该方法就可以定义为抽象方法。

抽象方法没有方法体

1
public abstract 返回值类型 方法名(参数列表);
  • 抽象类:如果一个类中存在抽象方法,那么这个类必须声明为抽象类
1
public abstract class 类名{};

注意事项:

  • 抽象类不能实例化,即不能创建对象;
  • 抽象类中不一定有抽象方法,有抽象方法的类一定是抽象类;
  • 可以有构造方法(作用:创建子类方法时给属性进行赋值);
  • 抽象类的子类要么重写抽象类中的所有抽象方法,要么是抽象类,多用第一种。

4.29

昨天参加了一个Python训练项目,本来想测试一下成绩提交是不是正常的,但是没料到成绩直接上了排行榜。。。啊啊啊啊我其实还没接触过Python。。。
那是我用ai写的,我还以为成绩显示在自己的库里,没想到直接交上去了。。。算了能学多少是多少吧

if

if … elif … elif … 序列可以当作其它语言中 switch 或 case 语句的替代品。

内置函数 range() 用于生成等差数列:

1
2
3
4
5
6
7
8
list(range(5, 10))
[5, 6, 7, 8, 9]

list(range(0, 10, 3))
[0, 3, 6, 9]

list(range(-10, -100, -30))
[-10, -40, -70]

要按索引迭代序列,可以组合使用 range() 和 len():

1
2
3
4
5
6
7
8
9
a = ['Mary', 'had', 'a', 'little', 'lamb']
for i in range(len(a)):
print(i, a[i])

0 Mary
1 had
2 a
3 little
4 lamb

break和contiune

break 语句将跳出最近的一层 for 或 while 循环:

1
2
3
4
5
6
7
8
9
10
for n in range(2, 10):
for x in range(2, n):
if n % x == 0:
print(f"{n} equals {x} * {n//x}")
break

4 equals 2 * 2
6 equals 2 * 3
8 equals 2 * 4
9 equals 3 * 3

continue 语句将继续执行循环的下一次迭代:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
for num in range(2, 10):
if num % 2 == 0:
print(f"Found an even number {num}")
continue
print(f"Found an odd number {num}")

Found an even number 2
Found an odd number 3
Found an even number 4
Found an odd number 5
Found an even number 6
Found an odd number 7
Found an even number 8
Found an odd number 9

高级数据

切片

[start:end:step] step默认1
(似乎是不包含起始位置,包含结束位置,可用来得到数据结构中的多种元素,算是半开半闭区间)

1
2
3
4
5
6
jing=[1,2,8,90,'啊哈哈',True]
print(jing[0:3])
print(jing[-1])
print(jing[:])
print(jing[3:6])
print(jing[0:6:2])

运行效果:

1
2
3
4
5
[1, 2, 8]
True
[1, 2, 8, 90, '啊哈哈', True]
[90, '啊哈哈', True]
[1, 8, '啊哈哈']

(目前的编程练习中,感觉python和Java有相似之处,都出现了
变量名.方法名()的形式)

1
for ... in ...  //目前的理解是把第二个空中的数据结构里的每个元素赋值给第一个空中的索引

不好,这玩意不叫索引,索引应该是和Java里数组下标一样

总之就是 for i in w 的意思就是返回 w 中的每个 i

列表的 * 增删查改 * 方法

1.extend和attend
  • 前者方法的参数必须是一个可迭代对象,新的内容是追加到原列表最后一个元素后面
    ,这里的内容可以是多个元素组成的列表。
  • 后者方法一次添加一个列表。
  • 二者都把新内容加在原列表后面。
1
2
3
4
5
6
practice=['唱','跳','rap']
practice.append('篮球')
print(practice)
practice.extend(['鸡','坤'])
print(practice)

运行效果

1
2
['唱', '跳', 'rap', '篮球']
['唱', '跳', 'rap', '篮球', '鸡', '坤']
2.insert

可以直接在列表任何一个位置插入,有两个参数

insert(a:插入点的前一个元素索引,b:元素内容)

1.remove
  • remove(删除元素内容)
  • 如果存在多个匹配的元素,只删除第一个(下标最小的)
  • 指定元素不存在会直接报错
2.clear

清除列表中所有元素,返回一个空列表

改和查完了再说,这里不多说了

元组(特性:不可修改)

1
2
3
4
5
6
7
8
9
10
11
12
s=('w',1,'啦啦啦',2)
print(s.index(1))

a=(1,3,7,9,4)
t=(2,3,4)
w=a,t

print(a*3)
print(a+t)
print(w)

print([each*2 for each in t])

运行效果

1
2
3
4
5
6
1
(1, 3, 7, 9, 4, 1, 3, 7, 9, 4, 1, 3, 7, 9, 4)
(1, 3, 7, 9, 4, 2, 3, 4)
((1, 3, 7, 9, 4), (2, 3, 4))
[4, 6, 8]

元组只含一个元素时,要这样写(元素,)

1
2
3
4
5
t=(1,4,8)  #把1,4,8打包到元组
x,y,z=t #把元组t解包到x,y,z
print(x)
print(y)
print(z)

运行效果

1
2
3
1
4
8

打包和解包在数组,字符串等等同样适用

这也是python多重赋值的原理

元组不可变,但是如果元组中的元素指向一个可变的列表,那么内容依旧可以改
变,比如把两个元组放入一个数组,形成二维数组,这样里面的元素就可变了


此后笔记记录的内容仅含有关键字,剩余内容看官方文档补足

  1. is 和 in
  2. 列表,元组,字符串相互转换关键字list(),tuple(),str()
  3. 字典

函数

关键字函数

收集函数

1
2
3
def myfunc(a,*b,**c):
print(a,b,c)
myfunc(1,34,5,6,74,3,5,x=1,y=4)

一个星号表示数据打包到元组,两个星号表示数据打包到字典

1
1 (34, 5, 6, 74, 3, 5) {'x': 1, 'y': 4}
  • 星号在形参上调用是参数的打包,实参上调用是参数的解包
1
2
3
4
args=(1,2,3,4)
def myfunc(a,b,c,d):
print(a,b,c,d)
myfunc(*args)

这里args前不用星号解包的话会直接报错

运行效果:

1
1 2 3 4
  • 两个星号可以把字典解包成关键字参数
1
2
3
4
kwargs= {'a':1,'b':2,'c':3,'d':4}
def myfunc(a,b,c,d):
print(a,b,c,d)
myfunc(**kwargs)

运行效果

1
1 2 3 4 

嵌套函数

nonlocal语句可以实现内部函数值修改外部函数值
1
2
3
4
5
6
7
8
9
def funA():
x=34
def funB():
nonlocal x
x=45
print("in funB:x=",x)
funB()
print("in funA:x=",x)
funA()

运行效果

1
2
in funB:x= 45
in funA:x= 45
LEGB 规则

L>E>G>B

匿名函数

  • lambda 函数通常只包含一行代码,这使得它们适用于编写简单的函数。
    lambda 语法格式:
1
lambda arguments: expression
  • lambda: Python 的关键字,用于定义 lambda 函数。
  • arguments: 参数列表,可以包含零个或多个参数,但必须在冒号(:)前指定。
  • expression: 一个表达式,用于计算并返回函数的结果。

装饰器

装饰器本质上是一个接收函数作为输入并返回一个新的包装过后的函数的对象。

(这玩意目前看不懂,先过了)

数据结构

列表

在这里不看具体函数,有个用列表当栈使用的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
class Stack:
def __init__(self):
self.stack = []

def push(self, item):
self.stack.append(item)

def pop(self):
if not self.is_empty():
return self.stack.pop()
else:
raise IndexError("pop from empty stack")

def peek(self):
if not self.is_empty():
return self.stack[-1]
else:
raise IndexError("peek from empty stack")

def is_empty(self):
return len(self.stack) == 0

def size(self):
return len(self.stack)

# 使用示例
stack = Stack()
stack.push(1)
stack.push(2)
stack.push(3)

print("栈顶元素:", stack.peek()) # 输出: 栈顶元素: 3
print("栈大小:", stack.size()) # 输出: 栈大小: 3

print("弹出元素:", stack.pop()) # 输出: 弹出元素: 3
print("栈是否为空:", stack.is_empty()) # 输出: 栈是否为空: False
print("栈大小:", stack.size()) # 输出: 栈大小: 2
实现队列

用deque实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
from collections import deque

# 创建一个空队列
queue = deque()

# 向队尾添加元素
queue.append('a')
queue.append('b')
queue.append('c')

print("队列状态:", queue) # 输出: 队列状态: deque(['a', 'b', 'c'])

# 从队首移除元素
first_element = queue.popleft()
print("移除的元素:", first_element) # 输出: 移除的元素: a
print("队列状态:", queue) # 输出: 队列状态: deque(['b', 'c'])

# 查看队首元素(不移除)
front_element = queue[0]
print("队首元素:", front_element) # 输出: 队首元素: b

# 检查队列是否为空
is_empty = len(queue) == 0
print("队列是否为空:", is_empty) # 输出: 队列是否为空: False

# 获取队列大小
size = len(queue)
print("队列大小:", size) # 输出: 队列大小: 2

用列表实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
class Queue:
def __init__(self):
self.queue = []

def enqueue(self, item):
self.queue.append(item)

def dequeue(self):
if not self.is_empty():
return self.queue.pop(0)
else:
raise IndexError("dequeue from empty queue")

def peek(self):
if not self.is_empty():
return self.queue[0]
else:
raise IndexError("peek from empty queue")

def is_empty(self):
return len(self.queue) == 0

def size(self):
return len(self.queue)

# 使用示例
queue = Queue()
queue.enqueue('a')
queue.enqueue('b')
queue.enqueue('c')

print("队首元素:", queue.peek()) # 输出: 队首元素: a
print("队列大小:", queue.size()) # 输出: 队列大小: 3

print("移除的元素:", queue.dequeue()) # 输出: 移除的元素: a
print("队列是否为空:", queue.is_empty()) # 输出: 队列是否为空: False
print("队列大小:", queue.size()) # 输出: 队列大小: 2

集合

下面是集合的各种操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
>>> basket = {'apple', 'orange', 'apple', 'pear', 'orange', 'banana'}
>>> print(basket) # 删除重复的
{'orange', 'banana', 'pear', 'apple'}
>>> 'orange' in basket # 检测成员
True
>>> 'crabgrass' in basket
False

>>> # 以下演示了两个集合的操作
...
>>> a = set('abracadabra')
>>> b = set('alacazam')
>>> a # a 中唯一的字母
{'a', 'r', 'b', 'c', 'd'}
>>> a - b # 在 a 中的字母,但不在 b 中
{'r', 'd', 'b'}
>>> a | b # 在 a 或 b 中的字母
{'a', 'c', 'r', 'd', 'b', 'm', 'z', 'l'}
>>> a & b # 在 a 和 b 中都有的字母
{'a', 'c'}
>>> a ^ b # 在 a 或 b 中的字母,但不同时在 a 和 b 中
{'r', 'd', 'b', 'm', 'z', 'l'}

模块

from a import b 语句

这个声明不会把整个 a 模块导入到当前的命名空间中,它只会将 a 里的 b 函数引入进来。
使用 as 关键字为模块或函数起别名:

1
2
import numpy as np  # 将 numpy 模块别名设置为 np
from math import sqrt as square_root # 将 sqrt 函数别名设置为 square_root

正则表达式

re.match函数

re.match 尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match() 就返回 None。

1
2
3
函数语法:

re.match(pattern, string, flags=0)
  • pattern 匹配的正则表达式
  • string 要匹配的字符串。
  • flags 标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。

老实了,求放过,改天再约

文件

____name__和__main__的使用

在 Python 中,常见的做法是在模块的末尾添加以下代码块:

实例

1
2
3
if __name__ == "__main__":
#这里的代码只有在模块作为主程序运行时才会执行
main()
  • name 是一个内置变量,表示当前模块的名称。

  • 当模块作为主程序运行时,name 的值是 “main“。

  • 当模块被导入时,name 的值是模块的文件名。

  • 使用 if name == “main“: 可以控制模块在被导入时不会执行某些代码,而只有在作为独立脚本运行时才会执行这些代码。

一、安装过程

1.安装node.js

Vue CLI 4.x 需要Node.js 8.9 或更高版本(推荐v10+)。可以使用n、nvm或nvm-windows 在同一台机器上管理多个版本的Node。 如果你不确定系统中正在运行的 Node.js 版本是什么,请在终端窗口中运行 如下命令

1
node -v

2.安装npm

可以通过这个命令检查是否安装了npm客户端

1
npm -v

3.安装Vue CLI新软件包

1
npm install -g @vue/cli

你可以通过以下命令检查是否安装成功

1
vue --version

如果你和我一样不小心安装了之前版本,可以用这个命令卸载

1
npm uninstall vue-cli -g

二、问题总结

其实在安装了新版本之后,我的vue依旧是安装失败的。此时有可能是npm全局路径没有添加到系统变量,所以我先通过以下命令找到npm全局安装路径

1
npm config get prefix

之后我把该路径添加到了系统的PATH变量上,问题就解决了。

HTML基础知识

  • HTML 代码是由 “标签” 构成的;
  • 整体的 HTML 代码是由一对 html 包裹的;
  • head 标签是页面的头部,标签中写页面的属性;
  • body 标签是页面的主体,标签中写的是页面显示的内容;
  • title 标签中写的是页面的标题。

默认页面模板:!+tab,生成代码如下

1
2
3
4
5
6
7
8
9
10
11
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>

</body>
</html>

一、常见标签

1.注释标签

1
<!--我是注释-->

2.标题标签

1
2
3
4
5
6
7
8
<body>
<h1>这是一级标签</h1>
<h2>这是二级标签</h2>
<h3>这是三级标签</h3>
<h4>这是四级标签</h4>
<h5>这是五级标签</h5>
<h6>这是六级标签</h6>
</body>

3.段落标签

1
2
3
4
5
<body>
<p>段落一</p>
<p>段落二</p>
<p>段落三</p>
</body>

4.换行标签

1
2
3
4
5
<body>
第一行<br>
第二行<br>
第三行<br>
</body>

5.格式化标签

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<body>
<strong>加粗</strong>
<b>加粗</b>

<em>倾斜</em>
<i>倾斜</i>

<del>删除线</del>
<s>删除线</s>

<ins>下划线</ins>
<u>下划线</u>

</body>

6.图片标签

1
2
3
<body>
<img src="相对路径,绝对路径或网络路径" alt="图片加载错误时的描述信息" width="宽" height="高" >
</body>

注意width 单位是px 像素。

7.超链接标签

1
2
3
<body>
<a href="网址">点击此处跳转</a>
</body>

超链接标签用 来表示,其中的href属性表示点击后会跳转到哪个页面,target表示打开方式,默认是_self,在本标签页打开,如果设置为_blank,则用新的标签页打开。

8.表格标签

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<table border="1">
<!-- 表头 -->
<th>列标题1</th>
<th>列标题2</th>
<th>列标题3</th>
<th>列标题4</th>
<tr>
<!-- 每一行都是一个tr标签 -->
<!-- 每一列都是一个td标签 -->
<td>444</td>
<td>欸嘿嘿</td>
<td>444</td>
<td>444</td>

</tr>

<tr>
<td>444</td>
<td>444</td>
<td>好玩</td>
<td>444</td>

</tr>

<tr>
<td>666</td>
<td>444</td>
<td>444</td>
<td>444</td>

</tr>

</table>

9.列表标签

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!-- 无序列表 -->
<ul>

<li>lalala</li>
<li>lalala</li>
<li>lalala</li>
<li>lalala</li>

</ul>

<!-- 有序列表 -->
<ol>

<li>111111</li>
<li>111111</li>

</ol>

10.表单标签

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<body>
<form action="">
<label for="">用户名:</label>
<input type="text" id="username" placeholder="有点意思">
<br><br>
<label for="">密码:</label>
<input type="password" id="psw" placeholder="有点意思">
<br><br>
<label>性别</label>
<input type="radio" name="gender">男
<input type="radio" name="gender">女
<br>
<label for="">爱好</label>
<!-- 通过相同的name使得单选框互斥,构成单选 -->
<input type="checkbox" name="hobby">唱跳
<input type="checkbox" name="hobby">rap
<input type="checkbox" name="hobby">篮球
<br><br>
<!-- value生成固定字样 -->
<input type="submit" value="上传">
</form>
</body>

这是一篇上高中前一位好友为我创作的短篇小说,在这篇博客上摘录下来,以纪念过去无法复刻的时光

  • 二十五年,时过境迁,沧桑尘世,分寸轻芒。却有些似碣石,随着岁月仓皇,灯火可亲,笑谈春冬竟是一般模样。人生如此,何憾,何悔?——姜祭临

檀木桌子上放着一个烫金信封,我点起灯,缓缓拆开。

一张巴掌大的纸片滑落出来,连同 一枚装在密封袋中的君山银针茶叶,滚落进我的视线。

昏黄灯火之中,我笑了。

“啧,居然没忘记……”

纸片上字迹依旧曲折有力,一丝年少的倔强隐藏在其中,赶走岁月不饶人的呼声,慢慢扩散到充盈沉香的房间中。有些人,果然是时间的强敌。

不过现在看来,他赢了。

“你看,我就说四分之三也是整数吧。”

正正经经的笔体勾勒这么几个顽皮的字眼,我没有意识到自己翻了一个白眼,抓信的手却把信越攥越紧。

片刻后,我将那一枚茶叶放进身后的玄关,拿出朱笔和纸。门口长信宫灯的火焰微微躲闪,笔与纸的这场折子戏,在我手下紧锣密鼓开演。

亲爱的初夏先生:

来信收悉。感叹君依旧笑颜如从前……

我的手忽然一抖,朱色墨汁滴落在米黄色的纸张上。

从前……又是多久之前呢……

(一)

人总会在不经意间回想起一些事,说是回想,就是记忆提取的过程,当然这其中有些记忆属于自己的头脑,有一部分属于自己的灵魂。

有些撼动灵魂的人,万里挑一,想来也是有趣得紧。

1967年……

我坐在木桌边小憩,门外嘈杂的声音终于还是挤进门缝,扰得我心中一丝不安。

“怕是又要一段时间不得安宁了……”我叹息道。

在这种不同的境况下,总会相应发生一些事,我以为人间万事无非海上波浪,一波未平一波又起,见惯了,也就习惯了,总不会朵朵奇葩都开在我的面前,若是那样,还不如收拾行李早点回乡,图个清闲。

在这个时候,没人想要惹麻烦。

“有人吗?”

敲门声。

我一皱眉,门在挣扎的声音中被推开,灰尘在阳光的照射下四处躲藏,一个文青模样的少年静静地看看我。

“您好,请问这里是疏离宇吗?”

我起身请他坐下,眼前的少年眉宇之间英气回荡,白色的衬衫整洁到咂舌的地步,他缓缓解下右臂上的红袖章,冲着我笑了笑。

“外面发生了好多事,看来您不感兴趣。”他将红袖章放进自己的皮包里,皮包有些旧,边角处有明显的磨损。

“像我这种人,永远把安身立命作为根本目的,屋里屋外,孰是孰非,与我何干?”我不知道这种避世思想是否让他感到不舒服,一个人留在一个地方,一定是有理由的,我的理由,只是现下不能讲罢了。

他居然笑了。

那种渐渐绵延开来的笑容就像是海潮撞向礁石后散开的花,白色的,温柔的,耀眼的。

“我想请您帮个忙。”他双手放在桌上,一脸诚恳。

“我是生意人。”我尽量让我的声音听上去不那么冷。

“我想确认一下,这里什么都可以交换。”

我转过身端起泡好的茶水,将两枚君山银针放在他面前一一排开,一枚推到他的面前,一枚放在我的手边。

他看着我,我将两枚茶叶交换位置。

“等价交换,各取所需,不能后悔。”我说道。

“好,我想用我的五年寿命换身边我用心交付的人一切安好,乱世之中,无碍无恙。”

我差点突出声。

“你是不是不理解等价的意思?”

好气不好笑,我就那样看着他。

他叹了口气,忽然让我觉得他有活了半个世纪的沧桑。

“我怕……”他顿了顿,“我怕我的生命中也没有几个五年。”

我捧着茶的手一抖,几滴茶水洒在了桌子上,看他拿出纸迅速擦去。我感觉自己的心都在滴血。

“那……四分之一的生命如何?”

“你别开玩笑,你究竟有多少光阴,能容得起你这般挥霍。”我声音一低。

“不,”他忽然抬起头,“我相信值得。”

看他心意已决,我重新倒了一碗茶推到他手边,“君山银针,尝尝吧。”

他想都没想,拿起茶一饮而尽。

我的心又一次滴血。

“对了,用这支笔整个名。”

他潇洒地勾名,随即道谢准备离去,临行前带走了那两枚茶叶。

我看着他肆意又极具章法的秀字出了神。

“剩下的四分之三在某种特定情况下也可以成为整数,你信吗?”

我猛然抬头,看见他沐浴在微光之下。
他的最后一句话,没有得到我的回答。

(二)

后来的后来,我发现一朵奇葩不可避免地开在了我的店里,暂且论他为热爱生活之人,当然他就像是高压锅的喷气嘴,如此比喻,不知是否准确。

“我叫蔺初夏。”他第一次正式介绍自己。

“书香门第出身吗?”我问道。

他很疑惑,显然对于这个问题的出现毫无预料。

“令初下,群臣进谏,门庭若市。”我挑衅地看了他一眼,“我读过书。”

他嘴角一勾,旋即声音压低,“您还是待在这里安全一些,这个世道,读书的先生是要遭劫难的,批斗大会一场接一场,谁都不知道什么时候是个头。”

我看着他谨慎的样子,不由得笑出了声,“所以屋里屋外的是非才不容易分辨。”

气氛变得尴尬,除了门外高声的批斗和呼喊,屋内静到了极点。

“为什么做这笔交易?”我突然问。

“修齐治平,只有我在乎的人平安顺遂,我才能安下心做事,静下心做人,不念外物喜悲,多感人间忧乐。”语出惊人。

“你很在乎你的家人。”

“我在乎的不仅仅是家人,生命中将我真心以待的人都是贵人,知恩图报,人之常情。”

我再次惊讶地看了看,他继续补充道:“此生为人,若不能做成大事,那就自小事起,逢事必究;此生为子,若不能改换门庭,那就自即日起,尊亲爱友。如此一生,何憾何悔?”

“君子之风蔚然,就算不成大贤,也不虚此行。”我认真地对他说。

四分之三是整数,你信吗?”

猝不及防。
我翻了个白眼。
他果断闭嘴。

“你要惜命,你想要的也许只是大梦一场,到时候你就不会这么乐观了。”又一次黄昏,我打开门送他走出疏离宇。

“我知道。”

他的笑在我脑海中占据一席之地,迎着夕阳,我忽然觉得,他失去的四分之一,可能不会完全弃他而去。

……

那天之后,他再也没来过。
不问人间事,是我三十几年前给自己定下的规矩。
不久之后,因为一些势力的干涉,疏离宇与我一同再次启程,搬往别处。
这个城市最后留给我的,竟然是他那个不靠谱的待证明命题。
也是他穷极一生要论述的命题。
我说过,一个人留在某个地方是有理由的。当这个理由消失以后,有些本来有趣的事就覆于黄土之下,不见天日。

疏离宇的旧址,就成了空空的房间,门口有放过长信宫灯的痕迹,也有奇花开放的声音。

“蔺初夏,我等你的好消息。”

我如此想,头也不回地跋涉向脚尖正对的方向。

(三)

半个世纪以后……

我端着茶碗,从木窗中望去,附近大学学生的议论声传入我的耳中。

“听说了吗?国内书法协会的蔺先生要来咱们学校办讲堂了!”

“真的吗?是书法类型的讲堂吗?听说蔺老的字极具特点,又有少年锐气,也有老成的沉稳呢。”

“不对不对,听说这次讲堂的名字叫……叫……”

“‘四分之三也能成为整数’,是哲理讲座。”

我倚着桌子,忽然想起了几十年前一个少年,一个喝君山银针像喝白开水的少年,一个眼里坚毅无比的少年。
一个舍弃了二十五年生命的少年。
近些年来,“蔺初夏”这三个字渐渐成了许多人的信仰。
有人羡慕他的博学,羡慕他自成一派的墨迹。
但传为美谈的,其实是他与家人闲坐,和和睦睦,是他与挚友雪地出游,乐比景更胜一筹,是他心如止水,只为他在意的人泛起涟漪。
他呀,倒是真的没有遗憾,没有后悔。
现世之人,无不羡慕他的处事方式,前不久他接受采访的时候还谈到,他所爱的都在身边,都在他的生活里未曾远去。
“如此人生,何憾?何悔!”他对着镜头,微微一笑。
现实中……
我看着手中的信,忽然有了感觉。


  • 亲爱的初夏先生:

来信收悉。感叹君依旧笑颜如从前。

如今我才发现,你放弃的四分之一全部成为你现在生命的一部分。举例,你原先一百天之中只能吃七十五天鱼肉,但是你现在每天都能够吃到;你原先一百天中只有七十五天能够与父母欢谈,如今却是每天都见。你典当给我的时间都浓缩在你应有的年纪里,四分之三,加四分之一,等于整数一。

我回答了你当年的问题。

这一句“我信”,送还给你。

二十五岁不是小数字,有太多人的得失建立在你放下的这些日子之上,望你惜命。

如此人生,值得你当日抉择。

无憾。

无悔。

祝身体健康
姜祭临


停笔那一刻,我有些庆幸。人世间知足者常乐,而知足者,遇见的多了,周围的空气都能升温。

就跟初夏时候一样。

我看着茶碗中君山银针一起一落,香气充盈在我的脑中,白毫如羽,三起三落,譬如人生,蔚然成趣。

“岁月要是这样走过,仓皇一些,又能如何呢?”

昏黑的暮色中,我看着人群散去,重新回到了疏离宇,吹灭了灯。

后记

这个月第三次收到无名包裹了。

不用打开我就知道,肯定是一包君山银针。

这种茶无疑适合蔺初夏,哪怕我认为他也许不会品茶。

君子之风,柔而不懦,韧而不露锋芒。

晚饭时候了,我走在大街上,路灯从远方亮到眼前,饭香罕见地刺激了我。远远的,我看见有一个人影停在疏离宇门口,他俯身放下一个东西,转身离开。

“不坐坐,就急着回去?”我笑着看着他。

“不了,饭熟了,在等我呢。”

他慢慢走远了。我想收回我的话,他不是时间的强敌。

是克星。

从此,他也淡出了我的生活。

人来人往很多年了,疏离宇又少了一个有趣的灵魂,我忽然有那么一丝丝惋惜。

“初夏的空气,充满了烟火的气息,你说呢?”

无声。

南戏凉生
2021年6月30日

随笔

抬头一看,整个黑幕布似的天空星星点点的闪烁着,刚开始只能看见一个又一个北斗七星一样的连串的星链。
再次出去,从四合院中透过去的方形的天空上,是无数颗斑斓的,跳动的星星,有微弱的细小的闪动着的,也有硕大明亮的,有金黄麦田一样热烈的黄色星星,也有白练雪莲般一样纯洁的,星星的排布是大自然最得意的一笔,细密而又大小不一,间隙而又或明或暗。

222

星星大多是连在一起组合成各种各样的形状的,像是轻跃而起的独角兽,又像是弯弯的白船,也有很多零散着的,就那么紧紧靠在一起,那是我从来没有见过的样子。我转着圈,星星就像流动的水一样旋转起来,托着俏皮的尾。我贪婪的疯狂的看着他们,想要尽收眼底,此刻我好像坐在阿尔卑斯雪山上仰望星空,我从来没有离星星这么近过,也从来没有这么真切的感受过他们,我看向那片没有边际却又框在方里的天,黑色的天空已经被星星铺满了,但没有专业设备,只能感叹于她的绚丽闪耀和再多看一眼,希望能在心里留得久些

333