简体   繁体   中英

Python function does not update attributes

I am writing a class called 'Message' which takes a string 'message' in its constructor function. It basically encodes and decodes the message with some algorithms. Very basic and beginner stuff. The class is as follows: (It is a very long one.)

class Message:
def __init__(self, message: str) -> None:
    self.message: str = message.strip()
    self.__displacement: int = 0
    self.__info: dict[Any, Any] = {
        "Encoded": False, "Algorithms": (), "Caesar_shift": "NONE"}

def __str__(self) -> str:
    return self.message

def __repr__(self) -> str:
    return self.message

_enc_types: list[str] = ["None", "CAESAR", "MORSE"]

_enc_funcs: dict[str, Any] = {
    "CAESAR": lambda message, *args: Message(message)._caesar_encode(*args),
    "MORSE": lambda message: Message(message)._morse_encode()
}

_dec_funcs: dict[str, Any] = {
    "CAESAR": lambda message: Message(message)._caesar_decode(),
    "MORSE": lambda message: Message(message)._morse_decode()
}

@staticmethod
def __modify_val(value: int, shift: str, mag: int) -> int:
    if shift == "LEFT":
        value -= mag
        if value < 0:
            value += 27
    elif shift == "RIGHT":
        value += mag
        if value > 26:
            value -= 27
    else:
        raise ValueError(
            f"Argument '{shift}' for parameter 'shift' is not allowed.")

    return value

def __displace(self, shift: str, mag: int) -> None:
    if shift.upper() == "RIGHT":
        self.__displacement += mag
    else:
        self.__displacement -= mag

    eval_dict: dict[bool, str] = {
        True: "LEFT",
        False: "RIGHT"
    }

    if self.__displacement != 0:
        self.__info["Caesar_shift"] = eval_dict.get(
            (self.__displacement < 0), "NONE")

def _caesar_encode(self, shift: str, mag: int) -> str:
    mag -= 1

    with open("F:\Practice_Python\jsons\caesar.json", "r") as file:
        dict_list = json.load(file)
        letter_dict: dict[str, int] = dict_list[0]
        num_dict: dict[str, str] = dict_list[1]

    self.message = ''.join([num_dict.get(str(self.__modify_val(letter_dict.get(
        letter, -1), shift, mag)), "?") for letter in self.message.lower()])

    self.__displace(shift, mag)
    return self.message

def _caesar_decode(self) -> None:
    if (not self.__info["Encoded"]) and (self.__info["Algorithms"][-1] != "Caesar"):
        raise EncodingError(
            "Given message is not encoded by allowed algorithms.")
    shift: str = self.__info["Caesar_shift"]
    mag: int = self.__displacement + 1

    if shift == "RIGHT":
        shift = "LEFT"
        self._caesar_encode(shift, mag)
        self.__displace(shift, mag)
    elif shift == "LEFT":
        shift = "RIGHT"
        self._caesar_encode(shift, mag)
        self.__displace(shift, mag)
    else:
        raise EncodingError(
            "Given message is not encoded by allowed algorithms.")

def _morse_encode(self) -> None:
    with open("F:\Practice_Python\jsons\morse.json", "r") as file:
        dict_morse: dict[str, str] = json.load(file)

    self.message = "".join(
        [dict_morse.get(char, char) + '   ' for char in self.message.lower()])

def _morse_decode(self) -> None:
    with open('F:\Practice_Python\jsons\morse.json', 'r') as file:
        dict_morse: dict[str, str] = json.load(file)
        dict_decode: dict[str, str] = {
            value: key for key, value in dict_morse.items()}

    self.message = ''

    for sub1 in self.message.lower().split('       '):
        for sub2 in sub1.split('   '):
            self.message += dict_decode.get(sub2, '?')
        self.message += ' '

def __update_encoded(self, type: str) -> None:
    self.__info["Encoded"] = True

    self.__info["Algorithms"] = list(self.__info["Algorithms"])
    self.__info["Algorithms"].append(type)
    self.__info["Algorithms"] = tuple(self.__info["Algorithms"])

def __update_decoded(self) -> None:
    self.__info["Algorithms"] = list(self.__info["Algorithms"])
    del self.__info["Algorithms"][-1]
    self.__info["Algorithms"] = tuple(self.__info["Algorithms"])

    if len(self.__info["Algorithms"]) == 0:
        self.__info["Encoded"] = False

def encode(self, type: str, *args):

    type = type.upper().strip()

    if type not in self._enc_types:
        raise EncodingError(
            "Given algorithm for encoding message is not present.")
    self._enc_funcs.get(type, type)(self.message, *args)

    self.__update_encoded(type)

def decode(self):
    type: str = self.__info["Algorithms"][-1]

    self._dec_funcs.get(type, type)()

    self.__update_decoded(type)

Sorry if it is poorly written. But the encode function when called does not behave properly. Expected:

>>> message = Message('Hello')
>>> message.encode('CAESAR', 'RIGHT', 4)
>>> print(message)
khoor

Actual:

>>> message = Message('Hello')
>>> message.encode('CAESAR', 'RIGHT', 4)
>>> print(message)
Hello

So, it does not change the attribute to the desired value. But the function does it properly. It is probably the encode function's fault. I cannot find the problem. Please help and guide me. Thank you. And again sorry for the messy code.

_enc_funcs: dict[str, Any] = {
    "CAESAR": lambda message, *args: Message(message)._caesar_encode(*args),
    "MORSE": lambda message: Message(message)._morse_encode()
}

These lambda functions create a new Message object (which is then discarded); they do not encode the current Message object.

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