I have two classes that refer to each other in a one-to-many relationship (Kid
and Toy
in the below example). When I assign a new Toy
to Kid
, I want the Kid
to be assigned to Toy
as well.
Creating a custom class based on list for the toys
attribute and redefining methods (e.g. append
, extend
, delete
) would work but I wanted to know if there is a better way.
class Toy:
def __init__(self, name, kid=None):
self.name = name
self.kid = kid
class Kid:
def __init__(self, name, toys):
self.name = name
self.toys = toys
@property
def toys(self):
return self._toys
@toys.setter
def toys(self, val):
self._toys = val
# Assign the kid to the toys
for toy in self._toys:
toy.kid = self
if __name__ == "__main__":
toys = [Toy('Woodie'), Toy('Slinky'), Toy('Rex')]
andy = Kid('Andy', toys)
# Andy corrected assigned to toys
for toy in andy.toys:
print('{}\t{}'.format(toy.name, toy.kid.name))
print('-')
# Add new toy
andy.toys.append(Toy('Buzz'))
# Throws error because Buzz is not assigned Andy
for toy in andy.toys:
print('{}\t{}'.format(toy.name, toy.kid.name))
Output:
Woodie Andy
Slinky Andy
Rex Andy
-
Woodie Andy
Slinky Andy
Rex Andy
Traceback (most recent call last):
File "c:/Users/jonat/Desktop/tests/inheritance_q.py", line 34, in <module>
print('{}\t{}'.format(toy.name, toy.kid.name))
AttributeError: 'NoneType' object has no attribute 'name'
I would like Buzz
to be assigned Andy
.
You could just add a method into your Kid class:
class Toy:
def __init__(self, name, kid=None):
self.name = name
self.kid = kid
class Kid:
def __init__(self, name, toys):
self.name = name
self.toys = toys
@property
def toys(self):
return self._toys
@toys.setter
def toys(self, val):
self._toys = val
# Assign the kid to the toys
for toy in self._toys:
toy.kid = self
def give_toy(self, toy):
toy.kid = self
self.toys.append(toy)
if __name__ == "__main__":
toys = [Toy('Woodie'), Toy('Slinky'), Toy('Rex')]
andy = Kid('Andy', toys)
# Andy corrected assigned to toys
for toy in andy.toys:
print('{}\t{}'.format(toy.name, toy.kid.name))
print('-')
# Add new toy
andy.give_toy(Toy('Buzz'))
# Throws error because Slinky is not assigned Andy
for toy in andy.toys:
print('{}\t{}'.format(toy.name, toy.kid.name))
Output:
Woodie Andy
Slinky Andy
Rex Andy
-
Woodie Andy
Slinky Andy
Rex Andy
Buzz Andy