簡體   English   中英

Python:如何檢查參數的類型是按值還是按引用傳遞?

[英]Python: how to check if an argument's type is such that it will be passed by value or by reference?

原子類型(int、string、...)似乎是按值傳遞的,而所有其他類型(對象、函數指針、方法指針等)都是按引用傳遞的。

檢查變量是按值傳遞還是按引用傳遞的最佳方法是什么?

isinstance(input_, float) or isinstance(input_, basestring) or <...>

似乎很不雅觀。

我需要它的原因如下:我有一個包裝 wx.Button 的類,如果 args/kwargs 是按值傳遞的類型,則不會考慮在其他對象中更新它們的值。 所以一些檢查將是有益的

class PalpyButton(wx.Button):        
    def __init__(self, parent, btnLabel, handler, successMsg = None, args = (), kwargs = {}):
        super(PalpyButton, self).__init__(parent, -1, btnLabel)
        self.handler = handler
        self.successMsg = successMsg
        parent.Bind(wx.EVT_BUTTON, lambda event: self.onClick(event, *args, **kwargs), self)
    def onClick(self, event, *args, **kwargs):
        try:
            self.handler(*args, **kwargs)
            if self.successMsg != None:
                if hasattr(self.successMsg, '__call__'):
                    showInfoMessageBox(self.successMsg())
                else:
                    showInfoMessageBox(self.successMsg)
        except BaseException, detail:
            showErrorMessageBox(detail)

這個問題不成立。 一切都以完全相同的方式傳遞,無論類型、值、操作系統、月相等如何。

這種參數傳遞的風格是否最好描述為按值傳遞、按引用傳遞或其他方式,尚有爭議(但請注意,使用“按值/引用傳遞”需要“值”/“引用”的非標准定義”,這是其他術語的主要推理,例如“通過對象”)。 這里沒關系。 它總是一樣的。

編輯:就您的示例而言, handler的語義不會根據參數類型而改變。 要么是分配給變量(AKA 名稱):

def my_handler(x):
    x = <whatever>

...但隨后my_handler(<anything>)不會改變參數所指的對象(並且無論您是傳入局部變量、對象屬性、更復雜表達式的結果還是其他任何內容都無關緊要)別的)。 順便說一下,一切都是一個對象,你人為的區別(“原子”,“函數指針”)是沒有意義的。

或者,該函數(嘗試)更改對象(例如,向集合添加/刪除項目、更改對象屬性、調用更改某些可以間接觀察的狀態的方法)。 如果對象不支持(例如調用一個不存在的方法),這可能會引發異常,但是對於任何訪問都會發生這種情況,而不僅僅是突變。 如果對象的值確實發生了更改,則通過對該對象的每次引用始終可見。 由於在許多情況下(例如參數傳遞、變量賦值、屬性賦值等)創建了對現有對象的新引用,您可以通過在一處更改對象的值並在另一處觀察更改來觀察對象沒有被復制. 這適用於所有對象(同樣,前提是您可以更改對象的值)。

現在,有些對象是不可變的,這(根據定義)意味着您無法更改它們的值,因此無法以這種方式觀察對象“共享”(盡管您可以通過其他方式觀察它)。 這並不意味着賦值根據可變性具有不同的語義(它不是),它只是意味着您可以使用可變對象來做那些使用不可變對象無法做到的事情。 您可以對兩者執行的操作對兩者的作用相同。

如果你真的需要改變傳遞給你的變量的值,你可以將它包裝在一個數組中,以在過程中實現按引用傳遞:

def increaseInt(i_var):
  i_var[0] += 1

i_ref = [42]
increase(i_ref)
print i_ref[0]  # will print 43

在某些情況下,這可能是像您這樣的問題的(有爭議的)解決方案。

但總的來說,所有值在 Python 中都是通過引用傳遞的(在某種意義上說,不創建副本); 有些值是不可變的(如整數、字符串、元組……)。 您可能會對為參數變量分配一個新值感到困惑——這絕對不會改變之前在參數變量中的值,它只是用一個新值覆蓋它(從而刪除對原始值的額外引用)。 這就是為什么上面的例子沒有給i_var分配任何東西,而是給i_var[0]分配一些東西。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM