-1

似乎原子类型(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)
4

2 回答 2

11

这个问题不成立。无论类型、值、操作系统、月相等如何,一切都以完全相同的方式传递。

是否最好将这种参数传递风格描述为按值传递、按引用传递或其他方式,还有待商榷(尽管请注意,使用“按值/引用传递”需要“值”/“引用”的非标准定义”,这是其他术语(例如“通过对象”)的主要推理)。在这里没关系。它总是一样的。

编辑:就您的示例而言, 的语义handler不会根据参数类型而改变。要么分配给变量(AKA 名称):

def my_handler(x):
    x = <whatever>

...但my_handler(<anything>)不会更改参数所指的对象(如果您传入局部变量、对象属性、更复杂表达式的结果或其他任何内容,都无关紧要)。顺便说一句,一切都是对象,您的人为区分(“原子”,“指向函数的指针”)毫无意义。

或者,该函数(尝试)更改对象的值(例如,向集合添加/删除项目,更改对象属性,调用更改某些可以间接观察到的状态的方法)。如果对象不支持它(例如调用不存在的方法),这可能会引发异常,但这会发生在任何访问中,而不仅仅是突变。如果对象的值确实改变了,这总是通过每个可见的对该对象的引用。由于在许多情况下会创建对现有对象的新引用(例如参数传递、变量赋值、属性赋值等),您可以通过在一个地方更改其值并在另一个地方观察更改来观察对象不会被复制. 这适用于所有对象(同样,前提是您可以更改对象的值)。

现在,一些对象是不可变的,这(根据定义)意味着你不能改变它们的值,因此不能以这种方式观察对象“共享”(你可以用其他方式观察它)。这并不意味着赋值根据可变性具有不同的语义(它没有),它只是意味着你可以用可变对象做一些你不能用不可变对象做的事情。您可以对两者执行的操作对两者都一样。

于 2012-11-28T11:41:34.173 回答
-1

如果您确实需要更改传递给您的变量的值,则可以将其包装在数组中以在过程中实现按引用传递:

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].

于 2012-11-28T12:25:51.527 回答