Friday, 13 March 2009

写Musorg程序使用QT4笔记

介绍

最近用写Musorg程序的机会学了一下PyQT4编程,感觉很不错,不过也遇到了不少的问题。在这里为以后做一些记录吧。

QT4 Designer

QT4 Designer为界面的设计提供了非常大的帮助,并且在设计的同时,他能够生成相应的C++代码。不过,我编程一般都会用Python,所以希望能够直接调用设计好的界面。在PyGTK中,我们有pygtk.glade这个模块,能够动态加载GTK设计的XML文件。幸运的是,QT4也提供了动态加载的模块,但是更进一步的是,他提供了一个将设计文件转成Python代码的工具:pyuic4。
该工具,pyuic4的基本是用方法就是:pyuic4 -o <python_file> <qt_ui_file>。选项-o就是 告诉pyuic4应该将生成的Python代码输出到那个文件中。这样一来,我们就可以直接在主程序 中调用相应的UI模块了。至于命名,pyuic4会根据QT4 Designer中最上层窗口的对象名,在其 之前加上UI。

调用生成的代码

如果要调用生成的代码的话,可以用如下的方法:
from ui_api import UI_MusorgMainWindow

class MusorgUI(QtGui.MainWindow, UI_MusorgMainWindow)
    def __init__(self):
        QtGui.MainWindow.__init__(self)
        self.setupUi(self)
        ...

QT4 Layout

在用Designer设计的时候,Layout一直困惑了我一阵。我以为,像GTK一样,QT4直接将Layouts里 边任意一个布局拖进控件里就行。结果发现每次拖进去,布局都没有自动展开,而只是被置于拖进 时的位置,而且大小是要手动调整,这显然不对。折腾了一阵后发现,原来是直接在对象查看器里 找到相应的容器控件,右击,然后选择布局便可。

QT4的信号发送与处理

QT4的信号发送与处理比较显而易见,所以没有遇到太大的问题。和GTK的信号发送与处理类似,也 是通过emit和connect(虽然函数名不太一样)。PyQT4中信号发送如下:
...
self.emit(SIGNAL("dataChanged(int, double)"), int_number, float_number)
...
假设之前这个信号是有一个叫做acontrol的QT4控件发送出来的,那么我们可以在另一个控件中定义 接受和处理该信号的函数:
def on_data_changed(self, int_param, float_param):
    # process the data
    pass
有了该函数之后,我们将信号与函数之间建立链接:
...
self.connect(acontrol, SIGNAL("dataChanged(int, double)"), self.on_data_changed)
...
这样就建立了信号的发送与接收的代码。每当程序执行到emit语句时,就会去查找相应的处理函数。

TreeView笔记

TreeView、ListView、TableView也许是任何一个UI库里边都比较复杂的控件。随着MVC模式的推广, 大部分UI库都在原有的Item-based控件之外又提供了Model-based控件。QT4里边的TreeView、ListView 和TableView就是Model-based,程序里我用的是TreeView。
QT4做的好的一点是的确将M,V,C分开了。M一般是由继承于QAbstractItemModel的类来控制,该类 需要实现以下函数:
  1. data(index, role): 返回对应于index的数据,需要注意的是,该函数在默认情况下应该只有在 role为Qt.DisplayRole的情况下才返回数据,其他时候应该返回空数据(QVariant())。
  2. rowCount(parent): 返回以parent为父节点的节点行数。
  3. index(row, column, parent): 返回以parent为父节点,row行column列的节点的索引。
  4. columnCount(parent): 返回以parent为父节点的节点列数。
  5. parent(index): 返回index索引所对应的父节点,如果没有父节点,返回空索引(QModelIndex())。
V一般是由继承于QAbstractItemDelegate的类来实现的,一般会重载paint()函数来绘画字符串以外 的内容,例如进度条、选项框、按钮等等。
C就是QTreeView本身。当用户选中某一个节点时,TreeView会发射信号,这就是控制器的一种表现。

QThread多线程笔记

刚开始用QThread时,不太习惯,而且犯了一个非常大的错误。该错误在今后的编程中也一定要注意。 其实是因为不知道要这么做,就是每一个QThread就是一个QObject,和其他QObject一样,应该有一个 parent,如果没有,当线程结束时(run函数返回时),它就会抛出异常:“Thread deleted while it's running”。

Semaphore, Mutex, Wait Condition

这三个其实就是我们在进程调用和通信中常用的,没有太大区别。当有共享资源需要控制时,就会需要 用到这些。但是这些还可以用来控制开始/暂停,呵呵~~
用这些来实现开始/暂停的原理其实比较简单:
  1. 让暂停信号(pause_semaphore)拥有一个资源。
  2. 当运行时,程序检测暂停信号资源的个数,如果大于零,那么程序会正常运行
  3. 暂停时,我们获取一个暂停信号资源,这时程序发现资源数不够,就会停止。
  4. 当我们再次开始时,我们释放一个信号资源,这样程序就会继续运行了。
还要注意的是,QThread不能直接控制主程序中的数据(其实也不推荐这么做),所以可以通过发送 信号给主程序,让接受到信号的主程序来做相应的处理。

Monday, 2 March 2009

发Blogspot文章的Python程序

初衷

因为是技术博客,所以经常有代码。每次发篇有代码的博客,都要先将代码用Pygments转成HTML,然后将HTML拷到博客的HTML中,再继续编辑博客。这样 麻烦死了。再者,在网上编辑格式还是不如Python的RST直接写出来的方便,所以就直接用Python的RST来写博客文章,然后通过Google Blogger API发到 网上,这样方便多了。

这篇文章就是第一次采用blogspot这个程序来完成编辑、渲染和上传。

代码

#!/usr/bin/env python
# -*- coding: utf-8 -*-

# utils.py
# author: rshen
# date: 2009-02-27

from gdata import service
import gdata
import atom

def post_blogspot(title, html_content, username, password):
    blogger_service = service.GDataService(username, password)
    blogger_service.source = 'blogup-app-1.0'
    blogger_service.service = 'blogger'
    blogger_service.account_type = 'GOOGLE'
    blogger_service.server = 'www.blogger.com'
    blogger_service.ProgrammaticLogin()

    entry = gdata.GDataEntry()
    entry.title = atom.Title("xhtml", title)
    entry.content = atom.Content(content_type='html',
            text=html_content.decode("utf-8"))

    query = service.Query()
    query.feed = '/feeds/default/blogs'
    feed = blogger_service.Get(query.ToUri())
    blog_id = feed.entry[0].GetSelfLink().href.split("/")[-1]

    return blogger_service.Post(entry, '/feeds/%s/posts/default' % blog_id)
#!/usr/bin/env python
# -*- coding: utf-8 -*-

# blogup.py
# author: rshen
# date: 2009-02-27

from __future__ import with_statement
from docutils import core
from optparse import OptionParser
from rstdirective import *
from utils import *
import tempfile
import BeautifulSoup as bs
import sys

def to_html(rst_file, options):
    f = open(rst_file)
    contents = f.read()
    parts = core.publish_parts(writer_name='html', source=contents)
    html_content = unicode(parts['whole']).encode('utf-8')
    tmp_file, tmp_path = tempfile.mkstemp()
    with open(tmp_path, 'w') as tmp:
        tmp.write(html_content)
    print "HTML Contents written to %s" % tmp_path

    return bs.BeautifulSoup(html_content)

def gen_blog(html_tree, options):
    content = html_tree.find("div")
    title = content.find("h1")
    title.extract()
    content.find("table", { "class" : "docinfo" }).extract()

    sections = content.findAll("div", { "class" : "section" })
    sections_html = ''.join([''.join([str(c) for c in sec.contents])\
            for sec in sections])
    return (''.join(title.contents), sections_html)

def upload_blog(title, html_content, options):
    post_blogspot(title, html_content, options.username, options.password)

Friday, 27 February 2009

中文测试

中文测试标题

该帖子纯粹为了测试中文,如果成功,将在博客上显示正确地中文~~

Wednesday, 25 February 2009

Test

This is a test blog post

If this appears on my Blogspot, then my python script for posting blogs is successful. The following is a test for Pygments code highlighting.

for a in [5, 4, 3, 2, 1]:
    print a

Tuesday, 17 February 2009

流程图生成器(2)

最近用pyparsing写好了流程图定义的模块:
#!/usr/bin/env python
# -*- coding: utf-8 -*-

# flow_parser.py
# author: Rongzhou Shen
# date: 2009-02-11

from pyparsing import *

LSQUARE, RSQUARE, SEMI, ASSIGN, QUOTE = map(Suppress, '[];="')
LBRACE, RBRACE, AT, LBRACK, RBRACK = map(Suppress, '{}@()')

# Definition part of the flow_def file
node_id = Word(alphanums + "_")("id")
node_type = Word(alphas)("type")
declaration = node_type + LSQUARE + node_id + RSQUARE
value = QuotedString('"')
definition = Group(declaration("declaration") + ASSIGN + value("value") + SEMI)

# Flow part of the flow_def file
flow = Group(node_id + OneOrMore(Group('=>' + node_id)) + SEMI)

# Grammar definition of the whole file
flow_impl = OneOrMore(definition)("definitions") + OneOrMore(flow)("flows")
flow_def = AT + LBRACK + QuotedString('"')("flow_name") + RBRACK + LBRACE +\
        flow_impl("flow_impl") + RBRACE

#sample = """
#@("A test flow_chart") {
#    process[node1] = "This is a test process";
#    process[node2] = "This is another test process";
#    a => b => c;
#    ffew => fweji;
#}"""

def test_parse():
    expected = ['process', '[', 'node1', ']', '=', '"',
            'This is a test process', '"', ';']
    test_def = 'process[node1] = "This is a test process";'
    data = definition.parseString(test_def)
    assert len(data) == len(expected)
    assert all([x == y for x, y in zip(expected, data)])

    expected = ['a', '=>', 'b', '=>', 'c', ';']
    test_flow = 'a => b => c;'
    data = flow.parseString(test_flow)
    assert len(data) == len(expected)
    assert all([x == y for x, y in zip(expected, data)])

Tuesday, 10 February 2009

流程图生成器

一直想写一个来着,趁着这次在python.ubuntu.org.cn写[常用库系列]的机会写了这个。目前还不太完善,不过会慢慢改进。接下来要做的就是用pyparsing来完善和扩展我的流程图定义文件。
#!/usr/bin/env python
# -*- coding: utf-8 -*-

from __future__ import with_statement
import yapgvb
import optparse

FORMATS = {"png" : yapgvb.formats.png,
        "jpg" : yapgvb.formats.jpg,
        "gif" : yapgvb.formats.gif}
ENGINES = {"dot" : yapgvb.engines.dot,
        "neato" : yapgvb.engines.neato,
        "circo" : yapgvb.engines.circo,
        "twopi" : yapgvb.engines.twopi}

if __name__ == '__main__':
#    args = sys.argv
#    if len(args) < 2:
#        print "Usage: python state_machine.py <def file>"
#        sys.exit(0)

    parser = optparse.OptionParser()
    parser.add_option("-f", "--format", dest="format",
            help="store the flow chart in FORMAT",
            metavar="FORMAT", default="png")
    parser.add_option("-o", "--output", dest="output",
            help="save the flow chart to FILE",
            metavar="FILE")
    parser.add_option("-e", "--engine", dest="engine",
            help="the layout ENGINE to use for the flow chart",
            metavar="ENGINE", default="dot")

    options, args = parser.parse_args()
    if len(args) < 1:
        parser.print_usage()
        sys.exit(0)

    graph = yapgvb.Graph("States")
    node_dict = {}

    with open(args[0]) as def_file:
        lines = [l.strip() for l in def_file.readlines()]
        for line in lines:
            nodes = line.split("=>")
            prev_node = None
            for node in nodes[::-1]:
                label = node.strip().split("#")
                if not node_dict.has_key(label[0]):
                    node_in_graph = graph.add_node(label=label[1],
                            shape='ellipse', fillcolor='yellow',
                            style='filled', width=0.5)
                    node_dict[label[0]] = node_in_graph
                else:
                    node_in_graph = node_dict[label[0]]

                if prev_node:
                    edge = node_in_graph - prev_node
                    edge.arrowhead = 'normal'

                prev_node = node_in_graph

    graph.layout(ENGINES[options.engine])
    format = FORMATS[options.format]
    if options.output:
        out_file = options.output
    else:
        out_file = args[0] + "." + format

    graph.render(out_file, format)

Wednesday, 28 January 2009

Vim和Shell/GNU Screen搭配的困扰

一直使用Vim与GNU Screen搭配编程,有几个原因: 1. 命令行上的Vim和GVim在功能上几乎没有区别(某些插件是只能用GVim,不过我没有); 2. GNU Screen在重启X时不会影响其中程序的运行; 3. 一直用命令行的话,我可以随时关注命令行上其他程序的情况,例如mutt有无新的邮件,irssi有无新的消息; 但一直有一个问题困扰着我,就是命令行下的Vim屏幕滚动非常缓慢,按住j不动一直到屏幕上最后一行,然后松手,光标会继续往下走十几行甚至几十行,这让我很不爽。 今天作了一个实验,得出以下结果: 1. GNU Screen打开与否和这个现象无关; 2. 此现象只有在分裂Vim窗口时才会出现; 3. GVim没有这个现象; 在网上搜索了一番,暂时没有找到解决的办法。因为GVim没有这个问题,所以暂时用GVim代替。GVim的问题在于离开命令行我就无法得知某些命令行程序的信息。如果能找到解决办法就好了

Thursday, 22 January 2009

irssi提醒脚本

喜欢irssi这个命令行上的IRC,每天都会打开上#ppmm, #ubuntu-cn, #java, #python等频道~~ 命令行工具的一个缺陷在于,提醒功能不完善。虽然用screen,在状态栏上也有提醒,不过并不是任何时候都会盯着命令行的,所以还得有一个图形界面的提醒。 幸好irssi提供了扩展脚本这个功能,所以能够用Perl对其进行扩展。在网上搜索一番之后,发现有人写过提醒脚本,调用gtk-dialog-info这个命令行在屏幕右下角生成提醒窗口。但原始脚本并不是很适合我,所以作了一番修改之后,成了下面这样:
##
## Put me in ~/.irssi/scripts, and then execute the following in irssi:
##
##       /load perl
##       /script load notify
##

use strict;
use Irssi;
use vars qw($VERSION %IRSSI);

$VERSION = "0.01";
%IRSSI = (
  authors     => 'Luke Macken',
  contact     => 'lewk@csh.rit.edu',
  name        => 'notify.pl'
);

sub notify {
    my ($server, $msg, $nick, $address, $target) = @_;

    return if (!($msg =~ /anticlockwise/));

    system("notify-send -i gtk-dialog-info -t 5000 '$nick' '$msg'");
}

Irssi::signal_add('message public', 'notify');
原始脚本采用的irssi信号是print text,虽然这个信号能够检测个人信息,却无法得到消息的内容(所谓的text是指的系统消息,却不是聊天消息)。所以就改成了message public,然后message public又没有一个通用的检测是否个人消息的方法,所以就只能用正则表达式来判断了,有些傻,不过管用。

Wednesday, 21 January 2009

Python Google Translate调用脚本

前一阵子一直想找一个命令行上的翻译程序,就自己写了一个Python程序:
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import urllib
import urllib2
import sys
import jsonlib
from optparse import OptionParser

URL = "http://ajax.googleapis.com/ajax/services/language/translate?v=1.0&q=%s&langpair=%s%%7C%s"

parser = OptionParser()
parser.add_option("-f", "--from", dest="lang1",
        help="The language code to translate from", default="en")
parser.add_option("-t", "--to", dest="lang2",
        help="The language code to translate to", default="zh")

(options, args) = parser.parse_args()
if len(args) < 1:
    print "Usage: python translate.py <translate text>"
    sys.exit(0)

text = ' '.join(args)
print "Translating %s from %s to %s" % (text, options.lang1, options.lang2)
query = (URL % (urllib.quote(text), options.lang1, options.lang2))
req = urllib2.Request(query)
req.add_header("Referer", "http://www.my-ajax-site.com")
r = urllib2.urlopen(req)

data = r.read()
obj = jsonlib.read(data)
if obj['responseStatus'] != 200L:
    print "Error: %s" % obj['responseDetails']
else:
    print "Translated text: %s" % obj['responseData']['translatedText']

Wednesday, 8 October 2008

Eclim: 在Vim中使用Eclipse的功能

Eclipse和Vim的强大谁都知道。我一直在用Vim进行代码编辑,在VJDE的帮助下,很多Java的东西已经变得非常方便。不过最近因工作原因,又必须使用Eclipse。不得不承认,Eclipse作为一个IDE的确是非常强大的,项目管理、自动导入、代码补全、代码格式调整等等都已经非常成熟,而这些是Vim(作为一个文本编辑器)所无法比拟的。 在网上搜索一阵后,找到了Sourceforge上的一个开源项目:Eclim。相见恨晚啊~~Eclim的基本原理是用Eclipse作为服务器后端,用Vim作为图形界面前端,这样既不会因为Eclipse浮肿的图形界面而导致变慢,又能拥有Vim强大的编辑功能,还可以使用Eclipse的许多有用的特性。 目前Eclim已经支持到最新的Eclipse版本Ganymede。Eclim最强大的是Java项目管理,包括创建项目、打开项目、显示项目目录结构、删除项目。它支持多种Java工具,其中包括Maven和Ant。在Maven的支持上,它可以直接读取Maven的pom.xml然后生成相应的Eclipse Classpath文件,并用这个Classpath作为当前项目的Classpath。它同时还整合了JUnit,可以运行某个JUnit测试并显示结果。其中我认为最有用的,而且也是最像IDE的一个特性是能够随时显示Java代码中的错误,它能够随时编译当前的Java代码,然后解析错误文件,并根据文件中的信息知道是在哪一行出现了什么错误~~ 其他的特性当然还包括自动格式化代码、自动导入、代码补全等等。除了帮助Java编辑外,它在其他语言编辑上也提供了帮助,例如XML(随时验证+格式化)、Python(验证)。 如果想知道更多关于Eclim: http://eclim.sourceforge.net

Tuesday, 7 October 2008

新的Python项目

最近喜欢上了命令行的工具,而本身我又喜欢GOOGLE的服务,所以想到了做一个Google服务的命令行工具,当然使用Python。幸运的是Google提供了一系列的Python API来访问他们的数据,其名为Google Data API。

Tuesday, 30 September 2008

Python常用函数和库

介绍了Python的特性,该介绍一下我常用的Python的函数和库了~~ 1. Python内建函数和库 1.1 函数: map(func, list): 将某个函数func作用于list中的每个元素 1.2 库: re : 正则表达式库 正则表达式本身就非常的强大,尤其是Perl 5的正则表达式。Python中的正则表达式库当然也非常不错~~例如,我要找出某文本中所有带括号的字符串:
#!/usr/bin/env python

import re

regex = re.compile(r"\([^)]*\)")
s = "Python is (cool)! So is everthing that uses (Python)!"
matches = regex.findall(s)
for match in matches:
    print match
如此一来,我们就可以得到(cool)和(Python)这两个字符串了,关于正则表达式,网上有太多的文章可以参考了,而且书也一大堆,我就不介绍了~~ urllib: 网络库 这是Python中提供的一个最简单的网络访问库,但非常实用,而且也非常方便~~如果要获取某个网站中的内容(HTML),如下: f = urllib.urlopen("http://www.google.com") html = f.read() print html 以上是用GET方式获取内容,如果要用POST方式的话,可以如下: data = {"some_data" : "some_info"} f = urllib.urlopen("http://www.google.com", data) html = f.read() print html 该库中还有许多其他的网络相关实用函数哦~~ os, sys: 操作系统、文件、系统相关库 os库中包括许多操作系统相关函数,例如获取当前目录os.getcwd(),执行一个命令行os.popen等等。sys库中包含系统相关的函数和变量,例如最有用的莫过于sys.argv,这个可以得到命令行上的所有参数。比如我如果敲入:python todocmd.py add I have to do this,那么sys.argv就是一个数组:['python', 'todocmd.py', 'add', 'I', 'have', 'to', 'do']。 optparse: 命令行解析库 很多时候,我们需要写一个命令行的程序,而这个程序在命令行上又有许多的参数,例如我常用的pal日历程序: pal -r 4 可以告诉我我在4天内的所有事件~~当然,命令行参数远远不止这一个……那么,如果我要写这么一个程序,我就可以用到optparse这个库来解析这些命令行的参数。
#!/usr/bin/env python

from optparse import OptionParser

parser = OptionParser()
parser.add_option("-f", "--file", dest="filename",
help="write report to FILE", metavar="FILE")
parse.add_option("-q", "--quiet",
actoin="store_false", dest="verbose", default=True,
help="don't print status messages to stdout")

(options, args) = parser.parse_args()
以上就是一个简短的命令行解析程序块,当我在命令行上敲入:my_script -f outfile -q时,该程序块就会帮我读取到这些参数,并以数组的方式传给我~~另外,如果我敲入my_script -h,它还会自动输出参数帮助~~ 2. 外部库 2.1 cElementTree (去Google搜索ElementTree) XML在目前的应用非常广泛,而如果要操作XML的话,我们需要相应的解析器~~各种语言都提供了自己的解析器,Python也不例外。在Python中,我比较喜欢的XML解析器是cElementTree。它是ElementTree的C Python版本,所以拥有ElementTree的所有功能,但比ElementTree的性能更好~~以下是一个简短的解析程序:
#!/usr/bin/env python

import xml.etree.cElementTree as ct

f = open("example.xml")
tree = ct.parse(f)

nodes = tree.getiterator()
for node in nodes:
    for child in node:
        print child.attrib["name"]
2.2 yapgvb (http://yapgvb.sourceforge.net) 全称叫做:Yet another Python graphviz binding。知道Graphviz的人都知道其强大,它是用来生成有向和无向图的,对于我来说很有用,因为我可以用它来生成状态机、文字关系图、Ontology树等等。其最大的好处是能够自动排版,使得图中每个节点互不相碰~~用yapgvb的话,我可以非常方便的根据我的内容生成相应的图片。例如:
#!/usr/bin/env python

import yapgvb

nodes = ["jack", "shen", "eden", "xu"]
graph = yapgvb.Graph("Example Graph")
root = graph.add_node(label="Root")
for node in nodes:
   n = graph.add_node(label=node)
   edge = root >> n

graph.layout(yapgvb.engines.neato)
format = yapgvb.formats.png
graph.render("example.png")
可以生成以下图片: 2.3 docutils (http://docutils.sourceforge.net): 文档工具 这是我的最爱,除了Latex之外,一般的小型文档我就用它了~~Docutils自己定义了一种文档语言叫做RestructuredText,用它写成一个文档后,可以用Docutils生成HTML、Latex和S5。HTML和Latex就不介绍了,不过S5是我比较喜欢的东西,当时做幻灯片的时候就是用的RestructuredText生成的S5格式的幻灯片。S5其实是一种专门用来制作幻灯片的HTML格式,最终生成的幻灯片也非常漂亮,而且因为是HTML,所以可以直接用CSS和Javascript来调整版面、格式、颜色等等。 这个是我极力推荐的库,一定要看看~~ 恩,其实Python好的库还有许多,我这里就不一一介绍了。我准备在之后一个一个详细解说,例如:Django(快速原型Web框架), SQLObject(Object-Relational Mapping框架),Epydoc(Python API文档生成),Docutils(文档生成工具),Mako(模板语言工具)等等~~

Monday, 29 September 2008

Commandline Tools

今天找到了几个常用程序的命令行替代品,分别是IRC、GTALK、MSN、电子邮件客户端和GOOGLE CALENDAR的。这些工具能够在一定程度上提高我开发的效率,因为曾经需要用鼠标的(离开键盘)现在均可以用键盘操作~~ 1. GTalk: Freetalk (http://www.gnu.org/software/freetalk/) Freetalk真的很不错,界面简洁,类似于IRC聊天工具,所有操作都是通过命令来完成,例如要知道有哪些人在线的话,敲入/who便可以得到了。 2. MSN: Python MSN lib (http://blitiri.com.ar/p/msnlib/) 其实这本是一个Python写的MSN库,不过作者提供了一个演示程序,但功能比较全面(至少我需要的都有),而且操作也非常方便~~ 3. IRC: irssi (http://www.irssi.org/) 这个客户端已经非常有名了,很多人都在用,和一般的IRC都一样,自己去看看吧。 4. Mail Client: mutt (http://www.mutt.org/) 这个我刚开始用,不过真的很不错,速度很快,而且界面清晰~~最主要的是它的键盘映射和VIM一样,所以非常符合我的口味~~ 5. Google Calendar: gcalcli 这貌似是GOOGLE自己开发的,调用了Google Data API,它没有像前面几个程序那样的界面,只有命令行的操作。例如,如果我要知道这段时间有些什么事件的记录的话:gcalcli agenda 就会帮我输出所有的事件,而且是彩色~~ 6. Todoist: 我自己写了一个程序…… 目前还在开发中,今天晚上刚开始写。现在已经支持项目查询和TODO查询,并用不同的颜色代表不同的重要级别,还要实现的是添加TODO项和修改已有的TODO项。

Sunday, 28 September 2008

Python入门详细介绍

作为最爱的语言之一,首先来详细介绍一下我对Python的认识吧~~当然,Python的特性远远不止我在次介绍的这些,这就需要读者自己去研究了。此文章中所有的代码高亮也是有一个Python的程序所完成的,叫做pygmentize。它可以解析多种编程语言并生成相应的HTML、LATEX等等来对代码进行高亮显示。 和Perl、Ruby一样,Python是一种动态类型语言(Dynamically Typed),也是一种脚本语言(Scripting Language),解释型语言(Interpreted)。这种类型语言的特性在于它们语法简洁,无须编译,拥有非常方便但又强大的数据结构操作,很利于创建初始程序原型或者完成某些小型脚本处理。例如,我如果想要用Python对某个文件中的每一行进行同一个操作的话:
#!/usr/bin/env python

f = open("example.file")
lines = f.readlines()
lines = map(lambda x : x.strip() + " str", lines)
print lines
以上就不一一解释了,但是example.file文件内容如下:
first line
second line
third line
输出结果如下:
['first line str', 'second line str', 'third line str']
Python中我喜欢的特性 Python的特性主要来自动态类型和脚本语言,所以很多我喜欢的特性其实也就是动态类型语言的特性:
  1. 简洁干净的语法结构。和许多语言不同,Python的某个程序块的开始和结束并不是由某个符号或者语句所包围,而是采用冒号和缩进来进行区别,例如:
    #!/usr/bin/env python
    
    def println(line):
    print line
    
    f = open("example.file")
    lines = f.readlines()
    for line in lines:
        println(line)
    
    以上的简短程序中,函数体和函数声明、for语句和语句块都是由冒号和缩进进行分隔,看上去非常清楚,增加可读性。然而,这种方式有利也有弊。在使语法干净的同时,它使得程序的书写非常严格,而且在自动生成代码上也会增加不必要的处理。
  2. 多值赋值和返回。这是脚本语言一个非常有用的特性。Python中有一个数据结构叫做tuple,他只可读不可写,然而却为多值赋值和返回提供了可能。例如,我如果要对多个变量同时赋值,我无须在每一行写一个,可以如下:
    var1, var2, var3 = 3, 4, 5
    这样,一方面减少了我的代码量,另一方面,如果我将同一类的变量放在一起赋值,可以增加可读性。多值返回就更有用了,在很多时候,我们需要返回的不只是某一个变量,而是想返回多个变量。例如:很多时候我们想得到数组中最大元素和最大元素的索引,那么用Python就可以如下:
    #!/usr/bin/env python
    
    # assume the list is "l", and all the values are positive
    def max_in_list(l):
        mvalue = -1
        mindex = -1
        for i in range(len(l)):
        value = l[i]
        if value > mvalue:
            mvalue = value
            mindex = i
    
        return (mvalue, mindex)
    
    value, index =  max_in_list(l)
  3. List comprehension。这是我最喜欢的一个特性,在数组/列表处理上非常实用。其作用是对某个已有列表的每个元素进行操作,并返回新的列表。例如,我要对某个列表中的所有大于2的数字加上另一个数,可以如下:
    #!/usr/bin/env python
    
    l = [4, 3, 5, 87, 4, 6, 4, 2]
    new_l = [x + 2 for x in l if x > 2]
    print new_l
  4. 高阶函数。这其实是各种动态语言都拥有的一个特性,而且非常有用。所谓高阶函数,从简单说来就是指函数可以作为另一个函数的参数。注意这是不是说将函数的返回结果作为参数,而是将函数本身作为参数。例如:
    #!/usr/bin/env python
    
    def add_one(n):
        return n + 1
    
    def add_two(n):
        return n + 2
    
    def process_list(func, list):
        for n in list:
            print func(n)
    
    l = [3, 4, 5, 6, 7]
    print "Function = add_one ", "-"*30
    process_list(add_one, l)
    print "Function = add_two ", "-"*30
    process_list(add_two, l)
    
    Python中还有一个特殊的lambda关键字来代表某个匿名函数例如以上的例子我可以改成如下:
    #!/usr/bin/env python
    
    def process_list(func, list):
    for n in list:
        print func(n)
    
    l = [3, 4, 5, 6, 7]
    print "Function = add_one ", "-"*30
    process_list(lambda x : x + 1, l)
    print "Function = add_two ", "-"*30
    process_list(lambda x : x + 2, l)
    

Friday, 26 September 2008

我常用的工具

在此介绍一些我常用的工具,只是简单介绍,某些工具的具体介绍我会在之后写新的博客,其他的自己看吧,哈哈~~ 实用的工具 1. Google Calendar 按照字面意思,他的主要功能就是一个日历。我平时主要用它记录所有的事件,例如开会、预约等等。其比较好的一个特性是能够通过邮件提前通知(当然是GMAIL啦),而且可以用不同的颜色对不同的事件进行分类,这样我就可以更好的管理我的时间。例如我可以用一种不同的颜色代表不同的项目事件~~ 2. Google Reader 这个很多人应该都知道,是用来订阅RSS的浏览器。订阅RSS是一种浏览各种信息的好方法,我可以在同一时间阅读来自多个网站的不同信息。我常看的有:
  • The ServerSide:这是Java服务器端技术的大型门户网站,包括各种Java服务器端技术的文章,牛人们的博客和各种库升级的信息和使用方法。有时有些新的东西出来时我会去看看,如果有什么比较好的文章我也会过目一下
  • Java.net communit:这是Java技术最大的社区网站之一,包括Java各种技术,常常会有一些技巧方面的文章,所以我也会看
  • JavaWorld:名字就告诉我们这是Java的世界,包括各种技巧性的文章和一些类库的使用方法
  • Python News:包含Python方面的许多新闻,例如Python3000开发的进展等等
  • Bruce Eckel的博客:牛人,主要写关于Java和Python,所以我经常看看
  • 朋友的博客。。。
RSS订阅最大的好处在于谁有更新我都能知道,这样就不用跑到个大网站挨个搜索了~~ 3. Google Notebook 用来作笔记的服务,界面简洁适用,最大的特点在于可以截取网页中的内容作为笔记内容。例如我要对某个感兴趣的文章进行节选,我可以将其内容拷到我的笔记中,而且格式会完全不变~~更方便的是他提供了一个Firefox插件,装上后Firefox右下角会有一个Notebook的链接,点击后就会弹出一个Notebook的新窗口。并且,Firefox的右击菜单也会多一个节选网页的菜单项,可以将选中的网页内容直接插入到我的Notebook中。工作时,我一般会打开Firefox Notebook插件,将其置在所有窗口最上边并且保持置顶,然后用Compiz fusion的窗口收卷功能将窗口卷起来,要用的时候再按快捷键放下来就可以了~~ 4. TODOIST 这个可能用的人稍微少一点,是专门用来管理TODO的。其特性在于非常简洁,而且提供了Firefox插件,可以和GMAIL整合在一起,随时可以通过邮件通知团队中的各位你的TODO列表是什么。TODO的好处在于我每天去上班一打开TODOIST就能知道我这天应该做些什么,而且所有TODO都可以有不同的重要性(在TODOIST中会用不同的颜色进行标记),所以也就知道改先做什么。TODOIST还有一个特性是可以将TODO进行分级,例如某些TODO是某一个TODO的子集,也就是某一个TODO更详细的描述。 在某个TODO完成后,我可以直接将其划入历史中,这样以后还可以知道我做过写什么,以便写文档和日志。 开发工具 1. VIM(之后会有详细描述) 这可是个好东东,就像某些人所说:“VIM是毒品,是鸦片,用上就会无法释手”。好吧,有人称VIM为“编辑器之神”,我觉得也差不多了~~刚开始用时不大习惯,因为各种命令会使你头痛,各种“与众不同”的按键也会使你抓狂,不过用到后来就会发现用回正常的文本编辑器时才更头痛…… 用上VIM,你能真正感受到不用鼠标,手在键盘上飞速敲打的快感~~有点像广告……加上一些插件和配置之后,VIM会变得无敌。 2. Python和Java(之后会有详细描述) 不用说,这是我最爱的两门语言,至于描述嘛,还是留到之后吧~~这两个包含的工具和库可不少:Java有Ant, Maven, Jakarta Commons, Log4J, Dom4J, Velocity等等,Python有Django, cElementTree, SQLObject, NLTK, Mako等等 3. XML(之后会有详细描述) 最近和XML打交道挺多,也慢慢需要处理许多XML代码,之后我会详细描述和XML相关的处理方法以及处理的工具 4. Latex(之后会有详细描述) 这个写文档的工具可不能少,大小论文(包括毕业论文)都是用它了。我有自己常用的模板,也有VIM的编辑插件,所以每次用起来都非常方便。最近学会了TIKZ,可以直接在LATEX编辑源代码然后生成图片(而且非常漂亮),所以就更喜欢了~~ 目前最缺的是一个Linux底下好的画图工具,虽说Dia什么都能画,但是画出的效果无法和Visio(Windows)或者OmniGraffle(Mac)相提并论。TIKZ倒是可以生成比较好看的图,但要编辑器来太麻烦了……

首个纯技术博客开张

RT,我的首个纯技术博客开张,在这上边讨论所有我喜欢的技术和研究~~