如何在Python中重新定义实例方法?

How to redefine instance methods in Python?

我正在为方法 dbg(代表 debug_message)、信息(代表 info_message)以及日志(记录功能)构建基础结构。

无论用户输入什么,dbg、info 和 log 方法都会被调用,但是,它们的功能会根据用户输入而有所不同,例如用户是希望进程打印 DEBUG 还是完全 QUIET比如用户是否要登录。

我可以实现这样的功能,只要我不使用对象来包装功能(出于多重原因)。当我将它包装到一个对象中并从一个对象调用它时,我得到 AttributeError,该对象没有方法。

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")

如何根据实例变量定义 dbg 方法?

函数是 python 中的值,因此您可以任意重新分配它们。

您可以这样做(简化示例):

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

我认为对您的作品进行重新编辑(有限测试)。我不得不做一个虚拟任务定义,它肯定与你原来的不同:

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")

阅读您的评论后,您会发现在各种调用中检查您的配置变量要干净和简单得多:

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")