Python 的代碼風格由 PEP 8 描述。這個文檔描述了 Python 編程風格的方方面面。在遵守這個文檔的條件下,不同程序員編寫的 Python 代碼可以保持最大程度的相似風格。這樣就易于閱讀,易于在程序員之間交流。
1 變量
常量 : 大寫加下劃線
USER_CONSTANT
對于不會發生改變的全局變量,使用大寫加下劃線。
私有變量 : 小寫和一個前導下劃線
_private_value
Python 中不存在私有變量一說,若是遇到需要保護的變量,使用小寫和一個前導下劃線。但這只是程序員之間的一個約定,用于警告說明這是一個私有變量,外部類不要去訪問它。但實際上,外部類還是可以訪問到這個變量。
內置變量 : 小寫,兩個前導下劃線和兩個后置下劃線
__class__
兩個前導下劃線會導致變量在解釋期間被更名。這是為了避免內置變量和其他變量產生沖突。用戶定義的變量要嚴格避免這種風格。以免導致混亂。
2 函數和方法
總體而言應該使用,小寫和下劃線。但有些比較老的庫使用的是混合大小寫,即首單詞小寫,之后每個單詞第一個字母大寫,其余小寫。但現在,小寫和下劃線已成為規范。
私有方法 : 小寫和一個前導下劃線
def _secrete(self):
print "don't test me."
這里和私有變量一樣,并不是真正的私有訪問權限。同時也應該注意一般函數不要使用兩個前導下劃線(當遇到兩個前導下劃線時,Python 的名稱改編特性將發揮作用)。特殊函數后面會提及。
特殊方法 : 小寫和兩個前導下劃線,兩個后置下劃線
def __add__(self, other):
return int.__add__(other)
這種風格只應用于特殊函數,比如操作符重載等。
函數參數 : 小寫和下劃線,缺省值等號兩邊無空格
def connect(self, user=None):
self._user = user
3 類
類總是使用駝峰格式命名,即所有單詞首字母大寫其余字母小寫。類名應該簡明,精確,并足以從中理解類所完成的工作。常見的一個方法是使用表示其類型或者特性的后綴,例如:
SQLEngine
MimeTypes
對于基類而言,可以使用一個 Base 或者 Abstract 前綴
BaseCookie
AbstractGroup
class UserProfile(object):
def __init__(self, profile):
return self._profile = profile

def profile(self):
return self._profile
4 模塊和包
除特殊模塊 __init__ 之外,模塊名稱都使用不帶下劃線的小寫字母。
若是它們實現一個協議,那么通常使用lib為后綴,例如:
import smtplib
import os
import sys
5 關于參數
5.1 不要用斷言來實現靜態類型檢測
斷言可以用于檢查參數,但不應僅僅是進行靜態類型檢測。 Python 是動態類型語言,靜態類型檢測違背了其設計思想。斷言應該用于避免函數不被毫無意義的調用。
5.2 不要濫用 *args 和 **kwargs
*args 和 **kwargs 參數可能會破壞函數的健壯性。它們使簽名變得模糊,而且代碼常常開始在不應該的地方構建小的參數解析器。
6 其他
6.1 使用 has 或 is 前綴命名布爾元素
is_connect = True
has_member = False
6.2 用復數形式命名序列
members = ['user_1', 'user_2']
6.3 用顯式名稱命名字典
person_address = {'user_1':'10 road WD', 'user_2' : '20 street huafu'}
6.4 避免通用名稱
諸如 list, dict, sequence 或者 element 這樣的名稱應該避免。
6.5 避免現有名稱
諸如 os, sys 這種系統已經存在的名稱應該避免。
7 一些數字
一行列數 : PEP 8 規定為 79 列,這有些苛刻了。根據自己的情況,比如不要超過滿屏時編輯器的顯示列數。這樣就可以在不動水平游標的情況下,方便的查看代碼。
一個函數 : 不要超過 30 行代碼, 即可顯示在一個屏幕類,可以不使用垂直游標即可看到整個函數。
一個類 : 不要超過 200 行代碼,不要有超過 10 個方法。
一個模塊 不要超過 500 行。
8 驗證腳本
可以安裝一個 pep8 腳本用于驗證你的代碼風格是否符合 PEP8。
>>easy_install pep8
>>pep8 -r --ignoire E501 Test.py
這個命令行的意思是,重復打出錯誤,并且忽略 501 錯誤(代碼超過 79 行)。
posted @
2011-02-02 00:45 lincode 閱讀(9324) |
評論 (0) |
編輯 收藏
Emacs 不僅僅是一個文本編輯器,它還可用于文件管理。使用 Emacs 作為文件管理工具的話,也解決了跨平臺問題,這樣在不同平臺下,你都可以使用一套工具來管理文件。
1 基本命令
Ctrl + x d : 打開文件管理視圖,在文件管理視圖中支持的操作如下表:
鍵值 |
效果 |
Enter |
打開文件 |
a |
打開文件并關閉文件管理視圖 |
o |
打開文件,但是在一個新建視圖中打開 |
q |
關閉文件管理視圖 |
C(大寫) |
復制文件 |
R(大寫) |
重命名文件 |
D(大寫) |
刪除文件 |
2 基于文件集合的命令
這主要是使一條命令作用于幾個文件。方法是標記你要操作的文件。
基本命令為 m
鍵值 |
效果 |
m |
標記文件 |
u |
去掉標記 |
U |
標記所有文件 |
t |
反向所以文件 |
% m |
基于正則表達式,標記文件 |
3 其他相關命令
在文件管理視圖中還可以做到:
鍵值 |
效果 |
g |
刷新文件夾 |
^ |
返回上級目錄 |
+ |
創建一個文件夾 |
Z |
壓縮或解壓文件 |
posted @
2011-02-01 18:14 lincode 閱讀(1071) |
評論 (0) |
編輯 收藏
我使用的是 goddady 的 VPS。家里使用 mac 。所以直接在 terminal 中使用 ssh 連接服務器即可。
> ssh 189.129.1.12 -l username
敲入密碼,進入服務器。
> su
敲入密碼,進入根用戶。
> cd /etc/ngnix/
進入 ngnix 配置文件目錄,進入 conf.d 目錄
> vim ghs.conf
建立一個 配置文件
一個范例:
upstream ghs {
ip_hash;
server ghs.google.com;
server 72.14.203.121;
server 72.14.207.121;
server 74.125.43.121;
server 74.125.47.121;
server 74.125.53.121;
server 74.125.77.121;
server 74.125.93.121;
server 74.125.95.121;
server 74.125.113.121;
server 216.239.32.21;
server 216.239.34.21;
server 216.239.36.21;
server 216.239.38.21;
}
server {
listen 80;
server_name ghs.myhosts.com www.test.com;
access_log /data/logs/ghs_proxyaccess.log;
location / {
proxy_redirect off;
proxy_set_header Host $host;
proxy_pass http://ghs;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_redirect false;
}
}
>/etc/init.d/ngnix start
啟動 nginx
在本機的瀏覽器中敲入反向代理 server 的 ip,能看到 ngnix 的藍色的界面,這驗證了 ngnix 啟動正常
> ping ghs.myhosts.com
應該指向反向代理 server 的 ip
首先將你的域名例如,www.tests.com 綁定到 google app engine 的你的目標 application 上
然后,在你的域名服務提供商那里,添加一個 www.tests.com 指向 ghs.myhosts.com 的 CNAME 即可。
posted @
2010-12-15 07:12 lincode 閱讀(503) |
評論 (0) |
編輯 收藏
transient:
java有個特點就是序列化,簡單地來說就是可以將這個類存儲在物理空間(當然還是以文件的形式存在),那么當你從本地還原這個文件時,你可以將它轉換為它本身。這可以極大地方便網絡上的一些操作,但同時,因為涉及到安全問題,所以并不希望把類里面所有的東西都能存儲(因為那樣,別人可以通過序列化知道類里面的內容),那么我們就可以用上transient這個關鍵字,它的意思是臨時的,即不會隨類一起序列化到本地,所以當還原后,這個關鍵字定義的變量也就不再存在。
volatile:
Volatile 修飾的成員變量在每次被線程訪問時,都強迫從共享內存中重讀該成員變量的值。而且,當成員變量發生變化時,強迫線程將變化值回寫到共享內存。這樣在任何時刻,兩個不同的線程總是看到某個成員變量的同一個值。
Java 語言規范中指出:為了獲得最佳速度,允許線程保存共享成員變量的私有拷貝,而且只當線程進入或者離開同步代碼塊時才與共享成員變量的原始值對比。
這樣當多個線程同時與某個對象交互時,就必須要注意到要讓線程及時的得到共享成員變量的變化。
而volatile關鍵字就是提示VM:對于這個成員變量不能保存它的私有拷貝,而應直接與共享成員變量交互。
使用建議:在兩個或者更多的線程訪問的成員變量上使用volatile。當要訪問的變量已在synchronized代碼塊中,或者為常量時,不必使用。
由于使用volatile屏蔽掉了VM中必要的代碼優化,所以在效率上比較低,因此一定在必要時才使用此關鍵字。
posted @
2010-06-14 23:03 lincode 閱讀(229) |
評論 (0) |
編輯 收藏
一 基本概念
單例模式是一種為類 提供唯一實例的設計模式。單例模式的目的是為了控制對象的創建,它可以限制創建的數目為一,但在情況改變的時候,也允許靈活地創建更多的對象。因為只有一個實例,所以也只有一套實例的類變量的拷貝,這很像 static 變量。
在 JAVA 中,單例模式不應該被當作一種實現全局變量的方法。更多的,如同工廠模式,單例模式允許你通過 確認某些先決條件是否滿足 或者 以 lazily 方式按需創建的方式 來封裝和控制創建過程。
二 編程實現
1 饑餓模式 Eager Singleton

public class MySingleton {
private static MySingleton fInstance = new MySingleton();

private MySingleton(){
// Construct object
}


public static MySingleton getInstance(){
reutnr fInstance;
}

}
2 懶漢模式 Lazy Singleton

public class MySingleton {
private static MySingleton fInstance;

private MySingleton(){
// construct object
}

public static synchronized MySingleton getInstance(){

if (fInstance == null){
fInstance = new MySingleton();
}
return fInstance;
}

}
由于只有一個私有構造器,所以單例類是無法被集成的。基于這一點,單例模式并不是一個面向對象模式,僅僅是一個基于對象的模式。
3 饑餓模式基本沒有問題,懶漢模式則容易出現一些錯誤的編程方法
1)
// error, no synchronization on method

public static MySingleton getInstance() {

if (fInstance==null) {
fInstance = new MySingleton();
}

return fInstance;
}
2)
// Also an error, synchronization does not prevent
// two calls of constructor.

public static MySingleton getInstance() {

if (fInstance==null) {

synchronized (MySingleton.class) {
fInstance = new MySingleton();
}
}
return fInstance;
}
3) Double-checked locking 不要使用

public static MySingleton getInstance(){

if (fInstance == null ){

synchronized (MySingleton.class) {

if(fInstance == null){
fInstance = new MySingleton();
}
}
}
}
為了避免每次調用 getInstance方法是抓取同步鎖的消耗,有人發明了 Double-checked locking 。但不要使用,因為這樣的代碼將無法在編譯器優化和多處理器共享內存的情況下工作。若想詳細了解,附錄中有對此做詳細描述的鏈接。
三 總結
1 單例模式不應被濫用,比如不能為了得到一個全局變量而創建單例,單例是用于控制對象的創建過程的。只有真正的目的是控制對象創建的過程或數量時,才能考慮使用單例。在大部分情況下,單例模式是有代替方案的。比如經典的數據庫連接類被以單例實現,其實可以以對象池模式實現。
2 使用單例模式,盡量使用饑餓模式 ,只有你能預測這個類一定會被創建,那么就可以使用饑餓模式。如果,一定需要推遲對象的創建時間。那么不要使用 Double-checked locking 之類的方法的來提高效率,這將得不償失。
[1] DoubleCheckedLocking
http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html
posted @
2010-04-30 21:04 lincode 閱讀(218) |
評論 (0) |
編輯 收藏
一 基本概念
這篇文章比較清楚地講述了字符集和編碼的基本概念
http://www.regexlab.com/zh/encoding.htm
摘抄:
各個國家和地區所制定的不同 ANSI 編碼標準中,都只規定了各自語言所需的“字符”。比如:漢字標準(GB2312)中沒有規定韓國語字符怎樣存儲。這些 ANSI 編碼標準所規定的內容包含兩層含義:
- 使用哪些字符。也就是說哪些漢字,字母和符號會被收入標準中。所包含“字符”的集合就叫做“字符集”。
- 規定每個“字符”分別用一個字節還是多個字節存儲,用哪些字節來存儲,這個規定就叫做“編碼”。
各個國家和地區在制定編碼標準的時候,“字符的集合”和“編碼”一般都是同時制定的。因此,平常我們所說的“字符集”,比如:GB2312, GBK, JIS 等,除了有“字符的集合”這層含義外,同時也包含了“編碼”的含義。
“UNICODE 字符集”包含了各種語言中使用到的所有“字符”。用來給 UNICODE 字符集編碼的標準有很多種,比如:UTF-8, UTF-7, UTF-16, UnicodeLittle, UnicodeBig 等。
二 eclipse 中對于編碼方式的設置
1 源文件的編碼設置
preference -> general -> Content Types
右邊選擇文件類型,右下更新 缺省編碼方式
2 控制臺的編碼設置
Run -> Run configuration( 或 Debug configuration)
右邊選項卡中 common, 一般為最后一項
在 console encoding 的 other 中選取需要的 編碼方式
三 java 中的 編碼轉換
byte[] bytes = oldStr.getBytes(); //默認編碼方式下的字節數組
String newStr = new String( bytes, "UTF-8" ); //轉換成 UTF-8 編碼下的字符串
posted @
2010-04-29 23:31 lincode 閱讀(263) |
評論 (0) |
編輯 收藏
Java 中函數參數傳遞和函數返回值都是以值方式傳遞的。當然,對于對象,我們也可以說是引用的方式傳遞,其實傳遞也是值,只不過是引用值。引用是一個對象的別名,對于引用的修改就是對于對象本身的修改。
為了便于理解還是可以說成是兩種類型,原始類型以值方式傳遞,對象以引用方式傳遞。
向函數里傳遞參數,已經有很多java教程講解了。這里主要記錄一個 函數返回值的問題。在返回一個對象時,是返回值本身的應用,還是拷貝這個值,再傳拷貝的引用呢。這是需要考慮清楚的。
這個問題,是我在 不同手機上調試 J2ME 程序時遇到的。
具體如下,這是一個關于時間的工具類。我發覺
Calendar 的 getTime() 在有的機器下 如 Nokia,返回的
Calendar 當前時間的一個拷貝的引用,而 SAMSUNG 則直接返回
Calendar 的當前時間的引用。這導致,我在想得到一個時間所在那一的起始時間和結束時間時,總是得到相同的值,即后一次調用的值。按照,比較正常的理解,這里應該返回拷貝的引用比較正確,就是說 SAMSUNG 的 JVM 實現有些問題。面對這種情況,我只能先用 Date 類 返回 一個 long 值,再用 long 值構造一個新日期,即日歷當前日期的拷貝,返回這個拷貝。
修改函數中的最后一行為
return new Date(fCalendar.getTime().getTime());
private static Date fCalendar = Calendar.getInstance();
/**
* Get the beginning of a day
* @param date <description>
* @return <description>
*/
public static Date getBeginOfDay( final Date pDate ) {
fCalendar.setTime( pDate );
try{
fCalendar.set( Calendar.HOUR_OF_DAY, 0 );
fCalendar.set( Calendar.MINUTE, 0 );
fCalendar.set( Calendar.SECOND, 0 );
}catch(ArrayIndexOutOfBoundsException ex){
ex.printStackTrace();
}
return fCalendar.getTime();
}
/**
* Get the end of a day
* @param date <description>
* @return <description>
*/
public static Date getEndOfDay( final Date pDate ){
fCalendar.setTime( pDate );
try{
fCalendar.set( Calendar.HOUR_OF_DAY, 23 );
fCalendar.set( Calendar.MINUTE, 59 );
fCalendar.set( Calendar.SECOND, 59 );
}catch(ArrayIndexOutOfBoundsException ex){
ex.printStackTrace();
}
return fCalendar.getTime();
}
posted @
2010-02-24 21:36 lincode 閱讀(2327) |
評論 (0) |
編輯 收藏
摘要: 原則很簡單: 不要使用 字符串鏈接操作符來合并多個字符串,除非性能無關緊要。相反,應該使用StringBuffer的append方法,或者采用其它的方案,比如使用字符數組,或者每次只處理一個字符串,而不是將它們組合起來。
閱讀全文
posted @
2010-02-10 18:46 lincode 閱讀(425) |
評論 (0) |
編輯 收藏
J2me 中使用 Log, 可以使用搜索引擎搜索下載 log4j2me.
使用方法和 j2se 中有一些區別,下面是在 log4j2me 包中的一個例子
package log4j2me.test;
import org.apache.log4j.*;
import org.apache.log4j.helpers.LogLog;
/**
Very simple log4j usage example.
@author Ceki Gülcü, Witmate
*/
// Modifiers: Witmate [Nov,2004: Modified for log4j2me]
public class Hello {
static Category log = Category.getInstance(Hello.class);
static Category log1 = Category.getInstance("Hello");
public static void main(String argv[]) {
Category root = Category.getRoot();
root.setPriority( Priority.DEBUG );
Layout layout = new PatternLayout("%p [%t] %c - %m%n");
try {
root.addAppender(new FileAppender(layout, System.out));
} catch(Exception e) {
LogLog.warn("Could not open file appender.");
}
log.debug("Hello world.");
log.info("What a beatiful day.");
log1.debug("Hello world.");
log1.info("What a beatiful day.");
}
}
posted @
2010-01-28 01:13 lincode 閱讀(371) |
評論 (0) |
編輯 收藏
摘要: Django 的 template 有繼承功能。這兩天遇到一個問題,
僅僅包含 {% extends "base.html" %} 一條語句的子 html 文件在瀏覽器中和 base.html 的渲染結果不一樣。
搞了兩天才找出問題的原因。是子文件選擇了 UTF-8 格式。
所有的文件應該都選擇 UTF-8 without BOM 格式。這樣就得到一致的結果了。
閱讀全文
posted @
2009-12-31 06:37 lincode 閱讀(229) |
評論 (0) |
編輯 收藏