考虑以下Python(在2.x或3.x中运行):
class Outer(object):
pass
class Inner(object):
def __init__(self):
print("Inner.self", self)
o = Outer()
i = o.Inner()
Run Code Online (Sandbox Code Playgroud)
我想o在里面亲自动手Inner.__init__().但:
o成为一个明确的参数Inner.O.Inner和o.Inner成为一个类的对象,不是很奇怪像关闭.你能建议我怎么做到这一点吗?
现在我最好的想法是使用线程本地存储.在我的用例中,每当我构造一个时o.Inner(),我已经在o某个地方的某个方法中,并且添加它不是什么大问题
threading.local()["my o object"] = o
Run Code Online (Sandbox Code Playgroud)
到我的代码.
这让您了解我愿意考虑的堕落程度.
Ale*_*lli 19
在Python 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)
Run Code Online (Sandbox Code Playgroud)
这会发出:
<__main__.Outer object at 0x82f90>
Outer is a <type 'type'>
Inner is a <type 'type'>
Run Code Online (Sandbox Code Playgroud)
只是为了证实这一点
o.Inner [[is]]是一个类对象,而不是像闭包那样奇怪的东西
根据你的特殊规格.当然,每次重入都需要一个不同的类 - 即使在单线程世界中,如下:
o1 = Outer()
o2 = Outer()
i1 = o1.Inner
i2 = o2.Inner
print i1(), i2(), i1(), i2()
Run Code Online (Sandbox Code Playgroud)
应该干净利落地工作,并且将o1和o2存放在除了o1.Innervs 返回的类别之外的任何地方o2.Inner(例如,在TLS中)将意味着这种使用的可怕结果.
但你并没有注明" o.Inner必须是完全相同的同一类对象的每个可能o这就是实例Outer",所以这段代码完全满足您的规格确实给;-).
您可以使用元类来实现将内部类绑定到外部类的__get__描述符。并且由于您似乎只对绑定到类感兴趣,请考虑就地修改内部类,这与包装到方法中的函数不同。
>>> 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
Run Code Online (Sandbox Code Playgroud)
如果您更愿意通过子类包装内部类,则将 __get__ 主体替换为:
return type(self.__name__, (self,), {'owner': owner})
Run Code Online (Sandbox Code Playgroud)