English 中文(简体)
内部班级: 我怎么能够在施工时找到外层物体?
原标题:Inner Classes: How can I get the outer-class object at construction time?
  • 时间:2010-02-17 04:59:57
  •  标签:
  • python

考虑以下山丘(2.x或3.x)。

class Outer(object):
  pass

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

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

我想在<条码>o上接手,在<条码>内。 但:

  • 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.

您能建议我如何做到这一点?

现在,我的最佳想法是利用当地现成的储存。 在我使用的情况下,每当我建造一个<代码>o.Inner()时,在某个地方,Im已经安装在o上的一种方法内,并且不会增加一个大事。

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

to my code.

这使你知道我愿意考虑的残废程度。

最佳回答

在Adhur 2.6中,还有一名习俗描述员的分校与你给出的光谱相匹配:

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)

::

<__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

根据您的特意。 当然,它需要成为每一次复读的fferent级——即使是在一个单一阅读的世界里——以下几个方面:

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.

但随后请didn t具体说明“o.Inner 必须是exactlyevery, 可能的o, s an instance of Outer,从而使该代码完全符合did 报盘;-

问题回答

http://docs.python.org 对内产阶级进行约束的描述。 而且,由于你似乎只想对某类人具有约束力,因此考虑修改内部班级,而不是将这种职能归入一种方法。

>>> class Outer(object):
    class Inner(object):
        class __metaclass__(type):
            def __get__(self, instance, owner):
                self.owner = owner
                return self


>>> Outer.Inner is Outer().Inner
True
>>> Outer.Inner.owner is Outer
True

如果你通过子级对内产阶级进行总结,那么将“植被”改为:

return type(self.__name__, (self,), { owner : owner})

做不到。 但经过重新设计:

class Outer(object):
  pass

  class _Inner(object):
    def __init__(self, outobj):
      self.outobj = outobj

  def Inner(self):
    return self._Inner(self)

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

print o, i.outobj

你们应当重新设计自己的法典,不要使用内部班级,在你提出时,明确将外部承包传给内地,或者不要求这样做。

You can t (in any portable, reliable or efficient way.) Nested classes have no relation to the nesting class. They have no added value, either. Instead of using nested classes, use containment of instances -- define Outer and Inner separately, and create an instance of Inner in Outer.__init__, possibly passing Outer or the Outer instance if you need it. You can make Inner a class attribute of Outer if you insist, but it will have no special access to Outer.

See Access outer class from inner class in python (https://stackoverflow.com/a/35118717/3787376)
for a simple reliable answer I made that only uses variables, attributes, functions and classes - no special code.

这是我对3年级(使用3.7米,不了解以前版本或2x)的解决办法。

from functools import wraps
from inspect import signature as _signature

class _Bound:
       type of bound methodsand classes   
    def __init__(self, callable):
        self._callable = callable
    def __get__(self, instance, cls):
         called when instance.callable or Class.callable 
        if instance is None: # called on class, not instance
            return self._callable

        @wraps(self._callable)
        def retf(*a, **k):
            try: 
                return self._callable(instance, *a, **k)
            except: # information if failed
                # user did `self.callable(*args, **kwargs)` and failed
                print(f failed call of {self._callable} )
                print(f self:   {instance} )
                print(f args:   {a} )
                print(f kwargs: {k} )
                raise 
        # additional wrap to expell first argument
        sig = _signature(retf)
        retf.__signature__ = sig.replace(parameters=tuple(sig.parameters.values())[1:])

        return retf
    def __call__(self, *a, **k):
         Class.__dict__[ BoundMethod ](instance, *a, **k) (c(), 55, 8, key=9) 
        return self._callable(*a, **k)
    pass

class UnBound:
    "similar to static, only doesn t change attribute at all (except for builtin-like method making)"
    def __init__(self, callable):
        self.callable = callable
    pass
class class_(classmethod):
    pass
class static(staticmethod):
    pass

class NestedType(type):
       meta to support nested classes (and other callables)
    meta to outer class   
    @staticmethod
    def bind(dict):
        for name, attr in dict.items():
            if callable(attr) and not isinstance(attr, (class_, static)): #functions, classes, ...
                dict[name] = _Bound(attr)
            elif isinstance(attr, UnBound):
                dict[name] = attr.callable
    def __new__(meta, object_or_name, bases, dict):
        NestedType.bind(dict)
        return type.__new__(meta, object_or_name, bases, dict)

class NestedBase(metaclass=NestedType):
    pass

<><>>>

class Outer(<note0>):
    class Inner:
        def __init__(self, self_): # I prefer self_ above outer

note0: here can come NestedBase or metaclass=NestedType (and beware of meta mismatch error)

need to know
Outer.Inner return class module.Outer.Inner
Outer().Inner returns bound method
Outer.__dict__[ Inner ] returns bound object _Bound...

note1
imports are not that important, they only change pop-up when using IDE (VScode python extension doesn t recognize it, so it displays it wrongly, but IDLE does)

classes explained
_Bound should not be used

used as a decorator:
UnBound will make old-style binding
class_ same as classmethod
static same as staticmethod

NestedType metaclass to the outer class
NestedBase base to the outer class
only one needed per outer class

note2
inner class that has no decorator UnBound needs to have init that receives <Outer object> as 2nd argument
otherwise will write (see _Bound.__get__.retf.except) and throw TypeError: Inner(?) takes ? arguments

meta mismatch
to see meta mismatch write class M(type): pass, class A(NestedBase): pass, class B(metaclass=M): pass, class C(A, B): pass
solution: create submeta of both metas and, if , call NestedType.bind(dict) (as in NestedType.__new__)
note3: overriding __new__ or NestedMeta not 1st in subclassing order (class NewMeta(NotNestedMeta, NestedMeta) ( here NestedMeta is non-strict submeta of NestedType)

不改动或甚至更改<代码>_init__ 我们可以使用一种内产阶级工厂,简单地增加母子或外部参考。

class Outer(object):
   pass

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

   def InnerFactory (self):
      class Inner(self._Inner):
         outer = self
      return Inner

o = Outer()

Iclass = o.InnerFactory()
i = Iclass()
# or directly
i = o.InnerFactory()()

this approach is of most interest in cases where we cannot change or have no control over the construction or __init__ method





相关问题
Can Django models use MySQL functions?

Is there a way to force Django models to pass a field to a MySQL function every time the model data is read or loaded? To clarify what I mean in SQL, I want the Django model to produce something like ...

An enterprise scheduler for python (like quartz)

I am looking for an enterprise tasks scheduler for python, like quartz is for Java. Requirements: Persistent: if the process restarts or the machine restarts, then all the jobs must stay there and ...

How to remove unique, then duplicate dictionaries in a list?

Given the following list that contains some duplicate and some unique dictionaries, what is the best method to remove unique dictionaries first, then reduce the duplicate dictionaries to single ...

What is suggested seed value to use with random.seed()?

Simple enough question: I m using python random module to generate random integers. I want to know what is the suggested value to use with the random.seed() function? Currently I am letting this ...

How can I make the PyDev editor selectively ignore errors?

I m using PyDev under Eclipse to write some Jython code. I ve got numerous instances where I need to do something like this: import com.work.project.component.client.Interface.ISubInterface as ...

How do I profile `paster serve` s startup time?

Python s paster serve app.ini is taking longer than I would like to be ready for the first request. I know how to profile requests with middleware, but how do I profile the initialization time? I ...

Pragmatically adding give-aways/freebies to an online store

Our business currently has an online store and recently we ve been offering free specials to our customers. Right now, we simply display the special and give the buyer a notice stating we will add the ...

Converting Dictionary to List? [duplicate]

I m trying to convert a Python dictionary into a Python list, in order to perform some calculations. #My dictionary dict = {} dict[ Capital ]="London" dict[ Food ]="Fish&Chips" dict[ 2012 ]="...

热门标签