Identifying Objects, Why Does the Returned Value from Id(...) Change

identifying objects, why does the returned value from id(...) change?

Because integers are immutable, each integer value is a distinct object with a unique id. The integer 10 has a different id from 11. Doing j=j+1 doesn't change the value of an existing integer object, rather it changes j to point to the object for 11.

Check out what happens when we independently create a new variable k and assign it the value 11:

>>> j=10
>>> id(j)
8402204
>>> j=j+1
>>> id(j)
8402192
>>> k=11
>>> id(k)
8402192

Note that it is not always the case that every integer has one and only one corresponding object. This only happens for small integers that Python decides to cache. It does not happen for large integers:

>>> x = 123456789
>>> id(x)
8404568
>>> y = 123456789
>>> id(y)
8404604

See https://docs.python.org/3/c-api/long.html#c.PyLong_FromLong:

The current implementation keeps an array of integer objects for all integers between -5 and 256, when you create an int in that range you actually just get back a reference to the existing object.

How come I can modify the properties of a named return object inside of a module, but not modify the object itself?

However, I cannot do publicAPI = {} or set the publicAPI object itself, e.g., publicAPI = {a: 1}.

Yes, you can. It just has no effect at all on foo.

Why is this the case?

Because when you do:

return publicAPI;

what's returned is the value of publicAPI, not a reference to the variable. That value is the object reference. If you change the value that's in the publicAPI variable later, that has no effect on anything that has received the previous value of the variable.

Is there a way to modify the object itself?

Your example of assigning to the identify property changes the object (e.g., changes the state of one of the object's properties). But the only way to change which object foo refers to is to assign to foo. Nothing you do to publicAPI can change what object foo refers to.

Difference in variable allocation in python interpreter and python program

An object id is an implementation-defined "blackbox" value. The only garantees are that a given object will keep the same id for all it's lifetime and that no other object (in the same process...) will share this id during this same time (but the id can be reused for another object in the same process one the first object has been garbage collected).

Note that the implementation is free to cache immutable objects for performance reasons, and CPython has indeed been caching some immutable objects under certain circonstances - notably "small" integers (for a definition of "small" that has changed from version to version) and strings that could be valid variables/functions/classes/modules names, but this is really just an implementation detail. FWIW, it looks like some of this caching is not happening at the REPL's top-level anymore (if it ever happened here) - but it still happens in functions defined in the REPL:

Python 2.7.6 (default, Jun 22 2015, 17:58:13) 
[GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
pythonrc start
pythonrc done
>>> x = 300
>>> y = 300
>>> id(x)
37126296
>>> id(y)
37126248
>>> def foo():
... x = 300; print "id(x): %s" % id(x)
... y = 300; print "id(y): %s" % id(y)
...
>>> foo()
id(x): 37126200
id(y): 37126200
>>> foo()
id(x): 37126200
id(y): 37126200
>>> foo()
id(x): 37126200
id(y): 37126200
>>> id(x)
37126296
>>> id(y)
37126248

To make a long story short: you shouldn't ever care about this (unless you're writing your own python runtime of course).

How can I find and update values in an array of objects?

You can use findIndex to find the index in the array of the object and replace it as required:

var item = {...}
var items = [{id:2}, {id:2}, {id:2}];

var foundIndex = items.findIndex(x => x.id == item.id);
items[foundIndex] = item;

This assumes unique IDs. If your IDs are duplicated (as in your example), it's probably better if you use forEach:

items.forEach((element, index) => {
if(element.id === item.id) {
items[index] = item;
}
});

How does python function return objects?

>>> def f():
temp = 6
print(id(temp))
return temp

>>> output = f()
507107408
>>> id(output)
507107408

from doc:

CPython implementation detail: For CPython, id(x) is the memory
address where x is stored.

So strictly speaking, if the value is 6, then output and temp is actually pointing to the same object, which is an int object that is cached when python started.

You may refer to identifying objects, why does the returned value from id(...) change? for more information.

Detecting changes in property values of a .NET object?

A good way is to have an IsDirty flag on the object and have all the setable properties update that flag if they are changed. Have the flag initialized to false when the object is loaded.

An example property would look like this:

public string Name {
get { return _name; }
set {
_name = value;
_isDirty = true;
}
}

Then when you get the object back you can simply check, Customer.IsDirty to see if you need to commit the changes to the database. And as an added bonus you get some humour from the resulting text :) (oh those dirty customers)

You can also opt to always save the object regardless of whether it has been changed, my preference is to use a flag.

Why does python allocate new memory to variables on every new assignment?

Python was designed to have integers be immutable objects. Meaning, you can never mutate (change) them and every operation with them yields a new integer object:

>>> a = 2
>>> id(a)
505911000
>>> id(a + 1)
505911016
>>> a += 2
>>> id(a)
505911032
>>>

Lists on the other hand were designed to be mutable objects. This means that you can change/update their contents without creating a new list object. Moreover, this is exactly what the list.append method does. It adds a new item to the list without creating a new object.

This code however:

a=a+[3,2]

is different than list.append in that it does create a new list object because you used the + operator. a+[3,2] creates a new list object that is the combination of a and [3,2]. You then assign this new object to the name a, overshadowing the old list object and causing a to now refer to the new list. That is why id(a) returns a different number.

What is the id( ) function used for?

Your post asks several questions:

What is the number returned from the function?

It is "an integer (or long integer) which is guaranteed to be unique and constant for this object during its lifetime." (Python Standard Library - Built-in Functions) A unique number. Nothing more, and nothing less. Think of it as a social-security number or employee id number for Python objects.

Is it the same with memory addresses in C?

Conceptually, yes, in that they are both guaranteed to be unique in their universe during their lifetime. And in one particular implementation of Python, it actually is the memory address of the corresponding C object.

If yes, why doesn't the number increase instantly by the size of the data type (I assume that it would be int)?

Because a list is not an array, and a list element is a reference, not an object.

When do we really use id( ) function?

Hardly ever. You can test if two references are the same by comparing their ids, but the is operator has always been the recommended way of doing that. id( ) is only really useful in debugging situations.

Compare a variable with itself using python

You can put the original value of x in another variable before changing its value.

x = 12
y = x
x = 32 # Change your x value after declaring y
if x == y:
print("Changed")
else:
print("Not changed")


Related Topics



Leave a reply



Submit