22464

Python elements retrieved from container (list, dict, tuple etc) passed by reference or value?

Question:

I have a function that updates data in a cache (implemented as a dictionary).

def updateCache(name, new_data): global cache info = cache[name] # is this being passed to me as a val or ref? datarows = info['datarows'] datarows.append(new_data) # These will not be necessary if I was dealing with references ...? # or in other words, are the following statements redundant or required? info['datarows'] = datarows cache[name] = info

As the comment in the snippet enquires, do I need to stick the new updated objects back into the cache, or am I dealing with references to the objects stored in the dict - in which case the last two statements are redundant?

Answer1:

Let's just try this out, shall we:

def updateCache(name, new_data): global cache info = cache[name] datarows = info['datarows'] datarows.append(new_data) cache = {'foo': {'datarows': []}, 'bar': {'datarows': []}} print cache updateCache('foo', 'bar') print cache

outputs:

{'foo': {'datarows': []}, 'bar': {'datarows': []}} {'foo': {'datarows': ['bar']}, 'bar': {'datarows': []}}

Answer2:

<blockquote>

or in other words, are the following statements redundant or required?

</blockquote>

They are redundant, since almost everything in python is a reference. (Unless you don't play with some magic functions like __new__)

Answer3:

There are actually three options. See <a href="http://docs.python.org/library/copy.html" rel="nofollow">this link</a> for a description on the different copy flavors. See <a href="https://stackoverflow.com/a/3975388/1025391" rel="nofollow">this post</a> for a nice explanation for each of these.

<ol><li>the variable info is a reference to the same dict object as cache[name]</li> <li>info holds a shallow copy of that dict</li> <li>info holds a deep copy of that dict</li> </ol>

For the determination of which option applies in this case, you need to investigate the <a href="http://docs.python.org/reference/datamodel.html" rel="nofollow">properties of your object</a>. In this case you have a mutable container object (dict). Which implies that you assign the object reference to the new name, as in (equivalent to c = d = {}):

<blockquote>

(Note that c = d = [] assigns the same object to both c and d.)

</blockquote>

Answer4:

info has a value assigned to it. A quick experiment in a Python command line will confirm:

>>> cache = {'ProfSmiles':'LikesPython'} >>> name = 'ProfSmiles' >>> cache[name] 'LikesPython'

therefore in this case if we did info = cache[name], then type(info) would evaluate to <type 'str'><br /> So yes, the last two lines are redundant

Answer5:

As this <a href="https://stackoverflow.com/a/986145/183066" rel="nofollow">answer</a> to a related question explains:

<ol><li>All variables contain references to an object</li> <li>All parameters receive references that are passed by value</li> <li>Changes will have an effect in the outside world only when a mutable object state is modified</li> </ol>

Hence, what has to be taken into account is when some statement changes the state of an object or creates a new one.

Answer6:

If cache[name] evaluates to an instance of a value-type (numeric, string, or tuple) it will be passed by value. If it is a reference-type (dict, list, most other types), it will be passed by reference and your last two lines will be redundant. Of course, if the object is of a reference type but immutable, you'll have to do something else, like make a copy of it and replace the copy in the cache.

Edit: this is how I think about it, anyway. A possibly more technically correct explanation is that all types are passed by reference in Python, but some types like numerics, strings, and tuples are immutable (basically all hashable types), and therefore you can't make changes to the dereferenced object, and have to treat it as if it were pass-by-value.

Final edit: mutability is independent of hashability (though it would be odd to design a type that was immutable but unhashable), and it is mutability, not hashability, that matters in the OP's case. (Of course, name must be hashable to be a key in cache, but cache[name] could be anything.)

Recommend

  • __init__ being called on __str__ result in aenum.Enum
  • Django WSGI deployment. No module named '_sqlite3'
  • Python SQLAlchemy: AttributeError: Neither 'Column' object nor 'Comparator' obje
  • Different resource folders for separate tablet & mobile APKs
  • Swift compile error, subclassing NSValue, using super.init(nonretainedObject:)
  • Dynamically generate package name for multi-flavors configuration
  • OSError: Could not open VISA library
  • Eclipse : Unknown Source Java SQL Exception
  • Why does _GET in PHP wrongly decodes slash?
  • cURL for Windows can't make a secure connection to the Stack API
  • Cleave.js Phone CA
  • SSLRead() return error -9806/15958)
  • What distributed message queues support millions of queues?
  • update record in database using jdatabase
  • C++ and JS RegEx equivalent of \\p{L}
  • Python getting common name from URL using ssl.getpeercert()
  • Most efficient way to move table rows from one table to another
  • std::remove_copy_if_ valgrind bytes in block are possibly lost in loss record
  • How can the INSERT … ON CONFLICT (id) DO UPDATE… syntax be used with a sequence ID?
  • Webgrid not refreshing after delete MVC
  • QLPreviewController hide print button in ios6
  • Functions in global context
  • Jquery UI tool tip close icon
  • does jqgrid support a multiple checkbox list for editing
  • Uncaught Error: Could not find module `ember-load-initializers`
  • Deleting and Updating values from a cusrsor adapter
  • output of program is not same as passed argument
  • Does CUDA 5 support STL or THRUST inside the device code?
  • Modifying destination and filename of gulp-svg-sprite
  • 'TypeError' while using NSGA2 to solve Multi-objective prob. from pyopt-sparse in OpenMDAO
  • Statically linking a C++ library to a C# process using CLI or any other way
  • Why winpcap requires both .lib and .dll to run?
  • XCode can't find symbols for a specific iOS library/framework project
  • Traverse Array and Display in markup
  • NSLayoutConstraint that would pin a view to the bottom edge of a superview
  • Free memory of cv::Mat loaded using FileStorage API
  • Memory offsets in inline assembly
  • Turn off referential integrity in Derby? is it possible?
  • Qt: Run a script BEFORE make
  • jQuery Masonry / Isotope and fluid images: Momentary overlap on window resize