2010-07-01 114 views
0

我想要一个具有内部类可以访问外部类的成员的嵌套类的Python类。我明白,正常的嵌套甚至不需要外部类有一个实例。我有一些代码,似乎产生我想要的结果,我想在风格和不可预见的并发症从内部类访问外部类方法

反馈

代码:

class A(): 

    def __init__(self,x): 
     self.x = x 
     self.B = self.classBdef() 

    def classBdef(self): 
     parent = self 

     class B(): 
      def out(self): 
       print parent.x 

     return B 

输出:

>>> a = A(5) 
>>> b = a.B() 
>>> b.out() 
5 
>>> a.x = 7 
>>> b.out() 
7 

所以,A有一个内部类B,它只能从A的实例创建。然后B通过父变量访问A的所有成员。

+0

是否有你需要B的情况下,只能从内部的创建的原因是什么?类继承似乎是实现这一点的一种更简单的方式。 – Wilduck 2010-07-01 19:14:38

回答

2

这对我来说看起来不太好。 classBdef是一种类工厂方法。通常(很少)您会使用这些来创建自定义类,例如一个具有自定义超类的类:

def class_factory(superclass): 
    class CustomClass(superclass): 
     def custom_method(self): 
      pass 
    return CustomClass 

但是,您的构造不使用自定义。事实上,它将A的东西放入B中,并将它们紧密结合在一起。如果B需要知道某个A变量,则使用参数进行方法调用,或通过引用A对象实例化B对象。

除非有某个特定的原因或问题需要解决,否则只需要制定一个正常的工厂方法,在A中给出B对象而不是像b = a.B()这样的东西就会更容易和更清晰。

class B(object): 
    def __init__(self, a): 
     self.a = a 

    def out(self): 
     print self.a.x 

class A(object): 
    def __init__(self,x): 
     self.x = x 

    def create_b(self): 
     return B(self) 

a = A() 
b = a.create_b() 
b.out() 
0

我不认为你想要做的是一个非常好的主意。 python中的“Inner”类与他们的“外层”类完全没有特别的关系,如果你打算在另一个里面定义一个类。它是完全一样的说:

class A(object): 
    class B(object): 
     pass 

,因为它是说:

class B(object): pass 
class A(object): pass 
A.B = B 
del B 

这就是说,它可以做到像你描述,通过使你的“内在”通过在其元类上定义__get__()将类描述成描述符。我建议不要这样做 - 这太复杂了,收益不大。

class ParentBindingType(type): 
    def __get__(cls, inst, instcls): 
     return type(cls.__name__, (cls,), {'parent': inst}) 
    def __repr__(cls): 
     return "<class '%s.%s' parent=%r>" % (cls.__module__, 
      cls.__name__, getattr(cls, 'parent', None)) 

class B(object): 
    __metaclass__ = ParentBindingType 
    def out(self): 
     print self.parent.x 

class A(object): 
    _B = B 
    def __init__(self,x): 
     self.x = x 
     self.B = self._B 

a = A(5) 
print a.B 
b = a.B() 
b.out() 
a.x = 7 
b.out() 

印刷:

<class '__main__.B' parent=<__main__.A object at 0x85c90>> 
5 
7