Simulating Pointers in Python
This can be done explicitly.
class ref:
def __init__(self, obj): self.obj = obj
def get(self): return self.obj
def set(self, obj): self.obj = obj
a = ref([1, 2])
b = a
print(a.get()) # => [1, 2]
print(b.get()) # => [1, 2]
b.set(2)
print(a.get()) # => 2
print(b.get()) # => 2
simulating pointer like behavior for python class attribute
You could just set obj.b
as a property:
class A:
def __init__(self, value):
self.a = value
@property
def b(self):
return self.a
obj = A('banana')
# now changing my mind
obj.a = 'apple'
print(obj.b) # apple
Of course there's a little more to properties than that. For example if you try to do something like this:
obj.b = 'orange'
It will fail because you can't set that property. But this
obj.a = 'orange'
Would always work, and this test would always be True
:
obj.a == obj.b
A working example in the console:
>>> class A:
... def __init__(self, value):
... self.a = value
... @property
... def b(self):
... return self.a
...
>>> a = A('apple')
>>> a.a
'apple'
>>> a.b
'apple'
>>> a.a = 'orange'
>>> a.b
'orange'
>>> a.b = 'hello'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: can't set attribute
Pointers in Python?
There's no way you can do that changing only that line. You can do:
a = [1]
b = a
a[0] = 2
b[0]
That creates a list, assigns the reference to a, then b also, uses the a reference to set the first element to 2, then accesses using the b reference variable.
How do I go about simulating the equivalent of pass-by-reference in Python?
Based on the comments, your goal is to get back the return status of a function that you don't call directly, and you want to avoid globals. In C you'd have no choice but to use a reference, but in python you have much more flexibility than just locals and (C-style) globals: You can use "closures" to let your callback assign to a local variable directly.
In Python 3
If you use python 3, you can do this straightforwardly with the nonlocal
keyword. The simplest case is when you define your callback on the spot:
myfunction():
x = None
def callback():
nonlocal x # Python 3 only
x = 5
gtk.somefunction(callback) # Executes callback()
print "My callback returned", x
But your callback is probably defined elsewhere, or called from lots of different places? No problem, just define on the spot a wrapper that captures the return value of the real callback:
def real_callback():
return 11
def myfunction():
x = 0
def wrapper():
nonlocal x # Python 3 only
x = real_callback()
gtk.somefunction(wrapper)
print "my callback returned", x
This can be obscured by turning wrapper
into decorator, but that's a different matter.
Python 2 solution
In python 2 there's no nonlocal
statement, and implicit closures are read-only: If you try the above without the nonlocal
statement, you get an error. You can assign to a variable if you declare it global
, and that's all. So, some trickery is necessary:
First, the function locals()
returns a dictionary with all the variables of the local context. locals()['x']
is the local variable x
. But locals()
is normally read-only. Fortunately there's a nice (or terrible) work-around: For its own reasons, exec
disables the optimization that renders locals()
read-only... and, it turns out, it stays disabled for the lifetime of the calling function! (Tested on Python 2.6.6, YMMV. If it doesn't work, try exec "a = 0"
instead). So, you can do it like this:
def wrapper(callback, context, varname):
def _callback():
context[varname] = callback()
return _callback
def mycode():
exec ""
some_library_function(wrapper(real_callback, locals(), 'z'))
print "The callback returned", z
Is this preferable to just using a mutable container for your return value? That's a matter of taste, I guess. But you can use the same wrapper any number of times, so in a sense it's cleaner than the python 3 solution... if you ignore the magic exec
.
How to implement pointers in Python? (or any similar solution else)
Python doesn't need pointers in order to achieve this as every variable is a reference to an object. These references are slightly different from C++ references, in that they can be assigned to - much like pointers in C++.
So to achieve what you're looking for, you'd just need to do something like this:
class A(object):
def __init__( self, connections, sum ):
self.connections = connections
self.sum = sum
def passToConnections( self, index ):
self.connections[ index ].receive( self.sum )
def receive( self, input ):
self.sum += input
And just to prove that this works as expected:
>>> a1 = A( [], 0 )
>>> a2 = A( [], 0 )
>>> a3 = A( [ a1, a2 ], 10 )
>>> a3.passToConnections( 0 )
>>> a3.passToConnections( 1 )
>>> a3.passToConnections( 1 )
>>> print a1.sum
10
>>> print a2.sum
20
So as you can see we have altered the original objects a1
and a2
by calling through to them via the references in a3
Related Topics
Generating Matplotlib Graphs Without a Running X Server
How to Prevent Python's Urllib(2) from Following a Redirect
How to Implement _Getattribute_ Without an Infinite Recursion Error
Generate a Random Letter in Python
In Python, How to Convert Seconds Since Epoch to a 'Datetime' Object
Connecting to Microsoft SQL Server Using Python
Subprocess.Popen() Error (No Such File or Directory) When Calling Command with Arguments as a String
Chain-Calling Parent Initialisers in Python
Why Are Str.Count('') and Len(Str) Giving Different Output
Moving X-Axis to the Top of a Plot in Matplotlib
Update Row Values Where Certain Condition Is Met in Pandas
How to Group a List of Tuples/Objects by Similar Index/Attribute in Python
Python Regex Escape Operator \ in Substitutions & Raw Strings
How to Access the Previous/Next Element in a for Loop
Splitting a Semicolon-Separated String to a Dictionary, in Python