0%

本文将简要介绍火爆全网的NLP对话AI:ChatGPT的注册使用教程。

1、使用dl工具,使用全局模式,选us节点

2、打开Chrome浏览器无痕模式

3、访问 OpenAI ChatGPT 入口:https://chat.openai.com/auth/login

4、填写非国内邮箱地址

5、使用短信接收平台验证:https://sms-activate.org/

6、注册完成后,登录截图如下:

JS装饰器是ES7的新语法,浏览器,nodejs不一定支持,需要babel转译。

实验环境

创建一个目录test,结构为:

1
2
3
4
5
6
7
.
├── .babelrc
├── .npmrc
├── lib
├── package.json
└── src
└── index.js

babel的装饰器配置:

阅读全文 »

元编程

什么是元编程?

用代码来生成代码,或者说,用程序来生成程序,就叫元编程。Python能通过反射实现元编程。

什么是元类?

与元编程相关的一个概念是元类。什么是元类呢,具体到Python,用来创建类的类,就叫元类。元类是制造类的工厂。

在Python中,一个普通类创建出来的东西是类的实例,实例是一个对象。而元类也是一种类,它创建出来的东西是另一个普通类,普通类也是一个对象(Python中一切皆对象),然后这个普通类,又可以创建出类的实例。所以说,元类是类的类。它们的构建过程如下图:

Python中:

1、所有非object类都继承自object类(包括type)
2、所有类的类型都是type(包括type、object、元类)
3、type类继承自object(符合第1句)

虽然type也继承自object,但是我们自己写的类,继承自object与继承自type,会有些不同。

type元类

type这个类,不仅可以获取Python中对象的类型,比如type(123),会告诉你123是int类型(int也是类)。

type也可以作为元类,来构建其他类。语法是:

type(name, bases, dict) -> a new type 返回一个新的类型

阅读全文 »

属性:这里表示类(或类的实例)中的变量与方法的统称。

所以搜索顺序包括:类的属性搜索顺序、类的实例的属性搜索顺序。

下面是所有魔术方法同时出现的情况下,类或实例的属性搜索顺序。

默认搜索顺序

对于类,比如查找A.x。A是类,x是类的属性。

类属性的默认搜索顺序:A自己的x(即A的属性字典__dict__) ⟶ A的父类的x [1] ⟶ 父类的父类的x… ⟶ object的x

对于类的实例,比如查找a.x。a是A的实例,x是实例的属性。

实例的默认搜索顺序:a自己的x(即a的属性字典__dict__)⟶ a从父类的构造方法(__new__, __init__)继承来的属性 ⟶ A自己的x ⟶ A的父类的x [1] ⟶ 父类的父类的x… ⟶ object的x

[1]:

如果A是单继承,直接不断向上找父类。如果A是多继承,由Python3的mro生成一个有序的继承列表,依次找父类。

相关的魔术方法

与搜索顺序相关的魔术方法有:

1、反射相关的:__getattr__, __setattr__, __delattr__, __getattribute__

2、描述器相关的:__get__,__set__,__delete__

下面是所有魔术方法同时出现的情况下,类或实例的属性搜索顺序:

阅读全文 »

装饰器

要讲清楚装饰器,首先要知道一些前置概念。下文涉及到这些概念的地方,会展开讲述。

什么是装饰器?

装饰器是一种AOP(面向切面编程)的设计模式。

面向对象编程往往需要通过继承或组合依赖等方式调用一些功能,这样可能造成代码的重复,增加了耦合。

而AOP可以在需要的类或方法上切入,切入点可以增强功能,让调用者与被调用者解耦。

这种不修改原来的业务代码,给程序动态添加(或修改)功能的技术,就是装饰器

装饰器可用于日志记录、监控、参数检查等地方。比如业务函数中不应该包含与业务无关的功能,那么可以构建一个logger装饰器,对业务函数增加日志功能。并且logger装饰器可以是通用的,需要日志功能的地方,都可以使用logger装饰器,达到复用的目的。

装饰器的分类

无参数装饰器:无参数装饰器实现的关键是“闭包”,即嵌套函数与自由变量。

带参数装饰器:带参数装饰器实现的关键是“柯里化”,多层嵌套函数可以实现柯里化。

什么是闭包?

在讲什么是闭包前,需要先讲一个概念:自由变量。什么是自由变量呢?

未在本地作用域中定义,就是出现在嵌套函数中,定义在某函数的外层函数的作用域中的变量,叫自由变量

如果某函数(即内层函数)引用了外层函数的自由变量,这样就形成了闭包

阅读全文 »

描述器

什么是描述器?

一个类中定义了如下一个或多个魔术方法,这个类的实例就是描述器:

__get__,__set__,__delete__

通常需要两个类来构建描述器:

如果类B的类属性x,指向另一个类A的实例。被指向的A的实例就是描述器对象。B.x是描述器,B也是描述器的属主(owner)。比如:

1
2
3
4
5
6
7
8
9
10
11
12
13
class A:
def __get__(self, instance, owner):
pass

def __set__(self, instance, value):
pass

def __delete__(self, instance):
pass

class B:
x = A() # x是描述器
pass

类属性的值,通常是一些已有类型的对象,比如字符串、列表等。

当使用了描述器,类属性就指向一个描述器对象,描述器通过三个魔术方法,可以自定义属性的行为。

阅读全文 »

查看Python的浮点数如何在内存中存储

下面的探讨主要针对Python3,在Python2中不一定适用。

Python的浮点数实现原理:
CPython实现有一个PyFloatObject的结构体,用来构造Python的浮点数类型:

typedef struct {
PyObject_HEAD # 这个对象包含:引用计数+对象类型,占8+8=16字节
double ob_fval; # 这个是存储浮点数的地方,Python的浮点数就是C的double,双精度
} PyFloatObject;

所以Python的浮点数类型占24字节:
引用计数+对象类型+双精度浮点数 = 8+8+8 = 24字节
不过Python3的整数长度无限,所以占字节数不定

用Python代码验证浮点数:

代码:

阅读全文 »

课程设计2

题目见 汇编语言 第四版 作者王爽 p312

这篇文章是《汇编语言 第四版》的完结篇。

概述

1、vm虚拟机中安装win98se,以下称为win98

2、成功安装系统后,虚拟机添加一个新软盘(需要创建软盘映像.img文件)。

3、启动win98系统,将下文源码编译,然后执行程序(需要masm汇编器)。

4、关闭win98系统,在虚拟机中,设置软盘为启动盘。

5、启动虚拟机,我们自己写的程序就能执行了。

如果用两个硬盘,即添加新硬盘代替软盘,然后设新硬盘为启动盘后,启动失败(暂不管此问题)!

程序结构

软盘:第1扇区存放我们的引导程序,第2-3扇区存放主程序,实现4个功能。

硬盘1:是win98系统盘,第1扇区有mbr引导程序。

开机后,软盘为启动盘,加载我们自己的引导程序,执行引导程序,然后加载2-3扇区的主程序。

内存结构

阅读全文 »

中断例程装载程序源码:

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
; 安装新的 7ch 中断例程,实现如下功能的子程序:
; 1) 清屏
; 2) 设置前景色
; 3) 设置背景色
; 4) 向上滚动一行

; 入口参数:
; ah=功能号:0清屏,1前景色,2背景色,3向上滚动一行
; 对于1、2号功能,用al传递颜色值,范围0~7的整数

assume cs:code
code segment
start:
mov ax,cs
mov ds,ax
mov si,offset setscreent ; ds:si指向中断例程的代码

mov ax,0
mov es,ax
mov di,200h ; es:di指向中断例程装载位置
mov cx,offset setsrcend - offset setscreent ; 中断例程长度
cld
rep movsb ; 串传输

; 设置 7ch 号中断向量
mov ax,0
mov es,ax
mov word ptr es:[7ch*4],200h
mov word ptr es:[7ch*4+2],0

mov ax,4c00h
int 21h

; 中断处理程序开始
setscreent:
jmp short set ; 此指令占2字节
; 此dw数据开始地址为 0:200h入口地址+2 即0:202h
; sub1为数据标号,dw sub1相当于dw offset sub1
dw 200h+sub1-setscreent,200h+sub2-setscreent,200h+sub3-setscreent,200h+sub4-setscreent
set:
push bx
cmp ah,3 ; 判断功能号是否大于3
ja sret
mov bl,ah
mov bh,0
add bx,bx ; ah中的功能号*2=table表中的偏移
call word ptr cs:[bx+202h] ; 此中断执行时,cs=0
sret:
pop bx
iret

sub1: ; 清屏
push bx
push cx
push es
mov bx,0b800h
mov es,bx
mov bx,0 ; 显存的偶地址单元为字符
mov cx,2000
sub1s:
mov byte ptr es:[bx],' ' ; 空格填充屏幕
add bx,2
loop sub1s
pop es
pop cx
pop bx
ret

sub2: ; 设置字体颜色
push bx
push cx
push es
mov bx,0b800h
mov es,bx
mov bx,1 ; 显存的奇地址单元为属性
mov cx,2000
sub2s:
and byte ptr es:[bx],11111000b
or es:[bx],al
add bx,2
loop sub2s
pop es
pop cx
pop bx
ret

sub3: ; 设置背景色
push bx
push cx
push es
mov cl,4
shl al,cl
mov bx,0b800h
mov es,bx
mov bx,1
mov cx,2000
sub3s:
and byte ptr es:[bx],10001111b
or es:[bx],al
add bx,2
loop sub3s
pop es
pop cx
pop bx
ret

sub4: ; 向上滚动一行
push cx
push si
push di
push es
push ds
mov si,0b800h
mov es,si
mov ds,si
mov si,160 ; ds:si指向n+1行
mov di,0 ; es:di指向n行
cld
mov cx,24 ; 共复制24行
sub4s:
push cx
mov cx,160
rep movsb ; 一行复制完,si+=160,di+=160
pop cx
loop sub4s
mov cx,80
mov si,0
sub4s1:
mov byte ptr [160*24+si],' ' ; 最后一行清空
add si,2
loop sub4s1
pop ds
pop es
pop di
pop si
pop cx
ret
; 中断处理程序结束

setsrcend:
nop

code ends
end start
阅读全文 »