Here's a utility function based on a (now-deleted) comment made by "Tiran" in a weblog discussion @Hophat Abc references in his own answer that will work in both Python 2 and 3.
Disclaimer: If you read the the linked discussion, you'll find that some folks think this is so unsafe that it should never be used (as likewise mentioned in some of the comments below). I don't agree with that assessment but feel I should at least mention that there's some debate about using it.
import _ctypes
def di(obj_id):
""" Inverse of id() function. """
return _ctypes.PyObj_FromPtr(obj_id)
if __name__ == '__main__':
a = 42
b = 'answer'
print(di(id(a))) # -> 42
print(di(id(b))) # -> answer
Answer from martineau on Stack Overflowpython - Is it possible to dereference variable id's? - Stack Overflow
python - How to "dereference" a dictionary? - Stack Overflow
python - Dereference variables at class initialization - Stack Overflow
In Python, what's the difference between a variable, an object, a reference, and a value?
Here's a utility function based on a (now-deleted) comment made by "Tiran" in a weblog discussion @Hophat Abc references in his own answer that will work in both Python 2 and 3.
Disclaimer: If you read the the linked discussion, you'll find that some folks think this is so unsafe that it should never be used (as likewise mentioned in some of the comments below). I don't agree with that assessment but feel I should at least mention that there's some debate about using it.
import _ctypes
def di(obj_id):
""" Inverse of id() function. """
return _ctypes.PyObj_FromPtr(obj_id)
if __name__ == '__main__':
a = 42
b = 'answer'
print(di(id(a))) # -> 42
print(di(id(b))) # -> answer
Not easily.
You could recurse through the gc.get_objects() list, testing each and every object if it has the same id() but that's not very practical.
The id() function is not intended to be dereferenceable; the fact that it is based on the memory address is a CPython implementation detail, that other Python implementations do not follow.
To simplify, when you do b = deepcopy(a), that means that nested dictionaries in b are not identical to the nested dictionaries in a, but it doesn't break the internal structure. Dictionaries accessible via different keys are still identical, and cyclical dictionaries (for example a[some_key] is a) remain cyclical.
The best way to deal with this is to make sure your dictionary doesn't have any unwanted shared references in the first place, for example by doing:
return {
"main_key": {
"x": d2,
"y": deepcopy(d2),
}
}
But if you don't control the way the data arrives, you could use a recursive function like this one:
def copy_tree(original):
'''Creates a deep copy of a dictionary, but the copy will
be a tree, so no shared references. Cyclic dictionaries will
cause a recursion error.
All keys, and all non-dictionary values are not copied but used
as-is.'''
if isinstance(original, dict):
return {key: copy_tree(value) for key, value in original.items()}
return original
You can use .copy() on t.
t = {1:2}
x = {'a' : t.copy(), 'b' : t.copy()}
print(x) #{'a': {1: 2}, 'b': {1: 2}}
x['a'].update({1:4})
print(x) #{'a': {1: 4}, 'b': {1: 2}}
I've been discussing Python semantics with a friend who's helped me a lot in the past with understanding programming concepts and he keeps saying that a Python variable is "a name bound to a reference" and "the object on the other side of the reference has a type and a value" while the variable itself doesn't. He's been trying to explain what he means, but I'm not just not fully understanding, so I'm hoping someone here can explain in a way that will make more sense to me.
I think part of why I'm struggling is that I'm very comfortable with the idea of variables and pointers in C because I first learned programming in C++ from a professor whose examples were very C-style, and because I completed an 8 month firmware internship which was primarily low-level c programming. So at this point, the idea of a variable as being fundamentally linked to a physical memory location is kind of stuck in my head. I tend to think of C variables as just labels for memory addresses and, in CPython at least, I know a Python variable's ID (obtained via the id function) IS just the memory address (that's what the CPython documentation says at least). But I also know that if I do something like,
x = 5 print(id(x)) x = 50 print(id(x))
it will print out two different values. My friend said that's because the id doesn't really belong to the variable itself, but to the object. So is the first ID number that would be printed by the above code then a reference to the ID of the object 5? But then, if 5 is an object, what's the value?
You need to hold a reference to an object (i.e. assign it to a variable or store it in a list).
There is no language support for going from an object address directly to an object (i.e. pointer dereferencing).
You're almost certainly asking the wrong question, and Raymond Hettinger's answer is almost certainly what you really want.
Something like this might be useful trying to dig into the internals of the CPython interpreter for learning purposes or auditing it for security holes or something… But even then, you're probably better off embedding the Python interpreter into a program and writing functions that expose whatever you want into the Python interpreter, or at least writing a C extension module that lets you manipulate CPython objects.
But, on the off chance that you really do need to do this…
First, there is no reliable way to even get the address from the repr. Most objects with a useful eval-able representation will give you that instead. For example, the repr of ('1', 1) is "('1', 1)", not <tuple at 0x10ed51908>. Also, even for objects that have no useful representation, returning <TYPE at ADDR> is just an unstated convention that many types follow (and a default for user-defined classes), not something you can rely on.
However, since you presumably only care about CPython, you can rely on id:
CPython implementation detail: This is the address of the object in memory.
(Of course if you have the object to call id (or repr) on, you don't need to dereference it via pointer, and if you don't have the object, it's probably been garbage collected so there's nothing to dereference, but maybe you still have it and just can't remember where you put it…)
Next, what do you do with this address? Well, Python doesn't expose any functions to do the opposite of id. But the Python C API is well documented—and, if your Python is built around a shared library, that C API can be accessed via ctypes, just by loading it up. In fact, ctypes provides a special variable that automatically loads the right shared library to call the C API on, ctypes.pythonapi.
In very old versions of ctypes, you may have to find and load it explicitly, like pydll = ctypes.cdll.LoadLibrary('/usr/lib/libpython2.5.so') (This is for linux with Python 2.5 installed into /usr/lib; obviously if any of those details differ, the exact command line will differ.)
Of course it's much easier to crash the Python interpreter doing this than to do anything useful, but it's not impossible to do anything useful, and you may have fun experimenting with it.
No, this is not possible. After executing the line
p = d['a']
The situation does not look like this:
p ───> d['a'] ───> 1
Rather, it looks like this:
p ───> 1
^
│
d['a'] ───┘
The name p is bound directly to whatever object was resolved as the value for key 'a'. The variable p knows nothing about the dict d, and you could even delete the dict d now.
As others have pointed out, this is not really possible in Python, it doesn't have C++ style references. The closest you can get is if your dictionary value is mutable, then you can mutate it outside and it will be reflected inside the dictionary (because you're mutating the same object as the object stored in the dictionary). This is a simple demonstration:
>>> d = {'1': [1, 2, 3] }
>>> d
{'1': [1, 2, 3]}
>>> x = d['1']
>>> x.append(4)
>>> d
{'1': [1, 2, 3, 4]}
But in general, this is a bad pattern. Don't do this if you can avoid it, it makes it really hard to reason about what's inside the dictionary. If you wanna change something in there, pass the key around. That's what you want.