Let's say I have the following code.
class Person:
def __init__(partner: Person)
self.partner = partner
So, basically, we have a world of persons, and every person has one partner. Obviously this relationship is mutual: if person A has person B as a partner, then person B must have person A as a partner.
But how would you make this code work in practice? How would I even instantiate A or B? And should code like this be avoided so as one does not run into recursive issues? What is common practice?
CodePudding user response:
You can use a method, after instanciation, that would create the 2 links, note that this a reference to the other not a copy
class Person:
def __init__(self, name):
self.name = name
self.partner = None
def set_partner(self, other: 'Person'):
self.partner = other
other.partner = self
def __str__(self):
if self.partner:
return self.name "<>" self.partner.name
return self.name " is alone"
a = Person("A")
b = Person("B")
print(a) # A is alone
print(b) # B is alone
a.set_partner(b)
print(a) # A<>B
print(b) # A<>B
You can't use other.set_partner(self)
because that would then call again the method again and again, leading to a RecursionError
CodePudding user response:
There may be better ways to model this than having the Person
object contain a reference to partner
, but if you do need circular references, the solution is to set them up after the objects have been instantiated:
class Person:
def __init__(self):
self.partner = None
alice = Person()
bob = Person()
alice.partner = bob
bob.partner = alice
A way to do this that didn't involve circular references between the objects themselves might be to store the relationships somewhere else:
from dataclasses import dataclass
@dataclass(frozen=True)
class Person:
name: str
partners: dict[Person, Person] = {}
alice = Person("Alice")
bob = Person("Bob")
partners[alice] = bob
partners[bob] = alice
CodePudding user response:
Addition to @azro's answer, but now it avoids having one-sided couples.
class Person:
def __init__(self, name):
self.name = name
self.partner = None
def set_partner(self, other: 'Person'):
if self.partner is not None: # |this is new
self.partner.partner = None # |
if other.partner is not None: # |
other.partner.partner = None # |
self.partner = other
other.partner = self
def __str__(self):
if self.partner:
return self.name "<>" self.partner.name
return self.name " is alone"
a = Person("A")
b = Person("B")
c = Person("C")
print(a) # A is alone
a.set_partner(b)
b.set_partner(c)
print(a) # A is alone again
print(b) # B<>C
print(c) # C<>B