I readily admit that I might be referring to this by the wrong name or wanting something that I shouldn't need. I'm just hung up on wanting this to be a thing: linking together object attributes so that if I change one, that I'll change the other. Always. Until I do something to disconnect them on purpose.
So let's go straight into an example:
class Example:
def __init__(self):
self.name = ["Thing1"]
a = Example()
b = Example()
c = Example()
a.name = b.name
b.name.append("Thing2")
b.name.remove("Thing1")
So now a.name
and b.name
are connected so that they both are names for the same mutable, which now reads ["Thing2"]
. And further, c.name
is a name of a different value ["Thing1"]
.
I've now accomplished what I want to do: a.name
and b.name
are linked. But this is tremendously kludgy.
I could make a custom list Class and create some methods to switch out the thing in the list and return an immutable when called, so that it looks more like a normal immutable. But all that seems like a hack.
Any thoughts on making this cleaner? Or am I simply wanting a bad thing?
What is data binding? Data binding is the process that establishes a connection between the app UI and the data it displays. If the binding has the correct settings and the data provides the proper notifications, when the data changes its value, the elements that are bound to the data reflect changes automatically.
In simple words, you can say that data binding is a communication between your typescript code of your component and your template which user sees. It makes easy to define interactive applications without worrying about pushing and pulling data. Data binding can be either one-way data binding or two-way data binding.
Two-way data binding will perform two things i.e. setting of the element property and listening to the element change events. The syntax of two way binding is – [( )}. As you can see, it is a combination of the property binding syntax i.e. [ ] and the event binding syntax ( ).
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With