2010-02-17 58 views
2

我正在使用Python(和PyGTK)的Gedit插件,我真的沒有'與Python合作太多,所以我不知道如果我正在編寫Pythonic代碼。改進我的Python代碼的空間?

我自己的所有代碼都包含在__init__.py中。還有一些其他文件,但它們來自我正在關注的外部庫。我__init__.py如下:

# 
# @file __init__.py 
# Does the heavy lifting behind connecting Zen Coding to Gedit. 
# 

import gedit, gobject, string, gtk, re, zen_core 

class ZenCodingPlugin(gedit.Plugin): 
    """ 
    A Gedit plugin to implement Zen Coding's HTML and CSS shorthand expander. 

    This file adds the menu items and keyboard shortcuts to the UI and connects 
    those items with the good stuff (i.e., the code expansion). 
    """ 

    def __init__(self): 
     gedit.Plugin.__init__(self) 

    def activate(self, window): 
     "Gedit callback: install the expansion feature into the UI" 

     ui_manager = window.get_ui_manager() 
     action_group = gtk.ActionGroup("GeditZenCodingPluginActions") 

     # Create the GTK action to be used to connect the key combo 
     # to the Zen Coding expansion (i.e., the good stuff). 
     complete_action = gtk.Action(name="ZenCodingAction", 
            label="Expand Zen code...", 
            tooltip="Expand Zen Code in document to raw HTML", 
            stock_id=gtk.STOCK_GO_FORWARD) 

     # Connect the newly created action with key combo 
     complete_action.connect("activate", 
           lambda a: self.expand_zencode(window)) 
     action_group.add_action_with_accel(complete_action, 
              "<Ctrl><Shift>E") 

     ui_manager.insert_action_group(action_group, 0) 

     # @TODO: Figure out what these lines do 
     ui_merge_id = ui_manager.new_merge_id() 
     ui_manager.add_ui(ui_merge_id, 
          "/MenuBar/EditMenu/EditOps_5", 
          "ZenCoding", 
          "ZenCodingAction", 
          gtk.UI_MANAGER_MENUITEM, False) 
     ui_manager.__ui_data__ = (action_group, ui_merge_id) 

    def deactivate(self, window): 
     "Gedit callback: get rid of the expansion feature" 

     ui_manager = window.get_ui_manager() 
     (action_group, ui_merge_id) = ui_manager.__ui_data__ 

     # Remove the UI data, action group, and UI itself from Gedit 
     del ui_manager.__ui_data__ 
     ui_manager.remove_action_group(action_group) 
     ui_manager.remove_ui(ui_merge_id) 


    def expand_zencode(self, window): 
     "The action which handles the code expansion itself." 

     view = window.get_active_view() 
     buffer = view.get_buffer() 

     # Grab the current cursor position. 
     cursor_iter = buffer.get_iter_at_mark(buffer.get_insert()) 

     # Grab the first character in the line. 
     line_iter = cursor_iter.copy() 
     line_iter.set_line_offset(0) 

     # Grab the text from the start of the line to the cursor. 
     line = buffer.get_text(line_iter, cursor_iter) 

     # Find the last space in the line and remove it, setting a variable 
     # 'before' to the current line. 
     words = line.split(" ") 
     before = words[-1].lstrip() 
     if not before: 
      return 

     # Get the language of the current document. Second line prevents an error 
     # if first line returns None. 
     lang = window.get_active_document().get_language() 
     lang = lang and lang.get_name() 

     # Using the 'before' variable, convert it from Zen Code 
     # to expanded code. If there isn't anything, just return. 
     if lang == 'CSS': 
      after = zen_core.expand_abbreviation(before,'css','xhtml') 
     else: 
      after = zen_core.expand_abbreviation(before,'html','xhtml') 
     if not after: 
      return 

     # Grab the line's indentation and store it. 
     indent = re.match(r"\s*", line).group() 

     # Automatically indent the string and replace \t (tab) with the 
     # correct number of spaces. 
     after = zen_core.pad_string(after,indent) 
     if view.get_insert_spaces_instead_of_tabs(): 
      tabsize = view.get_tab_width() 
      spaces = " " * tabsize 
      after = after.replace("\t",spaces) 

     # We are currently lame and do not know how to do placeholders. 
     # So remove all | characters from after. 
     after = after.replace("|", "") 

     # Delete the last word in the line (i.e., the 'before' text, aka the 
     # Zen un-expanded code), so that we can replace it. 
     word_iter = cursor_iter.copy() 
     position_in_line = cursor_iter.get_line_index() - len(before) 
     word_iter.set_line_index(position_in_line) 
     buffer.delete(word_iter, cursor_iter) 

     # Insert the new expanded text. 
     buffer.insert_at_cursor(after) 

我只是問,因爲上面並沒有顯得很面向對象和它種在我看來是一個壞主意,把這麼多的邏輯__init__.py,但作爲新的這個,我不確定。

是否有改進的餘地?如果是這樣,怎麼樣? (我試圖迴避什麼插件實際上做的,因爲我正在尋找更多的代碼風格審查比對數審查,但如果你需要看到來自外部庫的代碼,整個插件爲here

回答

3

我從來沒有做過的gedit插件,所以我不能評論Ø n中的__init__.py問題,但一般注意事項:

  • 並沒有叫父母帶冗餘沒有新ARGS __init__ - 你就不能拿出那些2線?

  • 您創建了比我更多的局部變量。我不得不四處查看價值來自哪裏,或者是否再次使用價值。例如:

    tabsize = view.get_tab_width() 
    spaces = " " * tabsize 
    after = after.replace("\t",spaces) 
    

    可能是:

    after = after.replace("\t", " " * view.get_tab_width()) 
    
  • 有點冗餘這裏:

    if lang == 'CSS': 
        after = zen_core.expand_abbreviation(before,'css','xhtml') 
    else: 
        after = zen_core.expand_abbreviation(before,'html','xhtml') 
    

    比較:

    after = zen_core.expand_abbreviation(before, 'css' if lang == 'CSS' else 'html', 'xhtml') 
    

除此之外,它看起來像一個相當不錯的Python代碼,我的眼睛。

+0

偉大的評論,非常感謝提示。 – 2010-02-17 22:34:05

2

也許你想要將它移動到一個名爲zen_plugin.py

然後文件讓你__init__.py

from zen_plugin import ZenCodingPlugin 
+0

好了,所以這是一個不好的做法,把這個多的東西在初始化呢? – 2010-02-17 22:23:13

+0

沒什麼不好,只是偏好。如果文件名與它的功能相關,它將使代碼更容易瀏覽。也意味着你不會像往常一樣編輯名爲__init__.py的文件,如果你使用了標籤編輯器,這是一個很痛苦的例子。 – 2010-02-17 22:39:34

+3

我同意這個建議。就我個人而言,當包的邏輯大部分位於'__init __。py'中時,我總是感到困惑。 – jathanism 2010-02-17 22:56:23

1

我會嘗試從long expand_zencode()中提取一些函數。例如,像expand_tabs()一樣。這在某種程度上是品味的問題,但每當我看到一個帶有評論指出「景點」的「遊記」時,這是一個強烈的暗示,而不是重構每個帶有doc註釋的函數。 (不一定是一對一;我沒有關於此功能的詳細建議的能量/知識。)此更改自動解決Ken關於跟蹤局部變量的投訴。

順便說一句,你有一個奇怪的tab-expansion定義:將每個製表符改爲製表符空格。我想這是有原因的。

這是不必要的:

def __init__(self): 
    gedit.Plugin.__init__(self) 

before變量的代碼似乎並不符合其評論。 (和.lstrip()是多餘的,不是嗎?)

你有時爭論,有時並不之間的空間; IIRC Python風格指南要求您始終使用空格。 (foo(x, y)而不是foo(x,y)。)

您班的評論說:「此文件添加...」。不應該是「這個插件增加了...」嗎?

考慮提出這樣的事情上,而不是http://refactormycode.com/

+0

謝謝,感謝您的意見。 – 2010-02-18 13:48:31

-3

它的GUI代碼,並始終是冗長,我最好的建議是:它的工作原理?好。下一個任務!

1

如果你只有一個文件,然後你的目錄結構可能看起來像

pluginname 
`- __init__.py 

在這種情況下,你可以扁平化您的項目

pluginname.py 

如果以後需要在其他模塊的包你可以去

pluginname 
+- __init__.py 
`- plugin.py 

其中plugin.py有這個在它和__init__.py類把

from pluginname.plugin import ZenCodingPlugin 

以前使用from pluginname import ZenCodingPluginimport pluginname; pluginname.ZenCodingPlugin仍然會以這種方式工作什麼。