Is Python call-by-value or call-by-reference? Binding Names to Objects

来源:互联网 发布:js设计模式 编辑:程序博客网 时间:2024/05/22 07:51

Is Python call-by-value or call-by-reference? Neither.
Posted on Nov 13, 2012 by Jeff Knupp

One aspect of Python programming that trips up those coming from languages like C or Java is how arguments are passed to functions in Python. At a more fundamental level, the confusion arises from a misunderstanding about Python object-centric data model and its treatment of assignment. When asked whether Python function calling model is "call-by-value" or "call-by-reference", the correct answer is: neither. Indeed, to try to shoe-horn those terms into a conversation about Python's model is misguided. "call-by-object," or "call-by-object-reference" is a more accurate way of describing it. But what does "call-by-object" even mean?

In Python, (almost) everything is an object. What we commonly refer to as "variables" in Python are more properly called names. Likewise, "assignment" is really the binding of a name to an object. Each binding has a scope that defines its visibility, usually the block in which the name originates.

That's a lot of terminology all at once, but those basic terms form the cornerstone of Python's execution model. Compared to, say, C++, the differences are subtle yet important. A concrete example will highlight these differences. Think about what happens when the following C++ code is executed:

string some_guy = "Fred";// ...some_guy = "George";

In the above, the variable some_guy refers to a location in memory, and the value 'Fred' is inserted in that location (indeed, we can take the address of some_guy to determine the portion of memory to which it refers). Later, the contents of the memory location referred to bysome_guy are changed to 'George'. The previous value no longer exists; it was overwritten. This likely matches your intuitive understanding (even if you don't program in C++).

Let's now look at a similar block of Python code:

some_guy = 'Fred'# ...some_guy = 'George'

Binding Names to Objects

On line 1, we create a binding between a namesome_guy, and a string object containing 'Fred'. In the context of program execution, the environment is altered; a binding of the namesome_guy' to a string object is created in the scope of the block where the statement occurred. When we later say some_guy = 'George', the string object containing 'Fred' is unaffected. We've just changed the binding of the name some_guyWe haven't, however, changed either the 'Fred' or 'George' string objects. As far as we're concerned, they may live on indefinitely.

With only a single name binding, this may seem overly pedantic, but it becomes more important when bindings are shared and function calls are involved. Let's say we have the following bit of Python code:

some_guy = 'Fred'first_names = []first_names.append(some_guy)another_list_of_names = first_namesanother_list_of_names.append('George')some_guy = 'Bill'print (some_guy, first_names, another_list_of_names)

So what get's printed in the final line? Well, to start, the binding of some_guy to the string object containing 'Fred' is added to the block's namespace. The name first_names is bound to an empty list object. On line 4, a method is called on the list object first_names is bound to, appending the object some_guy is bound to. At this point, there are still only two objects that exist: the string object and the list object. some_guy and first_names[0] both refer to the same object (Indeed, print(some_guy is first_names[0]) shows this).

Let's continue to break things down. On line 6, a new name is bound:another_list_of_names. Assignment between names does not create a new object. Rather, both names are simply bound to the same object. As a result, the string object and list object are still the only objects that have been created by the interpreter. On line 7, a member function is called on the object another_list_of_names is bound to and it is mutated to contain a reference to a new object: 'George'. So to answer our original question, the output of the code is

Bill ['Fred', 'George'] ['Fred', 'George']

This brings us to an important point: there are actually two kinds of objects in Python. Amutable object exhibits time-varying behavior. Changes to a mutable object are visible through all names bound to it. Python's lists are an example of mutable objects. An immutable object does not exhibit time-varying behavior. The value of immutable objects can not be modified after they are created. They can be used to compute the values of new objects, which is how a function like string.join works. When you think about it, this dichotomy is necessary because, again, everything is an object in Python. If integers were not immutable I could change the meaning of the number '2' throughout my program.

It would be incorrect to say that "mutable objects can change and immutable ones can't", however. Consider the following:

first_names = ['Fred', 'George', 'Bill']last_names = ['Smith', 'Jones', 'Williams']name_tuple = (first_names, last_names)first_names.append('Igor')

Tuples in Python are immutable. We can't change the tuple object name_tuple is bound to. But immutable containers may contain references to mutable objects like lists. Therefore, even though name_tuple is immutable, it "changes" when 'Igor' is appended to first_names on the last line. It's a subtlety that can sometimes (though very infrequently) prove useful.

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 ipad系统被锁了怎么办 电脑管理员账号删了怎么办 自己电脑删文件需要管理员怎么办 苹果电脑管理员密码忘记了怎么办 电脑提示安全设置不允许下载怎么办 微信和ipad同步怎么办 苹果6空间已满怎么办 苹果6内存虚满怎么办 监控主机密码忘了怎么办 加购物车不下单怎么办 绑定qq账号消息不见了怎么办 现在的注册微信怎么办 爱奇艺手机号码被别人绑定了怎么办 手机号码换了支付宝账号怎么办 qq换手机号了怎么办呢 公司被注销了公众号怎么办 qq号被限制查找怎么办 qq号别人查找不到怎么办 qq邮箱已被注册怎么办 微信付款没网络怎么办 天猫买的假货店铺关门了怎么办 鞋小了半码怎么办 迅雷会员种子不能加速怎么办 迅雷会员为什么不能加速怎么办 持有st创智股票怎么办 租的房子床坏了怎么办 宜家定时器不响怎么办 新插座插不进去怎么办 本溪人社app打不开怎么办 南宁电车超过上牌时间怎么办 苹果6s降频怎么办 0首付手机还不起怎么办 乐才app登录不上怎么办 买了笔记本网要怎么办? 电脑连接不上网络怎么办 电脑上没网络了怎么办 手机返回键不好使怎么办 笔记本无线网连接受限怎么办 魅族打电话图标没有了怎么办 京东价格保护后发票怎么办 淘宝未满十八岁怎么办