blog.Ring.idv.tw

Python

淺談Tuple

Tuple.在Python程式語言中是一個immutable data structure,也可以將它當做是immutable list,也由於它是不可變的,所以它沒有像list擁有的一些append、remove等函式可供使用,那這樣的話為何還需要它呢?大致上有下述三點:

1. 它可以讓程式更具安全性,這裡的安全性指的是它具備不被更改的可能

2. 由於它是immutable,所以也可以用來當作dictionary的key來使用。

3. 和list相較之下,Tuple在建構時的速度上較快

下述來看一些實例:

>>> def a():
...     x = [1,2,3]
... 
>>> def b():
...     x = (1,2,3)
... 
>>> import dis
>>> dis.dis(a)
  2           0 LOAD_CONST               1 (1)
              3 LOAD_CONST               2 (2)
              6 LOAD_CONST               3 (3)
              9 BUILD_LIST               3
             12 STORE_FAST               0 (x)
             15 LOAD_CONST               0 (None)
             18 RETURN_VALUE        
>>> dis.dis(b)
  2           0 LOAD_CONST               4 ((1, 2, 3))
              3 STORE_FAST               0 (x)
              6 LOAD_CONST               0 (None)
              9 RETURN_VALUE        

從上述這兩個bytecode instructions來看,在建構Tuple所需要的指令較少,也意謂著在建構時的速度較快,實證如下:

python -m timeit "x=(1,2,3,4,5,6,7,8,9,10)"
10000000 loops, best of 3: 0.0261 usec per loop
python -m timeit "x=[1,2,3,4,5,6,7,8,9,10]"
10000000 loops, best of 3: 0.177 usec per loop

透過Tuple大約只耗費了「0.0261 usec」,至於List則需要「0.177 usec」左右~ 但如果比較兩者存取的速度上來看,List會顯得較有效率上的優勢。

python -m timeit -s "x=(1,2,3,4,5,6,7,8,9,10)" "y=x[3]"
10000000 loops, best of 3: 0.0649 usec per loop
python -m timeit -s "x=[1,2,3,4,5,6,7,8,9,10]" "y=x[3]"
10000000 loops, best of 3: 0.0584 usec per loop

相關資源

Are tuples more efficient than lists in Python?

32.12. dis — Disassembler for Python bytecode

2009-08-23 17:11:13 | Add Comment

標籤雲(Tag Cloud)

Tag Cloud(或word cloud).它屬於視覺化介面的一種呈現方式~ 基本上是透過字母的排列順序和次數權重來決定字型大小的呈現,根據wikipedia的記載~ Tag Cloud最初是由Flickr率先開始使用,至於這個詞是由誰提出來的.. 筆者尚未找到有力的參考文獻~

另外Tag Cloud - Wiki也提供了「Computation of the tag size」公式計算,如下所示:

套用此公式的結果:

從上圖的結果可以發現,上述公式對於權重和字型大小之間的運算結果,會導致字型範圍「1px」至「20px」的情形發生,但基本上當字型大小小於「10px」就不容易閱讀和點選,所以筆者修改了此公式,希望它能自行定義Tag Cloud的字型大小範圍「10px」至「20px」,如下圖所示:

如此便能依照權重比例和字型大小形成相互的對應:

index.py

#! /usr/bin/python
from mod_python import psp

def index(req):
        param = {}
        req.content_type = 'text/html'
        tags = [('aggregators',2),('blogs',3),('wikis',4),('usability',5),('widgets',6),('ajax',7),('social',10),('Folksonomy',15)]
        tags.sort()
        param['Tags'] = tags

        tmpl = psp.PSP(req,'index.tmpl')
        tmpl.run(param)

index.tmpl

<html>
<head>
<title>Tag Cloud</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style type="text/css" media="all">
.tagcloud
{
        width: 200px;
        height: 100px;
}
</style>
</head>
<body>
<div class="tagcloud">
<%
Clist = [_t[1] for _t in Tags]
Tmax = max(Clist)
Tmin = min(Clist)
Fmax = 20
T = Tmax - Tmin

for _t in Tags:
        if _t[1] > Tmin:
                si = Fmax * (_t[1] - Tmin) / T 
        else:
                si = 1
        
%>
<span style='font-size: <%=si%>px'><a href="#"><%=_t[0]%></a></span> 
<%
# end for
%>
</div>
<div class="tagcloud">
<%
Fmin = 10

for _t in Tags:
        if _t[1] > Tmin:
                si = (Fmax - Fmin) * (_t[1] - Tmin) / T + Fmin
        else:
                si = Fmin
        
%>
<span style='font-size: <%=si%>px'><a href="#"><%=_t[0]%></a></span> 
<%
# end for
%>
</div>
</body>
</html>

2009-08-12 01:02:07 | Add Comment

Universal Text Box - 通用輸入框

Laconica - The Open Microblogging Tool.是一套免費且開放原始碼(PHP)的微型部落格平臺,可以用在一個社群或群組的短訊(140 character)溝通平臺,類似於當下熱門的TwitterPlurk

如果您是Twitter的愛用者,對於「@」符號應該不會太陌生,下述是從Laconica的原始碼抓出它的Regular Expression來看:

import re
msg = "@account This is a test."
p = r'(?:^|\s)@([a-z0-9]{1,64})'
m = re.findall(p,msg)  
for i in m:
    print i

從這個簡單的小程式來看,重點在於「(?:^|\s)@([a-z0-9]{1,64})」這一行Regular Expression,它處理的方式是在「@」之後的「帳號名稱」只能是小寫的字母和數字所組成,且範圍限制在1到64個字元之間,而在「@」之前的處理方式則是必須是訊息的起始位置或是空白字元,不過因為它是用「(?:^|\s)」括弧涵蓋起來,所以加上「?:」來排除這個Group,如此就是一個類似處理Twitter訊息輸入欄的Regular Expression

下述這個範例就是一個簡單的利用「#」符號來擴展成標記Tag的方法:

import re
msg = "Today is a sunny day. #weather #life"
p = r'(?:^|\s)#([A-Za-z0-9_\-\.]{1,64})'
m = re.findall(p,msg)  
for i in m:
    print i

參考資源

8.2. re — Regular expression operations

How @replies work on Twitter (and how they might)

2009-05-12 16:14:57 | Add Comment

N-gram.一個語言中立的斷詞方法

N-gram」.常被用於自然語言處理的領域之中~ 尤其是用來處理「CJK」的斷詞~

假設我們從詞庫的方式來看~ 如果有一個中文句子為:「研究生活動中心」,用詞庫來斷詞的話~ 可能的結果會是「研究」、「生活」、「動」、「中心」,或者「研究生」、「活動」和「中心」,當然這完全看詞庫斷詞是如何設計的~ 不過這還有許多洐生性的問題~ 例如:CKIP只針對Big5編碼的文字,或是未知詞的處理等等~

所以「N-gram」針對「CJK」能保有完善的斷詞方式~ 如果以上述的例子而言,用bigram斷詞的結果則為:「研究」、「究生」、「生活」、「活動」、「動中」和「中心」

而「N-gram」就取決於「N」的大小~ unigram(n=1)、bigram(n=2)、trigram(n=3) 以此類推~

下述是筆者簡單寫的一個小程式:

def ngram(n,sentence):
	s = sentence.split()
	if n == 1:
		return s
	
	slen = len(s)
	if n > slen:
		raise Exception, "N > %s" % slen
	
	nlist = []
	for idx in range(n-1,slen):
		s1 = []
		for i in range(0,n):
			s1.insert(0,s[idx-i])
		
		delimiter = " "
		str = delimiter.join(s1)
		nlist.append(str.strip())
	
	return nlist
	
print ngram(2,"the cat is on the mat , while a dog is on the chair .")

Bigram的結果:

['the cat', 'cat is', 'is on', 'on the', 'the mat', 'mat ,', ', while', 'while a', 'a dog', 'dog is', 'is on', 'on the', 'the chair', 'chair .']

Trigram的結果:

['the cat is', 'cat is on', 'is on the', 'on the mat', 'the mat ,', 'mat , while', ', while a', 'while a dog', 'a dog is', 'dog is on', 'is on the', 'on the chair', 'the chair .']

以此類推~

2008-10-03 01:38:11 | Comments (3)

Python Server Pages - Fruit Suggest

今天處理了一台伺服器~ 整個給它重灌Debian 4.0r4~ 因為這台伺服器先前被SSH-Attack~ 所以連IP都被封鎖住~

所以千萬別認為裝了「SSH」就絕對安全~ 因為總是有「無聊」的人會利用工具來做「暴力字典攻擊法」想辦法入侵... 所以防火牆的設定是不可少的~ 真搞不懂為什麼有人那麼「無聊」..= ="(我時間都不夠用了~)

好了~ 這不是重點~ 這篇的重點在於測試一個「Python Web Application」~ 我給它的主題就叫做「Fruit Suggest」~ 從名稱來看就知道和「Google Suggest」脫離不了關係~

是的~ 這個範例會結合「Python Server Pages」、「SQLite3」、「YUI Ajax」、「Google Suggest」和「PSP Template」,並且在「Debian Linux」的環境下執行~

我想~ 用一個最實際的簡單案例就是最好的驗證!!

不過~ 一開始還遇到許多問題~ 由於「Debian 4.0r4」預設是安裝「Python 2.4.4」版本~ 但是~ 我想用最新的「Python2.5」來執行這樣的環境~ 畢竟它有整合了「SQLite」~

所以要處理解決「Python2.5」的環境~ 筆者採用自行編譯「mod_python」的方式來處理~ 所以捨棄apt安裝「libapache2-mod-python」的方式~

如果你也需要這樣的解決方案~ 請參考「Jason R Briggs · mod_python and python2.5」的說明~

Fruit Suggest

.htaccess

SetHandler mod_python
PythonHandler mod_python.publisher
PythonDebug On

<Files ~ "\.(gif|html|jpg|png|js|css)$">
   SetHandler default-handler
</Files>

index.html

<html>
<head>
<title>Fruit Suggest</title>
<script src="http://yui.yahooapis.com/2.5.2/build/yahoo/yahoo-min.js"></script>
<script src="http://yui.yahooapis.com/2.5.2/build/event/event-min.js"></script>
<script src="http://yui.yahooapis.com/2.5.2/build/connection/connection-min.js"></script>
<style type="text/css" media="screen">
			body {
				font: 11px arial;
			}
			.suggest_link {
				background-color: #FFFFFF;
				padding: 2px 6px 2px 6px;
			}
			.suggest_link_over {
				background-color: #3366CC;
				padding: 2px 6px 2px 6px;
			}
			#search_suggest {
				position: absolute; 
				background-color: #FFFFFF; 
				text-align: left; 
				border: 1px solid #000000;			
			}		
</style>
<script language="JavaScript" type="text/javascript" src="ajax_search.js"></script>
</head>
<body>
		<div style="width: 500px;">
		<h3>Fruit Suggest</h3>
			<form id="frmSearch">
				<input type="text" id="txtSearch" name="txtSearch" alt="Search Criteria" onkeyup="searchSuggest();" autocomplete="off" />
				<input type="submit" id="cmdSearch" name="cmdSearch" value="Search" alt="Run Search" /><br />
				<div id="search_suggest">
				</div>
			</form>
		</div>
</body>
</html>

ajax_search.js

function searchSuggest()
{
	var callback = {
		success: function(o)
		{
			var ss = document.getElementById('search_suggest')
			ss.innerHTML = '';
			var str = o.responseText.split("\n");
		
			for(i=0; i < str.length - 1; i++)
			{
                                if(str[i] != "")
                                {
                                        var suggest = '<div onmouseover="javascript:suggestOver(this);" ';
                                        suggest += 'onmouseout="javascript:suggestOut(this);" ';
                                        suggest += 'onclick="javascript:setSearch(this.innerHTML);" ';
                                        suggest += 'class="suggest_link">' + str[i] + '</div>';
                                        ss.innerHTML += suggest;
                                }

			}
		},
		failure: function(o)
		{
			alert("Ajax failed!");
		}
	}
	var str = escape(document.getElementById('txtSearch').value);
	var transaction = YAHOO.util.Connect.asyncRequest('GET', '/ajax/ajax/index?search=' + str, callback, null);
}

//Mouse over function
function suggestOver(div_value) {
	div_value.className = 'suggest_link_over';
}
//Mouse out function
function suggestOut(div_value) {
	div_value.className = 'suggest_link';
}
//Click function
function setSearch(value) {
	document.getElementById('txtSearch').value = value;
	document.getElementById('search_suggest').innerHTML = '';
}

ajax.py

from mod_python import apache, psp
from cgi import escape
import sqlite3

def index(req):
	req.content_type = 'text/html'
	template = psp.PSP(req, filename='suggest.tmpl')
	_uid = req.form.getfirst('search')
	_uid = escape(_uid)+'%'
	conn = sqlite3.connect('/var/www/ajax/data.dat')
	c = conn.cursor()
	c.execute('select name from fruit where name like :who', {"who": _uid})
	res = c.fetchall()
	template.run({'search':res})

suggest.tmpl

<%
for f in search:
%>
<%=f[0]%>
<%
%>

data.dat (sqlite)

Fruit table的結構如下:

create table fruit(
	id int,
	name varchar
)

insert into fruit values (1,'apple')

Fruit Suggest 範例下載

Fruit Suggest.zip

參考資源

打造屬於你自己的Google Suggest!

2008-10-02 02:55:52 | Comments (2)

Previous Posts
Copyright (C) Ching-Shen Chen. All rights reserved.

::: 搜尋 :::

::: 分類 :::

::: 最新文章 :::

::: 最新回應 :::

::: 訂閱 :::

Atom feed
Atom Comment