如何在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")
我正在为方法 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")