瞎聊:Python2.x 和Lua中的字符串

Python2.x 中的String对象的实现让我觉得有点不可思议。Python的设计者为了提高内存利用率,使用了intern的机制来共享相同的字符串,也就是说如果你有两个字符串: s1='python' s2='python's1s2实际上是指向同一个内存块的,他们共享了同一个PyStringObjectPython内部维护了一个dict类型的变量interned来记录所有的共享字符串,这就引出了一个问题。由于共享字符串的维护直接依赖于Python中的dict,对interned查询需要的参数就应该是一个PyObect的‘派生’类型,不管interned中是不是已经存在了需要的字符串对象,Python总是会先建立一个零时的字符串对象,然后再以该零时对象为interned的一个key去查找是否存在一个已缓存的相同的字符串,如果存在的话就丢弃这个零时变量而是用interned中的缓存。这里最大的问题是在建立这个零时的字符串对象时有一个拷贝内存的过程: Py_MEMCPY(op->ob_sval, str, size+1);如果当前要创建的字符串还没有被缓存过,那么这里一切都很好;但是如果这个字符串已经缓存过了,这次所做的内存拷贝就是无用功,而且还是个耗费时间的无用功。如果字符串比较大,这里对效率的影响可想而知。

 

针对这个问题,最直接的想法是能不能不拷贝字符串而直接去根据参数中传进来的字符串去判断这个字符串有没有被缓存过了,这样做的话也就意味着不能再使用Pythondict来维护这些字符串缓存了,这可能就需要引入专门的代码来操作一个专用的数据结构了。相比较而言,Lua中使用一个stringtable来缓存所有字符串,创建一个新字符串的时候是先根据源字符串计算出一个hash值,再根据这个hash值去stringtable中查找,只有在这找不到时才会真正的创建一个通过拷贝创建一个新字符串。所以Lua中的字符串就没有这个问题。

 

Python的设计者肯定是意识到这个问题的,这应该也是他们权衡后的决策结果。这里纯粹就是一个概率游戏了,碰到某些极端应用时这个实现的效率可能会让人无法接受。这个问题也许只是Python广为诟病的速度问题的冰山一角。

 

 

Python Comments(79) Fri, 09 Jul 2010 07:21:19 +0800

The Vim epiphany

 Switching from the world of easy-to-use modeless editors (Notepad, TextMateBBEditXcode etc) to the unfamiliar modal landscape of Vim requires a large effort. I suspect that a fairly common outcome is that, without sufficient motivation and commitment, many people end up giving up and going back to what they were comfortable with before.

If you're one of the lucky ones, this won't happen to you and you will instead arrive at an "epiphany moment" (or perhaps a series of small epiphanies) in which you feel like you finally understand what all the fuss is about, and decide that this is the editor that you would like to take for your lawfully wedded wife, or husband as the case may be.

Some people never experience that moment, and some experience it in entirely different ways with an entirely different editor, like Emacs. Others never have an "epiphany" with any editor, but instead settle in comfortably with an editor like TextMate or an IDE like Eclipse.

In this brief article I'm going to try to convey the essence of my personal "epiphany" with Vim in a way that will be understandable to anybody, even someone who's never touched Vim, as long as it is read with a receptiveness and a desire to "get it" and find out what all the fuss is about.

Power

Vim is extremely powerful, but that's not what this is about. Emacs is extremely powerful too, as is any number of IDEs. Being able to do super-complicated stuff isn't something that can set an editing environment head and shoulders above the rest, but is rather a minimum base-line requirement.

For me the thing that matters about Vim is actually the simple stuff. The basic, repetitive editing actions which you do literally a thousand times a day. If an editor can make those things as easy as possible for me, then it's won my heart.

This is why Emacs could never truly win me over. The easy stuff just didn't feel easy enough; the key combinations too uncomfortable and the customization (using Emacs Lisp) had too high a barrier to entry.

Vim, on the other hand, instantly felt right: easy-to-remember, mnemonic key commands; excellent default settings out of the box; easy customization using a familiar, C-like scripting language; comfortable keyboard access (almost no modifier keys or sequences of multiple keys being held down).

Let's illustrate with a quick example:

if (foo)
{
    bar();
    baz();|
}

Imagine you're editing the above snippet and the cursor is at the end of the fourth line (shown with a vertical bar, |) and you decide that you want to insert an additional function call above that line.

With a "normal" text editor your typical pattern will be:

  1. Hit the "up" cursor key to go to the previous line
  2. Hit "Return" to open up a new line
  3. Start typing the additional function call

Note that if your editor is indentation-aware at least you won't have to worry about tabbing over before you start adding your function call, because you'll already be in the fourth column.

Now let's compare the Vim way of doing this:

  1. Hit "O" to open a new line above the current line
  2. Start typing the additional function call

The obvious advantage here is that we've achieved what we wanted in two steps rather than three; a very important distinction when we're talking about something that you probably want to do dozens or even hundreds of times in a normal day of coding. This two-step pattern is something that will come up again and again in Vim: "prepare to do something" and then "do it".

The not-so-obvious advantage but equally important in my mind, is the fact that with Vim there is a much smaller cognitive gap between what you want to do, and how you instruct the editor to actually produce the result that you want. That is, what you want to do is "open a new line above the current line", and the way you do it is to type "O", which is the Vim command for "open a new line above the current line". This command will work as you would expect no matter where the cursor is on the line.

In a normal editor on the other hand, the cognitive gap is larger. We can make the gap even more evident if instead of placing the cursor at the end of the line we imagine that it is somewhere in the middle (perhaps we moved it there to correct a typo). Note the cognitive gap between what we want to do (open a new line above the current line) and what we actually have to instruct the editor to do in order to get what we want:

  1. Hit the "up" cursor key to go to the previous line
  2. Hold down "Command" and the "right" cursor key to jump to the end of the line
  3. Hit "Return" to open up a new line

So that's three steps and only one of them actually matches up with our final intention (opening a new line); the first two steps instead have us thinking about completely unrelated things, like moving to the previous line (a line we don't even want to edit) and jumping to the end of a line (again, not even one we want to edit).

If you give Vim a try and start analyzing how you do things in Vim and how you do them in your old text editor, you will see this kind of pattern emerge again and again. The distance between what you want to do andhow you do it tends to be so much shorter in Vim.

And the reason this is so important is because it applies to operations which are so common while editing code. Things like:

  • opening up a new line before the current line
  • opening up a new line after the current line
  • appending to the current line
  • deleting a line
  • moving a line
  • copying a line

Learn these basics and you will be loving Vim already. The basics alone are enough to make a compelling case. But that's not all you get.

Vim makes the basics easy but it also makes the hard stuff easy too. You don't have to learn all the high-level "power features" on day 1, but as you go you will gradually pick them up, one by one. Things like macros, multiple clipboards ("registers" in Vim lingo), awesome buffer/window management, amazing customizability. And all of this in a rock-solid environment which can handle any number of files and files of any size.

 

Original post: https://wincent.com/blog/the-vim-epiphany

VIM Comments(45) Thu, 20 May 2010 04:58:53 +0800

皮皮书屋

皮皮书屋,不错的IT电子书共享网站,推荐!

 http://www.ppurl.com/

 

 

Reading Comments(63) Thu, 06 May 2010 20:41:53 +0800

Why 42?

我上初中时看过银河系漫游指南,后来又看了电影。感觉电影没有书有意思。

书中最有意思的是Answer to Life, the Universe, and Everything turns out to be 42.

在后来很多地方我都见过有人使用42当作一个“随机”选择的数字选用。

下面是Douglas Adams本人回答的为什么是42。

 

 (Mark J Cherkas) wrote: 

>I am new to this group so bear with this beginners question: 

>Why is the answer 42 ? 

>Has Douglas Adams ever explained this ? 

 

The answer to this is very simple. It was a joke. It had to be a number, an 

ordinary, smallish number, and I chose that one. Binary representations, 

base thirteen, 

Tibetan monks are all complete nonsense. I sat at my desk, 

stared into the garden and thought '42 will do' I typed it out. End of story. 

Best, 

Douglas Adams 

London, UK                     |   d...@dadams.demon.co.uk (dormant) 

Currently in Santa Fe, NM      |   ada...@nic.cerf.net (current) 

 

http://groups.google.com/group/alt.fan.douglas-adams/msg/d1064f7b27808692?pli=1

Reading Comments(519) Fri, 23 Apr 2010 03:14:23 +0800

CMD Tips

 命令行历史:

F7弹出一个命令选择窗口,

F8输入少数几个字符后按F8自动补全,

F9弹出一个窗口输入命令序号

 

Dpath:

Allows programs to open data files in specified directories as if they were

in the current directory.

 

重定向

Chkdsk /r 2> diskerror.txt; 只将标准错误发送到文件中

2>&1; 将标准错误重定向到标准输出

 

(command1 & command2 ...) 命令分组功能

Hostname & ipconfig  & netstat -a > current_cfg.txt这条命令只将netstat -a的输出发送到文件中

(hostname & ipconfig & netstat -a) > current_cfg.txt 这条命令会将所有输出合并后写入文件中

 

一些有用的工具(用法参考各自的帮助)

Typeperf 性能计数器

Wevtuitl 事件管理

Schtasks 管理计划任务

Diskpart 磁盘管理

Fsutil 磁盘维护

Defrag 磁盘整理

Where 文件查找

Code Comments(19) Tue, 06 Apr 2010 19:33:53 +0800

10,000-Hour Rule

 Gladwell notes:

“The idea that excellence at performing a complex task requires a critical minimum level of practice surfaces again and again in studies of expertise. In fact, researchers have settled on what they believe is the magic number for true expertise: ten thousand hours.”

Code Comments(16) Wed, 04 Nov 2009 19:54:49 +0800

Blocks (C language extension)

 玩聚上看见 神啊,C 终于开始支持 closure 了,吓了一跳啊,我的天啊!

 

 

#include <stdio.h>
#include <Block.h>
typedef int (^IntBlock)();
 
IntBlock MakeCounter(int start, int increment) {
	__block int i = start;
 
	return Block_copy( ^ {
		int ret = i;
		i += increment;
		return ret;
	});
 
}
 
int main() {
	IntBlock mycounter = MakeCounter(5, 2);
	printf("First call: %d\n", mycounter());
	printf("Second call: %d\n", mycounter());
	printf("Third call: %d\n", mycounter());
 
	Block_release(mycounter);
 
	return 0;
}
/* Output:
	First call: 5
	Second call: 7
	Third call: 9
*/

 

Code Comments(116) Sat, 17 Oct 2009 03:03:44 +0800

解决VSCmdShell在VS2008下崩溃

http://vscmdshell.codeplex.com/ 下载了VSCmdShell的最新版(其实很久没更新了),安装后在VS2008下无法使用Cmd shell,只能使用Powershell。很郁闷

上官网的Issue Tracker看了下,发现了相关的问题的描述http://vscmdshell.codeplex.com/WorkItem/View.aspx?WorkItemId=14645

其实是代码中硬编码了VS2005的注册表路径,而我没有安装VS2005,运行VSCmdShell后VS自然就崩溃了。解决方法只能自己下代码把注册表路径改掉重新编译,覆盖安装文件。这里要说的是,其实没必要完全按着官方的说明安装很多软件才能去编译源代码(我不写.NET代码,所以那些工具我都没有用过,当然也没有安装了)。打开解决方案,我们只要修改VSCmdShell2005项目下的CommandShellHost.cs文件中123行,把8.0改成9.0即可。编译时选择Debug配置,这个配置编译过程中不会调用我们没有安装的那些工具。当然,我们可以修改项目属性,让编译器优化代码。把生成的Microsoft.VSPowerToys.VSCmdShell.dll和Microsoft.VSPowerToys.VSCmdShell.Interfaces.dll复制到安装目录覆盖即可。

Code Comments(21) Wed, 14 Oct 2009 06:21:44 +0800

CRC32

 via: http://www.sunyzl.cn/read.php/96.htm

 

#include <tchar.h>

static unsigned long g_crc32_table[256] = {0};

void init_crc32_table()
{
	int i, j;

	for(i = 0; i != 256; i++)
	{
		unsigned long crc = i;
		for (j = 0; j != 8; j++)
		{
			if (crc & 1)
				crc = (crc >> 1) ^ 0xEDB88320;
			else
				crc >>= 1;
		}
		g_crc32_table[i] = crc;
	}
}

unsigned long crc32(char* buf, unsigned long len)
{
	unsigned long oldcrc32 = 0xFFFFFFFF;
	unsigned long i;

	for (i = 0; i != len; ++i)
	{
		unsigned long t = (oldcrc32 ^ buf[i]) & 0xFF;
		oldcrc32 = ((oldcrc32 >> 8) & 0xFFFFFF) ^ g_crc32_table[t];
	}

	return ~oldcrc32;
}

int _tmain()
{
	init_crc32_table();
	_tprintf_s(_T("crc32(\"StarsunYzL\") = %08X\r\n"), crc32("StarsunYzL", 10));

	return 0;
}

 

Code Comments(30) Sat, 10 Oct 2009 03:35:43 +0800