从 python 中获取容器/父对象

问题描述 投票:0回答:6

在 Python 中,是否可以从 Bar 本身获取包含另一个对象 Bar 的对象(例如 Foo)?这是我的意思的一个例子

class Foo(object):
    def __init__(self):
        self.bar = Bar()
        self.text = "Hello World"

class Bar(object):
    def __init__(self):
        self.newText = foo.text #This is what I want to do, 
                                #access the properties of the container object

foo = Foo()

这可能吗?谢谢!

python class object containers
6个回答
55
投票

传递对 Bar 对象的引用,如下所示:

class Foo(object):
    def __init__(self):
        self.text = "Hello World"  # has to be created first, so Bar.__init__ can reference it
        self.bar = Bar(self)

class Bar(object):
    def __init__(self, parent):
        self.parent = parent
        self.newText = parent.text

foo = Foo()

编辑: 正如@thomleo 所指出的,这可能会导致垃圾收集问题。建议的解决方案位于 http://eli.thegreenplace.net/2009/06/12/safely-using-destructors-in-python/ ,看起来像

import weakref

class Foo(object):
    def __init__(self):
        self.text = "Hello World"
        self.bar = Bar(self)

class Bar(object):
    def __init__(self, parent):
        self.parent = weakref.ref(parent)    # <= garbage-collector safe!
        self.newText = parent.text

foo = Foo()

5
投票

是否有可能从 Bar 本身获取包含另一个对象 Bar 的对象(例如 Foo)?

不是“自动”,因为语言不是这样构建的,特别是,语言的构建使得无法保证 Foo 存在。

也就是说,你总是可以明确地做到这一点。与 Python 中的所有其他标识符一样,属性只是名称,而不是数据的存储空间;因此,没有什么可以阻止您让 Bar 实例具有手动分配的

foo
属性,该属性是 Foo 实例,反之亦然。


4
投票

是的,这是可能的。即使在创建对象时没有传递容器引用,即如果您的对象是类属性。 你的对象需要实现描述符协议(有一个

__get__()
):

class ChildName(SimpleNamespace):                                                         

    def __get__(self, instance, owner):
        # instance is our parent
        return f'I am {self.name}, my parent is {instance.name}.'


class ChildDiff(SimpleNamespace):

    @property
    def diff(self):
        return self.born - self.parent.born

    def age_diff(self):
        return f'I am {self.diff} years older than {self.parent.name}.'

    def __get__(self, instance, owner):
        self.parent = instance  # XXX: weakref?
        return self  # expose object to be able call age_diff() etc.


class Parent(SimpleNamespace):

    child_name = ChildName(name='Bar')
    child_diff = ChildDiff(born=42)


parent = Parent(name='Foo', born=23)
print(parent.child_name)             # ... I am Bar, my parent is Foo.
print(parent.child_diff.age_diff())  # ... I am 19 years older than Foo.

0
投票

这对我有用:

家长

import child

obj_1  = 25             # an object that both parent and child can access

def startup():          # any startup function
    global obj_1
    child.ref( obj_1 )  # send the shared object to the child
    ...

孩子

obj_1 = 0               # initual value will be overwritten

def ref(shared_obj):    # receive a reference to the shared object
    global  obj_1       # shared object is global in the child, optional
    obj_1 = shared_obj  # set obj_1 in the child to be obj_1 in the parent

0
投票

可以通过检查


import inspect

class Foo(object):
    def __init__(self):
        self.text = "Hello World"
        self.bar = Bar()

class Bar(object):
    def __init__(self):
        parentFrameInfo = inspect.stack()[1]
        parentLocalContext = parentFrameInfo.frame.f_locals
        # in parent context (__init__ of Foo) object instance is in variable 'self'
        foo = parentLocalContext["self"]
        self.newText = foo.text #This is what I want to do, 
                                #access the properties of the container object

foo = Foo()
print(foo.text)
print(foo.bar.newText)

但是您需要在构造函数中的

self.text
之前声明
self.bar
。如果不这样做,当调用
Bar()
时,self.text 不会被定义

无论如何,只有当您有真正的特定约束时才应该执行此操作(例如,为了向后兼容,

Foo
构造函数 API 无法更改)。添加
Bar
构造函数
Foo
实例是一个更好的解决方案。


-3
投票

使用继承怎么样:

class Bar(object):
    def __init__(self):
        self.newText = self.text

class Foo(Bar):
    def __init__(self):
        self.txt = 'Hello World'
        Bar.__init__(self)

foo = Foo()
print foo.newText
© www.soinside.com 2019 - 2024. All rights reserved.