Python: Numeric and Dynamic Typing

      看书还是能学到新东西的,好好的了解了一下Python的Dynamic Typing以及垃圾收集。收获蛮大。

Numeric Type:

      这是最常用也是最简单的数据类型。值得注意的是 // 和 / 在python2 和 python3 中的区别。在python3中,/ 始终是浮点除。

      python的各种进制数也很好用。关键输出要注意,比如输出16进制,前面会自动加上0x,这在有些情况下是不希望出现的。使用format就可以解决这个问题。数的操作都比较浅显易懂,Fraction等都已经涉及过。估计也难得用python来位操作。

Dynamic Typing:

      Python的优点之一是不需要声明变量类型。这是怎么做到的?Python的每个变量都可以认为是一个指针,更确切是”Reference”。然后变量引用对象。对象知道自己是什么对象。因为每个对象都有 type designator和reference counter,所以”Types Live with Objects, Not Variables”。类型根本不关变量的事。
      这样做就需要垃圾管理机制。就是python的gc。每当引用变为0,就可以回收该对象的内存空间。但是这里有一个很著名也很普通的问题: cyclic references。比如 L = [1,2],L.append(L) ,就构成了一个循环引用。Python是怎么处理的我就不管了。
      当Python要比较的时候,可以用 ==,代表的是值相等,也可以用is,代表的是引用是否相同。比如:

      因为这种机制,很多对象都是共享的(Shared References )。不可变类型不要紧,可变类型就有问题,一旦改变某个变量的引用,就会使其他变量也变化,就是所谓的in-place object changes。要灵活运用L[:]和copy.deepcopy()

refcount 和 weakref:

      不深入看看Python的引用是无法完全理解这种机制的。还好Python提供了查看引用的方法。这里要注意对于一个数的引用是出乎意料的,这是因为Python的Cache机制。反正数是不可变的,多给引用完全没有问题。同样小字符串也是有cache的。然后这里sys.getrefcount,总是多1,查看文档,发现这是因为这个函数本身就临时引用了一次变量,想想蛮有道理。

      为了避免cyclic references,python提供了 weak ref机制,主要原理是这次引用不增加对该对象引用的计数,就相当于没引用。好吧,我讲不清。看这里。然后代码也能说明一切。这个功能的主要作用是防止一些大对象不能及时回收。list,dict什么的不能直接支持,要包裹一下。

[第8天] 鼠标控制

      其实现在已经第10天也已经完成。但是只记录到第8天,这不太好啊。第8天,作者讲了怎么控制鼠标以及填了GDT这个坑。总体来说还是轻松简单的,因为GDT基本在之前搞明白了。

鼠标数据:

      鼠标初始化之后,会传送一个字节”FA”。当接受到这个字节后就表示鼠标已经准备好了。在这之后鼠标的数据都是3个字节一组,但是会分3次传送。所以要处理这3个阶段。这3个字节有各自的意义。见OSDev。鼠标还可以进行一些设置, 我直接按作者的来,没有进行其他测试。

Y overflowX overflowY sign bitX sign bitAlways 1Middle BtnRight BtnLeft Btn
X movement
Y movement

数据解读:

      既然得到了鼠标的数据,就要对其进行处理。首要目的就是能移动鼠标。就要获取鼠标的位置。根据第2字节和第3字节就可以知道移动情况。但是Y的移动方向相反,要处理如下:(然后通过 mx += mdec.x; my += mdec.y; 就可以更新鼠标位置)

鼠标移动:

      在这里,鼠标移动还很简单,只要重新绘制鼠标的图像就好了,详细见github。因此也有不足的地方,就是会覆盖图层,如下图所示。这个问题,在第10天解决。姑且就放着不管。

mouse-move
Mouse Move With Error

32位解读:

      作者在这天解释了gdt的载入和程序的跳转。以及作者系统的内存分布。作者的系统从0x00280000开始,我从0xc400开始。但是我以后应该也会往后移。所以来用bochs来看一下gdtr吧。首先bochs指示gdtr在内存0x270000的位置,大小为0xffff。

gdtr-idtr
gdtr in bochs

      所以看看0x00270000位置的内存放着什么吧。因为我只定义了2个gdt,外加一个空gdt,所以一共3个记录。截图显示无误。早发现bochs,我估计我已经到13天了。

gdtr0x270000
0x270000 GDT

注意:

      作者介绍的是PS2鼠标,虽然说USB鼠标模拟了PS2,但在处理上还是存在一定差别,因为在真机上鼠标处理会有问题。鼠标的反映会不正常。

 链接:

  1. bochs debugger

Python运行和基本类型

运行:

       写了Python代码之后就要让其执行。可以交互方式执行,比如终端命令行,或者IDLE,这些都是比较古老的方式。比较新的有IPython,能有很好的效果。特别是notebook,有很多精美的,可以学习一下。

       或者命令行直接执行少量代码,如: python -c "print(2**100)" 。用来计算还是蛮不错的,当然也可以嵌入到shell脚本里。

       但更多的是写成脚本,然后执行。在Unix系统,首先要做的是加Shebang,可以表明这个脚本该怎么执行,否则可能用其他程序执行。标准的写法是: #!/usr/bin/env python 。+x之后可以直接运行。写成脚本之后,也会在被import的时候被运行。所以要注意判断是否是自己main,还是在被import。当然还有exec,reload等等方式。

基本类型:

       下面这张表概括了常用的类型。

python-built-in
Python Built-in Type From:Learning Python

       Python是动态类型,都是指向某个内存区域的。不需要事先确定类型。但是一旦确定了,就只能使用相应类型的操作。

       Python的number支持高精度,我觉得很好用。python还加了Fraction类型,爽屁了。

       Python的字符串是不可变的,重新赋值的话就是重新给个内存区域,这是合理的。(把字符串转成bytearray就可变)。每次说到字符串就想起很多面试时候问的一个问题,怎么反转字符串。 S[::-1] 糊他脸上。Python3默认支持Unicode,所以字符串前不用加u了。

       list是可变的,用处最广泛。也最好用。dict就是key-value对,估计是对key进行hash了,也是我常用的数据类型。但是注意dict的key是随机排的,如下可以排序。

       file类型也是常用的,file是个generator对象。还有set,decimal,fraction等等。

       有可能要测试一个变量的类型。比如用 type(L) == type([]),type(L) == list,isinstance(L, list)等等,这不一定是合适的,因为Python是多态的,Python关心what an object does, not what it is.

 

       有问题,要help。就跟man一样。dir(str), help(str)。足够。