了解Python的传递函数参数的对象风格 [英] Understanding Python's call-by-object style of passing function arguments

查看:90
本文介绍了了解Python的传递函数参数的对象风格的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我不确定我是否理解Python调用通过传递函数参数的对象风格的概念(这里解释 http://effbot.org/zone/call-by-object.htm )。有没有足够的例子可以很好地阐明这个概念(或者我的google-fu可能很弱!):D

我写了这个小小的人工Python程序试着理解这个概念:

$ $ $ $ $ $ $ $ deffoo $ it $ $ $ $ $ $ $
print id(itnumber),itnumber

print id(ittuple),ittuple

itlist.append(3.4)
print id(itlist),itlist

itdict ['mary'] = 2.3
print id(itdict),itdict



#初始化一个数字,一个元组,列表和字典
tnumber = 1
print id(tnumber),tnumber

ttuple =(1,2,3)
print id(ttuple) ,ttuple

tlist = [1,2,3]
print id(tlist),tlist

tdict = tel = {'jack':4098,'' sape':4139}
print'-------'
#调用一个函数并测试它
foo(tnumber,ttuple,tlist,tdict)

打印'-------'
#Tes t行为在函数调用后超过
print id(tnumber),tnumber
print id(ttuple),ttuple
print id(tlist),tlist
print id(tdict) ,tdict

程序的输出是

  146739376 1 
3075201660(1,2,3)
3075103916 [1,2,3]
3075193004 {'sape':4139,'' jack':4098}

---------

146739364 2
3075201660(1,2,3)
3075103916 [ 1,2,3,3.4]
3075193004 {'sape':4139,'jack':4098,'mary':2.3}

---------

146739376 1
3075201660(1,2,3)
3075103916 [1,2,3,3.4]
3075193004 {'sape':4139,'jack' :4098,'mary':2.3}

正如您所看到的,除了传入的整数,对象ID(据我所知,指memeory位置)保持不变。

所以在整数情况下,它被(有效地)按值传递,另一个数据结构被(有效地)通过引用传递。我试着改变列表,数字和字典来测试数据结构是否已经改变。这个数字不在名单和
字典中。

我在上面使用了这个词这个词,因为参数传递的'调用对象'风格似乎表现为两种方式,这取决于在上面的代码中传递的数据结构

对于更复杂的数据结构(比如numpy数组等),有没有什么快速的经验法则可以让
识别哪个参数将通过引用传递,哪些通过值传递?

解决方案

关键区别在于,在C风格语言中,变量是内存中的一个框,东东。在Python中,变量是一个名字。



Python既不是按引用也不是按值调用。这是更明智的东西! (事实上​​,在我学习更多常用语言之前,我学会了Python,因此对于我来说,按值调用和按引用调用看起来很奇怪。)



在Python中有 名称。列表,整数,字符串和自定义对象都是事物。 x y z 是名称。写作

  x = [] 

的意思是构建一个新的东西 [] 并给它起名叫 x 。写作

  x = [] 
foo = lambda x:x.append(无)
foo x)

表示构建一个新的东西 [] f 构造一个新函数(这是另一回事),并调用对于名称 x 的东西,c $ c> foo 。现在 foo 只是将 None 附加到所有收到的内容中,所以这会减少为append None 到空的列表。写作

  x = 0 
def foo(x):
x + = 1
foo (x)

的意思是构造一个新事物 0 名称 x ,构造一个新函数 foo ,并调用 foo on x 。在 foo 里面,赋值只是说重命名 x 为1加上它曾经是的,但那并不是' t改变 0。


I am not sure I understand the concept of Python's call by object style of passing function arguments (explained here http://effbot.org/zone/call-by-object.htm). There don't seem to be enough examples to clarify this concept well (or my google-fu is probably weak! :D)

I wrote this little contrived Python program to try to understand this concept

def foo( itnumber, ittuple,  itlist, itdict   ):
    itnumber +=1 
    print id(itnumber) , itnumber 

    print id(ittuple)  , ittuple

    itlist.append(3.4)
    print id(itlist)   , itlist

    itdict['mary']  = 2.3
    print id(itdict),    itdict



# Initialize a number, a tuple, a list and a dictionary
tnumber = 1
print id( tnumber ), tnumber 

ttuple  = (1, 2, 3)
print id( ttuple ) , ttuple

tlist   = [1, 2, 3]
print id( tlist ) , tlist

tdict = tel = {'jack': 4098, 'sape': 4139}
print '-------'
# Invoke a function and test it
foo(tnumber, ttuple, tlist , tdict)

print '-------'
#Test behaviour after the function call is over
print id(tnumber) , tnumber 
print id(ttuple)  , ttuple
print id(tlist)   , tlist
print id(tdict),  tdict

The output of the program is

146739376 1
3075201660 (1, 2, 3)
3075103916 [1, 2, 3]
3075193004 {'sape': 4139, 'jack': 4098}

---------

146739364 2
3075201660 (1, 2, 3)
3075103916 [1, 2, 3, 3.4]
3075193004 {'sape': 4139, 'jack': 4098, 'mary': 2.3}

---------

146739376 1
3075201660 (1, 2, 3)
3075103916 [1, 2, 3, 3.4]
3075193004 {'sape': 4139, 'jack': 4098, 'mary': 2.3}

As you can see , except for the integer that was passed, the object id's (which as I understand refers to memeory location) remain unchanged.

So in the case of the integer, it was (effectively) passed by value and the other data structure were (effectively) passed by reference. I tried changing the list , the number and the dictionary to just test if the data-structures were changed in place. The number was not bu the list and the dictionary were.

I use the word effectively above, since the 'call-by-object' style of argument passing seems to behave both ways depending on the data-structure passed in the above code

For more complicated data structures, (say numpy arrays etc), is there any quick rule of thumb to recognize which arguments will be passed by reference and which ones passed by value?

解决方案

The key difference is that in C-style language, a variable is a box in memory in which you put stuff. In Python, a variable is a name.

Python is neither call-by-reference nor call-by-value. It's something much more sensible! (In fact, I learned Python before I learned the more common languages, so call-by-value and call-by-reference seem very strange to me.)

In Python, there are things and there are names. Lists, integers, strings, and custom objects are all things. x, y, and z are names. Writing

x = []

means "construct a new thing [] and give it the name x". Writing

x = []
foo = lambda x: x.append(None)
foo(x)

means "construct a new thing [] with name x, construct a new function (which is another thing) with name foo, and call foo on the thing with name x". Now foo just appends None to whatever it received, so this reduces to "append None to the the empty list". Writing

x = 0
def foo(x):
    x += 1
foo(x)

means "construct a new thing 0 with name x, construct a new function foo, and call foo on x". Inside foo, the assignment just says "rename x to 1 plus what it used to be", but that doesn't change the thing 0.

这篇关于了解Python的传递函数参数的对象风格的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆