溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶(hù)服務(wù)條款》

PyCharm插件開(kāi)發(fā)實(shí)踐中PyGetter And Setter的介紹及用法是怎樣的

發(fā)布時(shí)間:2021-10-08 09:55:43 來(lái)源:億速云 閱讀:284 作者:柒染 欄目:開(kāi)發(fā)技術(shù)

這期內(nèi)容當(dāng)中小編將會(huì)給大家?guī)?lái)有關(guān)PyCharm插件開(kāi)發(fā)實(shí)踐中PyGetter And Setter的介紹及用法是怎樣的,文章內(nèi)容豐富且以專(zhuān)業(yè)的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。

背景需求

在面向?qū)ο蟮脑O(shè)計(jì)中,典型如Java語(yǔ)言,為了控制對(duì)象屬性的修改入口,我們常用的做法是把屬性設(shè)置為private,然后通過(guò)getter和setter方法訪問(wèn)、修改該屬性。

但是在Python語(yǔ)言中,并沒(méi)有Java的訪問(wèn)控制符,對(duì)象的屬性可以直接訪問(wèn)、修改。

為了良好的設(shè)計(jì)規(guī)范,我們可以規(guī)定,在Python類(lèi)中,所有的對(duì)象屬性均以下劃線"_"前綴開(kāi)頭,同時(shí)編寫(xiě)該屬性的getter和setter方法,在其他地方引用的時(shí)候,禁止出現(xiàn)直接引用。

在IDEA等IDE中,可以對(duì)Java的對(duì)象屬性直接生成getter和setter方法,但是針對(duì)Python沒(méi)有這樣的功能。大量的getter和setter方法,很耗費(fèi)精力,所以需要一款插件來(lái)輔助自動(dòng)化生成Python對(duì)象屬性的getter和setter方法。

搭建環(huán)境

編寫(xiě)IDEA系列的插件開(kāi)發(fā)環(huán)境,可以看我之前的一篇文章:《IntelliJ IDEA/Android Studio插件開(kāi)發(fā)指南》

官方開(kāi)發(fā)文檔:IntelliJ Platform SDK

過(guò)程拆解

Python文件例子:

class Test(object):
     def __init__(self):
         self._var1 = ""
         self._var2 = 0

明確了需求、輸入(python對(duì)象屬性定義代碼)、輸出(PyCharm插件自動(dòng)生成getter和setter)后,我們針對(duì)這個(gè)插件的流程進(jìn)行拆解:

  1. 首先,用戶(hù)選中了對(duì)應(yīng)行的文本內(nèi)容,插件獲取到該內(nèi)容文本

  2. 在內(nèi)容文本中過(guò)濾出變量,在本例中,就是過(guò)濾出_var1, _var2

  3. 拼裝變量的getter和setter方法

  4. 計(jì)算出要插入的位置

  5. 回寫(xiě)到編輯器中

1. 獲取文本

在PyCharm插件中,Editor對(duì)象是編輯器的總覽,其中包含很多Model,比如

CaretModel caretModel=editor.getCaretModel(); // 用于描述插入光標(biāo)
SelectionModel selectionModel = editor.getSelectionModel();  // 用于描述選中的文本
FoldingModel foldingModel = editor.getFoldingModel();  // 用于描述代碼折疊區(qū)域
IndentsModel indentModel = editor.getIndentsModel();  // 用于描述縮進(jìn)
……

在這里,我們只需要SelectionModel。

// 獲取光標(biāo)選中文本段對(duì)象
        SelectionModel selectionModel = editor.getSelectionModel();
        // 拿到選中部分字符串
        String selectedText = selectionModel.getSelectedText();

2. 正則匹配

拿到選中文本后,有可能選擇了多行,里面包含多個(gè)變量,所以我們需要獲取到變量列表。
觀察到所有的變量都是self.abc=xxx的模式,我們可以考慮用正則匹配把其中的abc獲取到。
Java中負(fù)責(zé)正則匹配并獲取匹配字符串的類(lèi)是PatternMatcher。

  /**
     * 獲取選中文本中所有的self.value中的value    <br>
     * e.g. self.value = xxx,or self._value = xxx,     <br>
     * 可以獲取到其中的value
     *
     * @param selectedText 選中文本
     * @return 變量字符串列表
     */
    public ArrayList<String> getFieldList(String selectedText) {
        ArrayList<String> list = new ArrayList<>();
        // 刪除所有空格
        selectedText = selectedText.replaceAll(" ", "");
        // 正則匹配獲得變量字符串
        String reg = "self.(.*?)=";
        Pattern pattern = Pattern.compile(reg);
        Matcher matcher = pattern.matcher(selectedText);
        while (matcher.find()) {
            list.add(matcher.group(1));
        }
        return list;
    }

3. 拼裝方法

Python中的getter和setter方法都非常簡(jiǎn)單,我們可以先創(chuàng)造一個(gè)模板:

// 定義Getter和Setter的模板
        String getterTemplate = "    def get_word(self):\n        return self.field\n    ";
        String setterTemplate = "    def set_word(self, word):\n        self.field = word\n    ";

之所以存在空格,是為了匹配PyCharm的縮進(jìn),我這里使用的4個(gè)空格做縮進(jìn),如果你使用兩個(gè)空格的話,在這里修改成兩個(gè)空格即可。
在這里不能使用\t,我嘗試了\t,在PyCharm中無(wú)法自動(dòng)轉(zhuǎn)換為4個(gè)空格,會(huì)報(bào)錯(cuò)。

上一步獲取到的變量,有可能不存在下?lián)Q線前綴,也有可能存在1個(gè)或者2個(gè)下劃線前綴,比如var,_var,__var,他們對(duì)應(yīng)的gett和setter如下:

# 假如變量為_(kāi)var
def get_var(self):
    return self._var;

def set_var(self, var):
    self._var = var;

可以看到在self.xxx中需要使用變量,而在get_xxx和setter的參數(shù)中,需要?jiǎng)h除對(duì)應(yīng)的下劃線。所以有:

   ……
        // 對(duì)于 “_value” 類(lèi)型的變量,在set方法參數(shù)中,只需要“value”
        for (String field : fieldList) {
            String tmp = field;
            int i = 0;
            while (tmp.charAt(i) == '_') {
                tmp = tmp.substring(1);
            }
            // 替換掉模板中的變量
            String customGetter = getterTemplate.replaceAll("word", tmp).replaceAll("field", field);
            String customSetter = setterTemplate.replaceAll("word", tmp).replaceAll("field", field);
            stringBuilder.append("\n").append(customGetter).append("\n").append(customSetter);
        }
       ……

4. 計(jì)算位置

首先需要獲取到Document對(duì)象,這是負(fù)責(zé)描述文檔的,里面有很多負(fù)責(zé)文檔的方法,比如在文件中插入字符串,計(jì)算文件行數(shù),計(jì)算文檔長(zhǎng)度,刪除相應(yīng)內(nèi)容等等。

Document document = editor.getDocument();

為了方便簡(jiǎn)單,我們?cè)O(shè)定在選中文本的下一行生成getter和setter。

   // 得到選中字符串的結(jié)束位置
        int endOffset = selectionModel.getSelectionEnd();
        // 得到最大插入字符串(生成的Getter和Setter函數(shù)字符串)的位置
        int maxOffset = document.getTextLength();
        // 計(jì)算選中字符串所在的行號(hào),通過(guò)行號(hào)得到下一行的第一個(gè)字符的起始偏移量
        int curLineNumber = document.getLineNumber(endOffset);
        int docLineCount = document.getLineCount();
        // 如果目前文件行數(shù)不足以支持選中文本的下一行,也就是選中文本包含最后一行,就插入一個(gè)空行
        if (docLineCount - 1 < curLineNumber + 1) {
            Runnable runnable = () -> document.insertString(maxOffset,"\n");
            WriteCommandAction.runWriteCommandAction(project, runnable);
        }
        int nextLineStartOffset = document.getLineStartOffset(curLineNumber + 1);

5. 回寫(xiě)

將字符串插入文檔中,不能直接使用document.insertString,會(huì)error: Assertion failed: Write access is allowed inside write-action only (see com.intellij.openapi.application.Application.runWriteAction())

需要把這個(gè)任務(wù)放入一個(gè)Runnable中,然后由WriteCommandAction來(lái)調(diào)度。

參考:Write access is allowed inside write-action only

 // 對(duì)文檔進(jìn)行操作部分代碼,需要放入runnable,不然IDEA會(huì)卡住
        Runnable runnable = () -> document.insertString(nextLineStartOffset, genGetterAndGetter(fieldList));

        // 加入任務(wù),由IDE調(diào)度任務(wù)
        WriteCommandAction.runWriteCommandAction(project, runnable);

效果

目前來(lái)看效果還不錯(cuò),關(guān)于安裝方法、使用方法,見(jiàn)github的README。

PyCharm插件開(kāi)發(fā)實(shí)踐中PyGetter And Setter的介紹及用法是怎樣的

資源

github鏈接:https://github.com/mybichu/PyGetterAndSetter

上述就是小編為大家分享的PyCharm插件開(kāi)發(fā)實(shí)踐中PyGetter And Setter的介紹及用法是怎樣的了,如果剛好有類(lèi)似的疑惑,不妨參照上述分析進(jìn)行理解。如果想知道更多相關(guān)知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI