web-dev-qa-db-ja.com

python内からコンテナ/親オブジェクトを取得する

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()

これは可能ですか?ありがとう!

28

次のように、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()

Edit:@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()
44
Hugh Bothwell

bar内から別のオブジェクトBarを含むFooなどのオブジェクトを取得することはできますか?

「自動的に」ではなく、言語はそのように構築されていないため、特に、言語はFooが存在することを保証する方法がないように構築されています。

つまり、いつでも明示的に行うことができます。 Pythonの他のすべての識別子と同様に、属性は単なる名前であり、データのストレージスペースではありません。したがって、BarインスタンスにFooインスタンスであるfoo属性を手動で割り当てさせたり、同時にその逆をさせたりすることを妨げるものは何もありません。

5
Karl Knechtel

はい、可能です。オブジェクトの作成時にコンテナー参照を渡さなくても、つまり、オブジェクトがクラス属性の場合です。オブジェクトは記述子プロトコルを実装する必要があります(__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
Da Mn