14

I'm writing Python scripts for Blender for a project, but I'm pretty new to the language. Something I am confused about is the usage of static variables. Here is the piece of code I am currently working on:

class panelToggle(bpy.types.Operator):
    active = False

    def invoke(self, context, event):
        self.active = not self.active
        return{'FINISHED'}

class OBJECT_OT_openConstraintPanel(panelToggle):
    bl_label = "openConstraintPanel"
    bl_idname = "openConstraintPanel"

The idea is that the second class should inherit the active variable and the invoke method from the first, so that calling OBJECT_OT_openConstraintPanel.invoke() changes OBJECT_OT_openConstraintPanel.active. Using self as I did above won't work however, and neither does using panelToggle instead. Any idea of how I go about this?

gibberish
  • 145
  • 1
  • 2
  • 6
  • Okay, it seems I can use self.__class__.active or type(self).active to let the method inherit properly. Thanks! – gibberish Aug 13 '10 at 09:52
  • Why are you using static variables in the first place? That doesn't seem sensible. Is this `active` attribute some kind of global, shared among all `PanelToggle` instances? If so, why isn't it actually global? Or why isn't in some more global shared object? – S.Lott Aug 13 '10 at 10:09
  • I want each panelToggle subclass to have its own "active" variable that can be accessed without creating an instance. If I understand the use of the "global" keyword correctly, I'd have to insert a 'global active' line first in 'invoke(..)' before just using active like a local variable. Doing this gives an error saying the global name 'active' is not defined. I'm not sure I understand what's wrong with my approach, however. – gibberish Aug 13 '10 at 11:17
  • Why class-level? Clearly you want each subclass to have a variable. Why is it at the class level? That's what makes little sense. Why isn't this an ordinary instance variable? – S.Lott Aug 13 '10 at 15:45

2 Answers2

22

use type(self) for access to class attributes

>>> class A(object):
 var  = 2
 def write(self):
   print(type(self).var)
>>> class B(A):
 pass
>>> B().write()
2
>>> B.var = 3
>>> B().write()
3
>>> A().write()
2

UPDATE

for a classmethod is event easier, and most natural

class A(object):
     var  = 2
     @classmethod
     def write(cls):
       print(cls.var)

and a staticmethod should not depend on the instance type, so such form of dispatch is possible here

Odomontois
  • 15,918
  • 2
  • 36
  • 71
  • 4
    is `type(self)` in any way different from using `self.__class__`? – jorelli May 02 '11 at 22:19
  • 3
    It is not at the moment. But some features can be implemented later. Also you can do some monkey patch to type function. – Odomontois May 03 '11 at 19:47
  • I'm using Python 3.8.5 and I noticed a difference: I could not modify type(self).var from inside an instance method of the class. I had to use self.__class__.var in order to be able to modify it within an instance method. Not sure why? – mattyb Dec 03 '20 at 19:43
  • is there a way to accomplish this if `write` were a static method? – ekkis Dec 22 '22 at 02:33
  • @ekkis updated an answer a little bit – Odomontois Jun 02 '23 at 09:54
4

You can access active through the class it belongs to:

if panelToggle.active:
    # do something

If you want to access the class variable from a method, you could write:

def am_i_active(self):
    """ This method will access the right *class* variable by
        looking at its own class type first.
    """
    if self.__class__.active:
        print 'Yes, sir!'
    else:
        print 'Nope.'

A working example can be found here: http://gist.github.com/522619


The self variable (named self by convention) is the current instance of the class, implicitly passed but explicitely recieved.

class A(object):

    answer = 42

    def add(self, a, b):
        """ ``self`` is received explicitely. """
        return A.answer + a + b

a = A()

print a.add(1, 2) # ``The instance -- ``a`` -- is passed implicitely.``
# => 45

print a.answer 
# => print 42
miku
  • 181,842
  • 47
  • 306
  • 310
  • Yes, but I want to be able to do the same with OBJECT_OT_openConstraintPanel. I want it to have its own static "active" variable, inherited from panelToggle. I also want to make the "invoke" method work in the subclass (access its own "active" variable instead of its parent's) – gibberish Aug 13 '10 at 09:29
  • Edited my post and added sample code in http://gist.github.com/522619, hope it helps. – miku Aug 13 '10 at 09:44