Access Class B's function inside Class A?
-
Hi,
Is there a way I can access Class A's function inside Class B?
My case scenario is Class A is a treeview layout. Class B is the main GeDialog.
You can see it here: https://www.dropbox.com/s/zua8k8xi8zw05g6/c4d263_access_class_a_function_inside_class_b.jpg?dl=0I want Class B's
refresh_layoutfunction to trigger when I changed a variable in the treeview layout specifically the global variablefolder. Is this possible?A mock code would be something like this
class A(c4d.gui.TreeViewFunction): def Select(self, root, userdata, obj, mode): if mode == c4d.SELECTION_NEW: for node in self.node_list : node.selected = False if node == obj: node.selected = True folder = obj.name # Trigger Class B's refresh layout() function class B (gui.GeDialog): def InitValues(): global folder def refresh_layout(): # refreshes Class B's layoutThe other alternative would be to make the
refresh_layoutfunction live outside the class but since the function has already a lot of variables usingClass B, I want it to be insideClass Btoo.Is this possible?
-
Not in the way you may imagine it, but yes.
For a class function to be called, you need an object to call it on (
self). Since many classes may have functions of the same name, it is necessary to know what class you're even addressing here.
For example,x.doSomething()andy.doSomething()may call totally different functionsdoSomethingbecause x and y belong to different classes, each with its own definition ofdoSomething.
That means, to callrefresh_layout()you need to have an object to invoke it on. Like,thatDialog.refresh_layout().So, what you need to do is to pass the dialog object of
class Btoclass Ain some way. Then, class A can invoke the refresh by just calling the function on that object. You normally pass such connecting objects in the init function of the class A (but that's really a design question that I can't answer for you).(To cover all cases: it is possible to define functions that do not have a self parameter; read up on your Python class definitions for that... it doesn't apply for your case here, since a refresh wll need the dialog object anyway.)
-
Hi,
everything is an object in Python, which is leaves you with many options to do what you want. Here are two of the more popular variants.
class Item(object): """A type to invoke some_function on. """ def __init__(self, name): self._name = name def __repr__(self): return self._name def some_function(self, *args, **kwargs): """ """ msg = "{} has been invoked with the args: {} and the kwargs: {}." print msg.format(self.some_function, args, kwargs) class Invoker(object): """Invokes an anonymous callable by binding that callable. """ def __init__(self, func): self._callable = func def invoke(self, *args, **kwargs): """Invoke the stuff we want to invoke. """ print "\nInvoking callable." # We are invoking an anonymous function that has been bound # to the class. We are not really aware that this is actually # a method. This could also be a function, a lambda, everything # that is callable. self._callable(*args, **kwargs) class AlsoInvoker(object): """Invokes a specific method by binding objects and calling the class implementation on them. """ def __init__(self, objects): self._objects = objects def invoke(self, *args, **kwargs): """Invoke the stuff we want to invoke. """ print "\nInvoking class implementation." for obj in self._objects: # We are calling the class object for a known method and # are just filling in the "self" part of the call (obj). Item.some_function(obj, *args, **kwargs) # Some Items with methods we want to invoke. a, b = Item("a"), Item("b") # Option A: bind the instance of a function object directly. invoker = Invoker(func=a.some_function) invoker.invoke(42, pi_equals_e=True) # Option B: bind instances of an object and then call the implementation of # a method on the class object with these objects. invoker = AlsoInvoker(objects=[a, b]) invoker.invoke("bob is your uncle", pi=3, e=3)Invoking callable. <bound method Item.some_function of a> has been invoked with the args: (42,) and the kwargs: {'pi_equals_e': True}. Invoking class implementation. <bound method Item.some_function of a> has been invoked with the args: ('bob is your uncle',) and the kwargs: {'pi': 3, 'e': 3}. <bound method Item.some_function of b> has been invoked with the args: ('bob is your uncle',) and the kwargs: {'pi': 3, 'e': 3}. [Finished in 0.1s]Cheers,
zipit -
Another solution, in your specific scenario, where you don't really need to access a method but want to trigger the
GeDialogin some way, is to message the dialog as discussed here.In short: your treeview sends a message, and the dialog reacts to the message by performing the refresh layout.
-