Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
248 views
in Technique[技术] by (71.8m points)

python - Inner Classes: How can I get the outer-class object at construction time?

Consider the following Python (runs in 2.x or 3.x):

class Outer(object):
  pass

  class Inner(object):
    def __init__(self):
      print("Inner.self", self)

o = Outer()
i = o.Inner()

I want to get my hands on o while inside Inner.__init__(). But:

  • I don't want o to be an explicit parameter to Inner.
  • I want O.Inner and o.Inner to be a class object, not something weird like a closure.

Can you suggest how I might achieve this?

Right now my best idea is to use thread local storage. In my use case, whenever I construct an o.Inner(), I'm already inside a method on o somewhere, and it wouldn't be a big deal to add

threading.local()["my o object"] = o

to my code.

This gives you an idea of the level of depravity I'm willing to consider.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

In Python 2.6, a class decorator that's also a custom descriptor matches the specs you give:

class InnerClassDescriptor(object):
  def __init__(self, cls):
    self.cls = cls
  def __get__(self, instance, outerclass):
    class Wrapper(self.cls):
      outer = instance
    Wrapper.__name__ = self.cls.__name__
    return Wrapper

class Outer(object):
  @InnerClassDescriptor
  class Inner(object):
    def __init__(self):
      print self.outer

o = Outer()
i = o.Inner()
print 'Outer is a', type(Outer)
print 'Inner is a', type(o.Inner)

This emits:

<__main__.Outer object at 0x82f90>
Outer is a <type 'type'>
Inner is a <type 'type'>

just to confirm that

o.Inner [[is]] a class object, not something weird like a closure

as per your peculiar specs. Of course it needs to be a different class each time for reentrancy -- even in a single-threaded world, the following:

o1 = Outer()
o2 = Outer()
i1 = o1.Inner
i2 = o2.Inner
print i1(), i2(), i1(), i2()

should work cleanly, and stashing o1 vs o2 anywhere else than in the classes returned by o1.Inner vs o2.Inner (e.g., in TLS) would mean horrible results for this use.

But then you didn't specify "o.Inner has to be exactly the same class object for every possible o that's an instance of Outer", so this code fully meets the specs you did give;-).


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...