<pre id="vvttv"><mark id="vvttv"><progress id="vvttv"></progress></mark></pre>
    <pre id="vvttv"></pre>

      <p id="vvttv"></p>

          <p id="vvttv"></p>

                <p id="vvttv"></p>

                <pre id="vvttv"><cite id="vvttv"><progress id="vvttv"></progress></cite></pre>

                  <output id="vvttv"><dfn id="vvttv"><th id="vvttv"></th></dfn></output>

                    <p id="vvttv"></p>

                    4.4. 通過 getattr 獲取對象引用

                    你已經知道 Python 函數是對象。你不知道的是,使用 getattr 函數,可以得到一個直到運行時才知道名稱的函數的引用。

                    例 4.10. getattr 介紹

                    >>> li = ["Larry", "Curly"]
                    >>> li.pop                       1
                    <built-in method pop of list object at 010DF884>
                    >>> getattr(li, "pop")           2
                    <built-in method pop of list object at 010DF884>
                    >>> getattr(li, "append")("Moe") 3
                    >>> li
                    ["Larry", "Curly", "Moe"]
                    >>> getattr({}, "clear")         4
                    <built-in method clear of dictionary object at 00F113D4>
                    >>> getattr((), "pop")           5
                    Traceback (innermost last):
                      File "<interactive input>", line 1, in ?
                    AttributeError: 'tuple' object has no attribute 'pop'
                    1 該語句獲取列表的 pop 方法的引用。注意該語句并不是調用 pop 方法;調用 pop 方法的應該是 li.pop()。這里指的是方法對象本身。
                    2 該語句也是返回 pop 方法的引用,但是此時,方法名稱是作為一個字符串參數傳遞給 getattr 函數的。getattr 是一個有用到令人無法致信的內置函數,可以返回任何對象的任何屬性。在這個例子中,對象是一個 list,屬性是 pop 方法。
                    3 如果不確信它是多么的有用,試試這個:getattr 的返回值 方法,然后你就可以調用它,就像直接使用 li.append("Moe") 一樣。但是實際上你沒有直接調用函數;只是以字符串形式指定了函數名稱。
                    4 getattr 也可以作用于字典。
                    5 理論上,getattr 可以作用于元組,但是由于元組沒有方法,所以不管你指定什么屬性名稱 getattr 都會引發一個異常。

                    4.4.1. 用于模塊的 getattr

                    getattr 不僅僅適用于內置數據類型,也可作用于模塊。

                    例 4.11. apihelper.py 中的 getattr 函數

                    >>> import odbchelper
                    >>> odbchelper.buildConnectionString             1
                    <function buildConnectionString at 00D18DD4>
                    >>> getattr(odbchelper, "buildConnectionString") 2
                    <function buildConnectionString at 00D18DD4>
                    >>> object = odbchelper
                    >>> method = "buildConnectionString"
                    >>> getattr(object, method)                      3
                    <function buildConnectionString at 00D18DD4>
                    >>> type(getattr(object, method))                4
                    <type 'function'>
                    >>> import types
                    >>> type(getattr(object, method)) == types.FunctionType
                    True
                    >>> callable(getattr(object, method))            5
                    True
                    1 該語句返回 odbchelper 模塊中 buildConnectionString 函數的引用,第 2 章 第一個 Python 程序 你已經研習過這個方法了。(你看到的這個十六進制地址是我機器上的;你的輸出結果會有所不同。)
                    2 使用 getattr,你能夠獲得同一函數的同一引用。通常,getattr(object, "attribute") 等價于 object.attribute。如果 object 是一個模塊的話,那么 attribute 可能是定義在模塊中的任何東西:函數、類或者全局變量。
                    3 接下來的是你真正用在 info 函數中的東西。object 作為一個參數傳遞給函數; method 是方法或者函數的名稱字符串。
                    4 在這個例子中,method 是函數的名稱,通過獲取 type 可以進行驗證。
                    5 由于 method 是一個函數,所以它是可調用的

                    4.4.2. getattr 作為一個分發者

                    getattr 常見的使用模式是作為一個分發者。舉個例子,如果你有一個程序可以以不同的格式輸出數據,你可以為每種輸出格式定義各自的格式輸出函數,然后使用唯一的分發函數調用所需的格式輸出函數。

                    例如,讓我們假設有一個以 HTMLXML 和普通文本格式打印站點統計的程序。輸出格式在命令行中指定,或者保存在配置文件中。statsout 模塊定義了三個函數:output_htmloutput_xmloutput_text。然后主程序定義了唯一的輸出函數,如下:

                    例 4.12. 使用getattr 創建分發者

                    
                    import statsout
                    
                    def output(data, format="text"):                              1
                        output_function = getattr(statsout, "output_%s" % format) 2
                        return output_function(data)                              3
                    
                    1 output 函數接收一個必備參數 data,和一個可選參數 format。如果沒有指定 format 參數,其缺省值是 text 并完成普通文本輸出函數的調用。
                    2 你可以連接 format 參數值和 "output_" 來創建一個函數名稱作為參數值,然后從 statsout 模塊中取得該函數。這種方式允許今后很容易地擴展程序以支持其它的輸出格式,而且無需修改分發函數。所要做的僅僅是向 statsout 中添加一個函數,比如 output_pdf,之后只要將 “pdf” 作為 format 的參數值傳遞給 output 函數即可。
                    3 現在你可以簡單地調用輸出函數,就像調用其它函數一樣。output_function 變量是指向 statsout 模塊中相應函數的引用。

                    你是否發現前面示例的一個 Bug?即字符串和函數之間的松耦合,而且沒有錯誤檢查。如果用戶傳入一個格式參數,但是在 statsout 中沒有定義相應的格式輸出函數,會發生什么呢?還好,getattr 會返回 None,它會取代一個有效函數并被賦值給 output_function,然后下一行調用函數的語句將會失敗并拋出一個異常。這種方式不好。

                    值得慶幸的是,getattr 能夠使用可選的第三個參數,一個缺省返回值。

                    例 4.13. getattr 缺省值

                    
                    import statsout
                    
                    def output(data, format="text"):
                        output_function = getattr(statsout, "output_%s" % format, statsout.output_text)
                        return output_function(data) 1
                    
                    1 這個函數調用一定可以工作,因為你在調用 getattr 時添加了第三個參數。第三個參數是一個缺省返回值,如果第二個參數指定的屬性或者方法沒能找到,則將返回這個缺省返回值。

                    正如你所看到,getattr 是相當強大的。它是自省的核心,在后面的章節中你將看到它更強大的示例。

                      <pre id="vvttv"><mark id="vvttv"><progress id="vvttv"></progress></mark></pre>
                      <pre id="vvttv"></pre>

                        <p id="vvttv"></p>

                            <p id="vvttv"></p>

                                  <p id="vvttv"></p>

                                  <pre id="vvttv"><cite id="vvttv"><progress id="vvttv"></progress></cite></pre>

                                    <output id="vvttv"><dfn id="vvttv"><th id="vvttv"></th></dfn></output>

                                      <p id="vvttv"></p>

                                      这里只有精品视频