Is Python call-by-value or call-by-reference? Binding Names to Objects
2014-03-25 23:17
525 查看
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 misunderstandingabout 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_guyrefers
to a location in memory, and the value 'Fred' is inserted in that location (indeed, we can take the address of
some_guyto
determine the portion of memory to which it refers). Later, the contents of the memory location referred to by
some_guyare
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 name, some_guy,
and a string object containing 'Fred'. In the context of program execution, the environment is altered; a binding of the name
some_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_guy. We
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_names another_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_guyto
the string object containing 'Fred' is added to the block's namespace. The name
first_namesis
bound to an empty list object. On line 4, a method is called on the list object
first_namesis
bound to, appending the object
some_guyis bound to. At this point,
there are still only two objects that exist: the string object and the list object.
some_guyand
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_namesis 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_tupleis
bound to. But immutable containers may contain references to mutable objects like lists. Therefore, even though
name_tupleis
immutable, it "changes" when 'Igor' is appended to
first_nameson the
last line. It's a subtlety that can sometimes (though very infrequently) prove useful.
相关文章推荐
- Is Python call-by-value or call-by-reference?
- call by value or reference -
- call by value or reference -
- call by value or reference ?
- 002:Is Java “pass-by-reference” or “pass-by-value”?
- Is Java pass by VALUE or pass by REFERENCE?
- Passing by reference or by value? it is a question
- 出现 Assigning the return value of new by reference is deprecated in xxxx &&“Warning: Call-time pass-by-reference has been deprecated”怎么办?
- call by value or reference -
- 显示Deprecated: Assigning the return value of new by reference is deprecated in解决办法
- call by value ;call by address/reference ;call by name;call by pointer
- Java: pass by value or reference?
- PHP显示Deprecated: Assigning the return value of new by reference is deprecated in解决办法
- Does Java pass by reference or pass by value?
- JavaScript: Passing by Value or by Reference
- parameters vs. arguments and call by value vs. call by reference
- php5.3 的问题 “Assigning the return value of new by reference is deprecated in xxxx”
- ECShop后台站点地图关于 Deprecated: Assigning the return value of new by reference is deprecated的错误的解决办法
- Reference Or Value pass in python
- Warning: Null value is eliminated by an aggregate or other SET operation.