0

I have a python class that implements a decorator (as classmethod , thank to this post decorator-inside-python-class as following:

import os
from functools import wraps
import pandas as pd

class global_tracking():

    def __init__(self, globals=None):
        self.globals = globals

    def save_current_data_frame_to_track(self,current_data_frame,path_to,filename,logger=None):
        current_data_frame.to_parquet(filename+'.parquet.gzip', compression='gzip')
        os.system('gsutil cp '+filename+'.parquet.gzip'+' gs://'+path_to+filename+'.parquet.gzip')
        return True

    @classmethod
    def save_input_to_track_from_globals(cls,globals):
        def save_input_to_track(func):
            @wraps(func)
            def func_wrapper(*args, **kwargs):
                for key, kwarg in kwargs.items():
                    if isinstance(kwarg, pd.core.frame.DataFrame):
                        self.save_current_data_frame_to_track(kwarg,globals['file_system_path'])
                return func(*args, **kwargs)
            return func_wrapper
        return save_input_to_track

I would like to use this decorator, in another class as following: Python wont let me use the decorator:

globals={'file_system_path':''}

class global_data_getter():

    def __init__(self,globals):
        self.globals=globals

    @global_tracking(globals).save_input_to_track_from_globals(globals) #Python wont recognise this!
    def get_train_data(self,file_name):
        data_to_train = pd.read_csv(file_name)
        return data_to_train

Quick clarification, I want that when ever get_train_data is bing used the function will both read and return the data frame and also save it in google storage, that is why i'm using the decorator.

I would prefer if the decorator would be a member of a class (global tracking) where i save other decorators, that are all intended to keep track of methods.

globals (bad name i know :( ) is just a dict with information on where to store the csv

Why cant i use this decorator ?

Thanks in advance!

9
  • 3
    Some nitpicking: it is customary for classmethods to name the first argument cls, not self. That is because the first argument the method will get when called will be a class object, not an instance object. Commented Apr 17, 2019 at 8:01
  • This code is a bit confused. You have several things all called globals and it's not clear which one you are trying to refer to, or what Python "won't let" you do. It's also not clear why, having made your decorator a classmethod, you instantiate global_tracking anyway when decorating. Commented Apr 17, 2019 at 8:02
  • Could you explain what you are trying to achieve with your code? I think there are much easier ('Pythonic') things you can do. Commented Apr 17, 2019 at 8:11
  • You don’t seem to be following the example in the link you supply. Commented Apr 17, 2019 at 8:13
  • I had a look at the link, and I thoroughly disagree with the argument to put the decorator function inside some contrived inner class. It requires more code than to simply put the decorator outside the class, and more code means more complexity, more maintenance, etc. Keep It Simple, Stupid! As the man said, "The most simple solution you are probably already thinking of is to declare function outside of the class." Always go for the simplest solution. Commented Apr 17, 2019 at 8:26

2 Answers 2

2

Your code mixes-up class objects, instance objects and function objects. You make that error in the definition of the global_tracking function (see my first comment), and when trying to call its return value. The call to global_tracking(globals) returns a function object, not an instance object. The function object returned by the call does not have a member save_input_to_track_from_globals, so you can not call it.

I tried to improve your code, but it is far too contrived and unnecessarily complex. Just stick with a simple decorator function. The link you provide was showing some theoretical possibilities with the Python syntax, not something you would actually use in real life.

Sign up to request clarification or add additional context in comments.

4 Comments

Hmm I think thatglobal_tracking(global) returns an instance not a function.
@quamrana: it certainly does not. A the call to global_tracking(global) returns the function save_input_to_track. It is an object, as all things in Python, but a function object, not an instance object. I have edited my answer to make the distinction clearer.
@EvertW thanks , you are right, changing to @global_tracking.save_input_to_track_from_globals(globals) solved it! can you just edit the answer?
@quamrana: The easiest way to resolve such questions is to try them in the interpreter interactively. That way you can query the returned object's type to determine whether your assertion is correct.
1

The decorator syntax has been deliberately kept restrictive to save you from having to maintain problematic code such as this. If you insist on this level of complexity you could assign the appropriate decorator in the class namespace so you can use a simple name, which would give you acceptable syntax.

I would be interested in the justification for using a classmethod in the first place.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.