简体   繁体   中英

How to redefine instance methods in Python?

I am making infrastructure for methods dbg (stands for debug_message), info (stands from info_message) as well as log (logging functionality).

The dbg, info, and log methods will be called whatever the user input, however, they will function differently based on the user input, such as whether the user wants the process to print DEBUG or be fully QUIET as well as whether the user wants to LOG.

I could achieve such functionality as long as I am not using an object to wrap the functionality (for multiplicity reasons). When I wrap it into an object and call it from an object I get AttributeError , that the object has no method.

class Feedbacker(object):
    def __init__(self, task):
        self.LOG = task.LOG
        self.LOG_DIR = task.LOG_DIR
        self.DEBUG = task.DEBUG
        self.QUIET = task.QUIET

        self.timestamp = datetime.now().strftime("%Y-%m-%d_%H%M%S")

        # Logging
        # Based on parameter input. Creates a log file and logs all info output.
        if self.LOG: # If logging parameter was provided -> Initiate logging
            Path(self.LOG_DIR).mkdir(parents=True, exist_ok=True) # Creates directory

            import logging
            logging.basicConfig(format='%(asctime)s %(message)s',\
                handlers=[logging.FileHandler(\
                f"{self.LOG_DIR}/ytr_log_{self.timestamp}.log", 'w', 'utf-8')]) # UTC-8
            logging.logThreads = 0
            logging.logProcesses = 0
            logger=logging.getLogger()
            logger.setLevel(logging.ERROR)
            def log(*args,**kwargs):
                msg = " ".join(args) # Joins all args into one string. " " seperator.
                logger.log(60, msg) # First agr is the log level.

        else: # If logging is not provided, log will still be run, but will do nothing.
            def log(*args,**kwargs):
                pass
        # Debug message handling
        if self.DEBUG:
            def dbg(*args, head = "DEBUG", **kwargs):
                info(*args, head = head, **kwargs)
        else:
            def dbg(self, *args, head = "DEBUG", **kwargs):
                log(f"[{head}]: ", *args, **kwargs)
                pass
        # Quiet execution
        if self.QUIET:
            def info(*args, head = "INFO", **kwargs):
                log(f"[{head}]: ", *args,**kwargs)
        else:
            def info(*args, head = "INFO", **kwargs):
                print(f"[{head}]: ", *args,**kwargs)
                log(f"[{head}]: ", *args,**kwargs)

# Example call, which does not work.
fb = Feedbacker(task)
fb.dbg("Test message")

How can I define dbg method based on instance variables?

Functions are values in python so you can arbitrarily reassign them.

You can do something like this (simplified example):

class Feedbacker(object):
    def __init__(self, switch):
        if switch:
            self.foo = self.bar

    def foo(*args):
        return "something"

    def bar(*args):
        return "something_different"

print(Feedbacker(False).foo()) # something
print(Feedbacker(True).foo()) # something_different

This re-edit of what you had works, I think (limited testing). I had to make a dummy task definition which is certainly different from your original:

from datetime import datetime
from pathlib import Path

class Task:
    LOG = True
    LOG_DIR = 'C:\Temp\Logs'
    DEBUG = True
    QUIET = True

task = Task()

class Feedbacker(object):
    def __init__(self, task):
        self.LOG = task.LOG
        self.LOG_DIR = task.LOG_DIR
        self.DEBUG = task.DEBUG
        self.QUIET = task.QUIET

        self.timestamp = datetime.now().strftime("%Y-%m-%d_%H%M%S")

        # Logging
        # Based on parameter input. Creates a log file and logs all info output.
        if self.LOG: # If logging parameter was provided -> Initiate logging
            Path(self.LOG_DIR).mkdir(parents=True, exist_ok=True) # Creates directory

            import logging
            logging.basicConfig(format='%(asctime)s %(message)s',\
                handlers=[logging.FileHandler(\
                f"{self.LOG_DIR}/ytr_log_{self.timestamp}.log", 'w', 'utf-8')]) # UTC-8
            logging.logThreads = 0
            logging.logProcesses = 0
            self.logger=logging.getLogger()
            self.logger.setLevel(logging.ERROR)
            self.log = self.log_a

        else: # If logging is not provided, log will still be run, but will do nothing.
            self.log = self.log_b

        # Debug message handling
        if self.DEBUG:
            self.dbg = self.dbg_a
        else:
            self.dbg = self.dbg_b

        # Quiet execution
        if self.QUIET:
            self.info = self.info_a
        else:
            self.info = self.info_b

    def log_a(self,*args,**kwargs):
        msg = " ".join(args) # Joins all args into one string. " " seperator.
        self.logger.log(60, msg) # First agr is the log level.

    def log_b(self,*args,**kwargs):
        pass

    def dbg_a(self,*args, head = "DEBUG", **kwargs):
        self.info(*args, head = head, **kwargs)

    def dbg_b(self, *args, head = "DEBUG", **kwargs):
        self.log(f"[{head}]: ", *args, **kwargs)

    def info_a(self,*args, head = "INFO", **kwargs):
        self.log(f"[{head}]: ", *args,**kwargs)

    def info_b(self,*args, head = "INFO", **kwargs):
        print(f"[{head}]: ", *args,**kwargs)
        self.log(f"[{head}]: ", *args,**kwargs)

# Create the logging object and output test message
fb = Feedbacker(task)
fb.dbg("Test message")

After reading your comment, you can see it is far cleaner and simpler to just examine your configuration variables within the various calls:

class Feedbacker(object):
    def __init__(self, task):
        self.LOG = task.LOG
        self.LOG_DIR = task.LOG_DIR
        self.DEBUG = task.DEBUG
        self.QUIET = task.QUIET

        self.timestamp = datetime.now().strftime("%Y-%m-%d_%H%M%S")

        # Logging
        # Based on parameter input. Creates a log file and logs all info output.
        if self.LOG: # If logging parameter was provided -> Initiate logging
            Path(self.LOG_DIR).mkdir(parents=True, exist_ok=True) # Creates directory

            import logging
            logging.basicConfig(format='%(asctime)s %(message)s',
                handlers=[logging.FileHandler(
                f"{self.LOG_DIR}/ytr_log_{self.timestamp}.log", 'w', 'utf-8')]) # UTC-8
            logging.logThreads = 0
            logging.logProcesses = 0
            self.logger=logging.getLogger()
            self.logger.setLevel(logging.ERROR)

    def log(self,*args,**kwargs):
        if self.LOG:
            msg = " ".join(args) # Joins all args into one string. " " seperator.
            self.logger.log(60, msg) # First agr is the log level.

    def dbg(self,*args, head = "DEBUG", **kwargs):
        if self.DEBUG:
            self.info(*args, head = head, **kwargs)
        else:
            self.log(f"[{head}]: ", *args, **kwargs)

    def info(self,*args, head = "INFO", **kwargs):
        if not self.QUIET:
            print(f"[{head}]: ", *args,**kwargs)
        self.log(f"[{head}]: ", *args,**kwargs)

# Sample call
fb = Feedbacker(task)

fb.dbg("Test message")

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM