开发者

Python access attributes of an enclosing class (not parent)

I have a simple problem, I'm developing something for which I need to have some classes accessing some common variables like that:

somevar="foo"

class A(SomeParent):
  def eval_class(self):
     global somevar
     return somevar

def index(request,input_somevar):
  global somevar
  somevar=in开发者_如何学运维put_somevar
  return HttpResponse(A().eval_class())

Problem: That code runs on django so, every request the code will be still running and the somevar will reiceve a new value. If requests happen to overlap I'll enp up having values of somevar for one request which are set by another request.

Solution? What came to my mind was to use instances of a single class.

Class Parent:
  somevar=None
  def set_somevar(self,somevar):
    self.somevar=somevar

  class A(SomeParent): #Note: the parent of this class is NOT "Parent".
    def eval_class(self):
      #Here I would like to retrieve somehow "somevar"
      return somevar

def index(request,input_somevar):
  p=Parent()
  p.set_somevar(input_somevar)
  return HttpResponse(p.A().eval_class())

NOTE: I cannot pass variables to the classes, they have to be able to access to the "enclosing but not parent class" as they are sympy's Function classes which need to be passed to the sympy interpreter.

Thank you in advance!


Basically you say that different threads of your Django app have an access conflict: while one of them is reading the value of somevar, another is modifying it.

So you seem to be solving a wrong problem. Really you need to design your application in a way that access conflicts do not happen.

An ideal solution would be having no shared state at all. Use threading.local to store data accessible to only one (current) thread. You will have to sort out affinity issues, though: if one request goes to this thread and the next request of the same client, minutes later, goes to another thread, it will not see the data set by the previous request.

Another solution would be using a database to serialize the changes. Take SQLite, it's almost weightless and supports transactions. One change locks the somevar record for update, and another transaction that would change it will fail. You'll have to sort this out, again, in a meaningful manner.

It would help if you described the bigger problem you're solving.


Why not just pass input_somevar to the classes that need it?

class A(SomeParent):
    def eval_class(self, somevar):
        return somevar

def index(request,input_somevar):
    return HttpResponse(A().eval_class(input_somevar))

If your view calls other classes, pass it to those too if they need it.


Unlike in java, nested classes are not linked to instances of the outer class. It just changes the namespace in which the class is available. That means p.a is the same thing as Parent.A.

As Brian said, the simplest thing to do might be to just pass the variables you need from your view.


with set_somvevar() you are setting the value of the attribute of the instance p, while the somevar global remains unchanged. Thus, p.A().eval_class() will always return None (the original value).

edit: with the global somevar defined as a class attribute instead of an instance attribute, setting this attribute will not solve your problem: you still get the latest set value of this class attribute, assuming you meant with eval_class to return P().somevar.

What about making the Parent-instance a variable to the A-init function?

class Parent:
    def __init__(self, somevar):
        self.somevar = somevar

    class A(SomeParent):
        def __init__(self, parent):
            SomeParent.__init__(self)
            self.parent = parent

        def eval_class(self):
            return self.parent.somevar

def index(request,input_somevar):
  p = Parent(input_somevar)
  return HttpResponse(p.A(p).eval_class())
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜