Replacing conditional conditions in Python with polymorphism

I recently read a snippet of an article / code that shows an example of replacing conventions with polymorphism. Here is the code:

Before:

def log_msg(log_type):
    msg = 'Operation successful'
    if  log_type == 'file':
        log_file.write(msg)
    elif log_type == 'database':
        cursor.execute('INSERT INTO log_table (MSG) VALUES ('?')', msg)

After:

class FileLogger(object):
    def log(self, msg):
        log_file.write(msg)

class DbLogger(object):
    def log(self, msg):
        cursor.execute('INSERT INTO log_table (MSG) VALUES ('?')', msg)

def log_msg(obj):
    msg = 'Operation successful'
    obj.log(msg)

Here , where I got it from.

My question now is that the essential method is the second method better than the first? As far as I know, if I want to use the second method, I have to do something like this every time I want to write something:

if log_type == 'file':
    log_msg(FileLogger())
elif: log_type == 'database':
    log_msg(DbLogger())

Am I missing a point or is something very obvious?

+4
source share
2 answers

, , , - . , log_msg(myLogger), , , db.

, :

# beginning of file
from logmodule import FileLogger, DBLogger, log_msg
myLogger = FileLogger()

# lots of other code here. . .
# later if you want to log something:

log_msg(myLogger)

myLogger = DBLogger(), . , , , , , .

, ( ) - ; , . -, . , , - , .

+1

Replace Conditional with Polymorphism , . , . - , , OO .


, .

if log_type == "file":
    log_file.write("DEBUG: beginning script")
elif log_type == "database":
    cursor.execute("INSERT INTO log_table (Level, Msg) VALUES ('DEBUG', 'beginning script')")

try:
    file = open("/path/to/file")
    lines = file.readlines()

    if log_type == "file":
        log_file.write("INFO: read {} lines".format(len(lines)))
    elif log_type == "database":
        cursor.execute("INSERT INTO log_table (Level, Msg) VALUES ('INFO', 'read {} lines')".format(len(lines)))
except:
    if log_type == "file":
        log_file.write("ERROR: failed to read file")
    elif log_type == "database":
        cursor.execute("INSERT INTO log_table (Level, Msg) VALUES ('ERROR', 'failed to read file')")

    raise
finally:
    if log_type == "file":
        log_file.write("INFO: closing file")
    elif log_type == "database":
        cursor.execute("INSERT INTO log_table (Level, Msg) VALUES ('INFO', 'closing file')")
    file.close()

, , , , - . , , , script elif , .

, script, .


, . :

class AbstractLogger:
    def debug(self, msg):
        self.log("DEBUG", msg)

    def info(self, msg):
        self.log("INFO", msg)

    def error(self, msg):
        self.log("ERROR", msg)

    def log(self, level, msg):
        raise NotImplementedError()

class FileLogger(AbstractLogger):
    def __init__(self, file):
        self.file = file

    def log(self, level, msg):
        self.file.write("{}: {}".format(level, msg))

class DatabaseLogger(AbstractLogger):
    def __init__(self, cursor):
        self.cursor = cursor

    def log(self, level, msg):
        self.cursor.execute("INSERT INTO log_table (Level, Msg) VALUES ('{}', '{}')".format(level, msg))

, FileLogger DatabaseLogger.

script:

# create the logger once at the start
if log_type == "file":
    logger = FileLogger(log_file)
elif log_type == "database":
    logger = DatabaseLogger(cursor)

logger.debug("beginning script")

try:
    file = open("/path/to/file")
    lines = file.readlines()

    logger.info("read {} lines".format(len(lines)))
except:
    logger.error("failed to read file")
    raise
finally:
    logger.info("closing file")
    file.close()

: EmailLogger , . : , , .

+4

Source: https://habr.com/ru/post/1546733/


All Articles