[英]What is the pythonic way to have objects that reference one another?
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.显然,这种关系是相互的:如果 A 与 B 作为合作伙伴,那么 B 必须与 A 作为合作伙伴。
But how would you make this code work in practice?但是你如何让这段代码在实践中发挥作用呢? How would I even instantiate A or B?我什至如何实例化 A 或 B? And should code like this be avoided so as one does not run into recursive issues?并且应该避免这样的代码,以免遇到递归问题? What is common practice?什么是普遍做法?
You can use a method, after instanciation, that would create the 2 links, note that this a reference to the other not a copy您可以在实例化之后使用一种方法来创建 2 个链接,请注意,这是对另一个链接的引用,而不是副本
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您不能使用other.set_partner(self)
,因为那样会一次又一次地再次调用该方法,从而导致 RecursionError
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:可能有比让Person
对象包含对partner
的引用更好的方法来对此进行建模,但是如果您确实需要循环引用,则解决方案是在对象实例化后设置它们:
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
Addition to @azro's answer, but now it avoids having one-sided couples.除了@azro 的答案,但现在它避免了单方面的夫妇。
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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.