如何查找物业的所有者?
我有一个简单的类,叫做 A。
class A(object):
pass
我在变量 "a" 中创建了 A 类的一个实例。
a = A()
然后我在 "a" 里创建了一个属性 "b",它也是 A 类的一个实例。
a.b = A()
如果我像这样失去了对 "a" 的引用:
c = a.b
有没有办法在 c 上调用某种函数/方法来返回 "a" 呢?
someFunction(c) == a or c.someMethod() == a
我原以为需要使用 super() 函数,但我不太确定。
我的方法
我再想了一下,这就是我决定采取的做法。
class notObject(object):
pass
class A(notObject):
def __setattr__(self,name,value):
if isinstance(value,A) and name!="parent":
value.parent = self
super(notObject,self).__setattr__(name, value)
a = A()
a.b = A()
c = a.b
c.parent==a
如果有人能帮我把这段代码整理得更好一些,我会很感激。我不想创建一个占位符类 "notObject",但如果 A 继承自对象,那么我就不能把属性设置到它的父类上。
3 个回答
如果你失去了对一个对象的引用,除了通过其他引用外,就没有办法再找回它了。(我想不出其他办法)。如果你需要某个东西的引用... 就要好好保存它。
你问如何找到一个属性的“拥有者”... 但实际上并没有一个单独的“拥有者”... 只有对那个对象的引用。而且,任何一个对象可能有多个引用。看看下面这个例子:
class A(object):
pass
# Create an instance of A
a = A()
# Create a string object
myString = 'Test string'
# Assign the string to a.stringVal
a.stringVal = myString
# Create another instance of A
a2 = A()
# Assign the same string to a2.stringVal
a2.stringVal = myString
在这个例子中... 谁“拥有”myString呢?是a还是a2?答案是这两个对象只是对同一个对象有引用。引用是单向的。你可以跟着引用走,但不能反过来回去。换句话说... 如果你只知道myString,你就无法找到a或a2。而且我不知道有什么方法可以找出哪些对象引用了某个特定的对象,除非你能扫描你知道的每一个变量,看看某个属性是否就是你正在检查的对象。
简单来说,不要丢失引用。如果它们很重要... 就要好好保存。如果一个对象需要另一个对象,你应该设计你的类,让依赖关系在对象创建时就注入,并且那个对象要自己管理自己的依赖关系。想了解更多这种设计模式,可以看看http://en.wikipedia.org/wiki/Dependency_injection。
我知道有三种方法可以处理这个问题。按照我推荐的顺序,它们是:
- 别这么做。如果你需要
a
,就直接跟踪a
,而不是只关注它的b
属性。 - 给
a.b
添加一个属性,指向a
。比如可以写成a.b.owner = a
,不过要注意这样做时不要搞得对象的属性有时候有,有时候没有,显得很乱。 - 通过
gc.get_referrers(c)
查找一个A
实例,它的b
属性是c
。这种方法容易出错,因为可能还有其他的A
实例也有相同的属性。
一般来说,你不能这样做,因为可能没有一个明确的“拥有者”,或者可能有多个“拥有者”。比如说,如果你这样做:
a = A()
a.b = A()
c = a.b
del a.b
通过删除属性 a.b
,你就切断了 a
和之前叫做 a.b
的对象之间的联系。这个对象依然存在,但它和 a
之间不再有任何关系。
同样,你也可以这样做:
a1 = A()
a2 = A()
c = A()
a1.b = c
a2.b = c
那么,c
的“拥有者”是谁呢?同一个对象既是 a1
的一个属性的值,也是 a2
的一个属性的值。你无法在这两者之间做出选择。
在 Python 中并没有内置的“拥有权”概念,因为 Python 的内置结构并不要求一个对象必须“被”或“通过”一个特定的对象来“拥有”。任何对象都可以被任意数量的其他对象引用。如果你想让一个对象有“拥有者”的概念,你需要自己定义这个概念,并把它加入到对象中(例如,给它一个“owner”属性,当你决定拥有权发生变化时,自己更新这个属性)。