In general, when you do re-definition
x = 8
y = x
x = 4 # <-- Re-definition of x
x and y will no longer reference the same thing (try print id(x) == id(y)).
Consider how re-definition works:
x = 8
y = x
x = 4
print y # Still 8
x = "foo"
y = x
x = "bar"
print y # Still 'foo'
x = [1,2,3]
y = x
x = [4,5,6]
print y # Still [1,2,3]
What you can do, with mutable types is to change the object "in place".
For example,
x = [1,2,3]
y = x
Now, both x and y reference the same list (print id(x) == id(y)).
Now we can replace the elements, by using only x:
x[:] = [4,5,6]
Here, we're not re-defining x, we're just modifying the values in the list.
In this case, the changes will be reflected in y:
print y # Now [4,5,6]
Note:
print id(x) == id(y) # True
If you want the ability to modify in-place an immutable type, you can "fake" it by wrapping it in a list:
x = ["Foo"] # Strings are immutable
y = x
x[0] = "Bar"
print y # ['Bar']
print id(x) == id(y) # True
There will be a million questions on here about mutable / immutable types -- you should review them.
Edit We could accomplish what you want with your bind line with a combination of mutable types and properties:
First, we create a "fake" mutable string class:
class FakeMutableString(object):
def __init__(self, s=""):
self.s = [s]
def __str__(self):
return self.s[0]
def get(self):
return self.s[0]
def set(self, new):
self.s[0] = new
And to see how it works
x = FakeMutableString("Foo")
y = x
x.set("Bar")
print y # Prints 'Bar' -- Change in x is reflected in y
Note that we don't re-assign to x -- instead we use the x.set() method. If we re-assigned to x, we'd ruin everything (as we talked about above).
Then, we can modify your Example class to the following:
class Example(object):
def __init__(self):
self._name = FakeMutableString()
@property
def name(self):
return self._name.get()
@name.setter
def name(self, new):
self._name.set(new)
Example instances have an attribute _name attribute that references a FakeMutableString object.
But with properties, we can pretend we're providing direct attribute access, while hiding the actual implementation.
So we can do something like:
# Create Example instances
a = Example()
b = Example()
c = Example()
# Set their name attributes
# ( this actually calls <Example>._name.set() )
a.name = "ThingA"
b.name = "ThingB"
c.name = "ThingC"
# Access and print their name attributes
# ( this actually calls <Example>._name.get() )
print a.name, b.name, c.name # ThingA ThingB ThingC
# We can't bind like you suggested, but we can change what b._name points to
# So here, we change b._name to point to the FakeMutableString a._name points to
b._name = a._name
# Now when we print the names, we see something different
print a.name, b.name, c.name # ThingA ThingA ThingC
# And we can make a change in a, and have it reflected in b
a.name = "CommonName"
print a.name, b.name, c.name # CommonName CommonName ThingC
# And vice-versa
b.name = "StillCommon"
print a.name, b.name, c.name # StillCommon StillCommon ThingC
namein an object with reference semantics; ex.a.name = ["foo"]; b.name = ["bar"]; a.name = b.name; a.name[0] = "baz"; print(b.name[0]) # bazystill references 8 -- try it.