Should I decorate the function?

Trying to determine if you should try to use a decorator or some other Pythonic method to shorten the code that performs many of my functions. I would like these functions to be able to call only one function at the beginning of each function or to somehow "decorate" the beginning of each function. I have never used a decorator before and am struggling to implement this decorating idea in a pythonic way to reduce the overall set of access code for each function.

I have many functions that will perform the same set of steps at the beginning of a function. However, there are some structural problems of common code that make this decorator idea difficult:

  • All functions are in the child class of the parent class.

  • General commands between function reference names that are function specific (but a subset of the function name).

  • General commands must return to the caller and not perform any more child functions if a certain condition is met. (block "if jobj:" in the sample code)

For examples with variables / attributes, the child function get_nas_server (self) will use the variable variables "nas_server" in the general set of code. Subtracting get_ from the function name shows the base of the variable name that will be used in the general set of code. Examples of variable names and attributes of objects obtained from the function name "get_nas_server":

nas_server
nas_server.json
self.nas_server (attribute)

Here is the generic code from one of the functions:

#################################################################### def get_nas_server(self): #################################################################### """\nGets COMMAND nas_server and places data into self.nas_server""" try: self.nas_server return self.nas_server except AttributeError: pass self.get_file_cmd('nas_server') jobj = self.fresh_json('nas_server.json') if jobj : self.nas_server = jobj return self.nas_server self.get_file_cmd('get_nas_server') 

Anything below the above code in a function is specific to the purpose of the function and is not suitable for discussion here. Basically, I am trying to make all of this code higher than reusable in my functions, but the code should have variables and attribute changed depending on the name of the function.

Thank you for reading, if you succeeded, and thanks for the help.

+5
source share
3 answers

It looks like you can define as a helper method in the parent class:

 class Parent(object): def _get_something(name): try: return getattr(self, name) except AttributeError: pass self.get_file_cmd(name) jobj = self.fresh_json(name+'.json') if jobj : setattr(self, name, jobj) return jobj self.get_file_cmd('get_'+name) 

As this snippet shows, you can use getattr() , setattr() and hasattr() to refer to the attributes of an object by name.

+2
source

You can use the decorator inside your class if the source material for accounting is too specific for this class. Each time you need to perform this initial check inside a class method, you can simply decorate it with the auto_nas decorator, which I added below. The volume of this shell, I believe, is specific only to this class. Otherwise, you can move it outside the class for generality, but be sure to change (self=None) if you do.

 class YourMainClass(): # This is your main class inside which all the methods are defined. def auto_nas(func): # This wrapper function will be called instead of your class methods. def wrap(self): # All your bookkeeping stuff goes here. try: self.nas_server return self.nas_server except AttributeError: pass self.get_file_cmd('nas_server') jobj = self.fresh_json('nas_server.json') if jobj : self.nas_server = jobj return self.nas_server self.get_file_cmd('get_nas_server') # Things went well - we shall call the actual method. return func(self) return wrap @auto_nas def get_nas_server(self): # This is one of your methods that require bookkeeping pass 

Also note the self inside the wrapper function. It is automatically passed as a Python argument, and so you can access all the attributes of the instance from within this decorator. Once again, this is suitable if your decorator needs to perform tasks specific to each instance of your class. If this is not the case, you can simply put all this code in a function and call it every time you want.

+1
source

Many thanks to Augurar for pointing in the right direction. I ended up creating a stub method in the parent class. You just need to call the method with the proper technique to "extend" the parent method. Then calling this method stubs from the child class using super (). Should there be a proper name for this technique? method overrides? Is the method expanding?

Here is the parent class method, mainly as Augurer suggested:

 ########################################################################### def get_stub(self,fcmd): ########################################################################### try: return getattr(self, fcmd) except AttributeError: pass jobj = self.fresh_json(fcmd + '.json') if jobj : setattr(self, fcmd, jobj) return jobj if not self.get_file_cmd(fcmd): self.log.error("{} not found".format(fcmd)) return False 

Here is the way the child method uses this parent method:

 #################################################################### def get_nas_server(self): #################################################################### super().get_stub('nas_server') #bunch of child method specific code below here 
0
source

All Articles