Приватные переменные в функции Python
Я написал код для шифрования и дешифрования строки кодом Вернама. Код прекрасно работает и преобразует строку в зашифрованную и наоборот. Но есть маленькая проблема, по сколько основные переменные сделаны приватными, я не могу добавить их в качестве стандартных параметров в функции, как это сделать? (пример ниже)
Код программы:
import string
import random
class Cipher:
__encryption_key = ""
__user_data = ""
@staticmethod
def add_string(user_data) -> None:
Cipher.__user_data = user_data
@staticmethod
def clear_user_data():
del Cipher.__user_data
@staticmethod
def generate_encryption_key(length_key=32) -> str:
Cipher.__encryption_key = "".join("".join(random.choices(string.ascii_letters, k=length_key)))
return Cipher.__encryption_key
@staticmethod
def clear_encryption_key():
del Cipher.__encryption_key
@staticmethod
def encrypt_user_string() -> str:
encrypt_user_string = "".join(chr(ord(p) ^ ord(k)) for p, k in zip(Cipher.__user_data,
Cipher.__encryption_key))
return encrypt_user_string
@staticmethod
def decrypt_user_string(encryption_data: str, encryption_key: str) -> str:
decrypt_user_string = "".join(chr(ord(c) ^ ord(k)) for c, k in zip(encryption_data, encryption_key))
return decrypt_user_string
Сейчас вот так:
@staticmethod
def decrypt_user_string(encryption_data: str, encryption_key: str) -> str:
decrypt_user_string = "".join(chr(ord(c) ^ ord(k)) for c, k in zip(encryption_data, encryption_key))
return decrypt_user_string
Требуется что-то типа такого:
@staticmethod
def decrypt_user_string(encryption_data=encrypt_user_string(), encryption_key: Cipher.__encryption_key) -> str:
decrypt_user_string = "".join(chr(ord(c) ^ ord(k)) for c, k in zip(encryption_data, encryption_key))
Как это сделать? Код для проверки работы программы:
from vernam_cipher import Cipher
if __name__ == "__main__":
user_data = "Привет, мир!"
cipher = Cipher()
encryption_key = cipher.generate_encryption_key()
print(f"Ключ шифрования данных: {encryption_key}")
cipher.add_string(user_data)
print(f"Данные: {cipher._Cipher__user_data}")
encrypt_user_string = cipher.encrypt_user_string()
print(f"Зашифрованные данные: {encrypt_user_string}")
decrypt_user_string = cipher.decrypt_user_string(encrypt_user_string, encryption_key)
print(f"Расшифрованные данные: {decrypt_user_string}")
return decrypt_user_string
Ответы (1 шт):
Ваш код кажется несколько странным.
Если у вас создаётся объект класса, то логично использовать методы, привязанные к объекту (нестатические), и сделать код более объектно-ориентированным.
Я бы посоветовал вам: избавится от статических методов, сделать приватные атрибуты более доступными через Property\Дескрипторы
и работать с объектом класса, а не через статические вызовы. Или вообще всё решить на уровне модуля, не создавая класс вообще.
К тому же, у вас ключ всегда имеет фиксированную длину в 32 символа (само по себе это не проблема, но..). И вы не проверяете, что данные короче или длиннее ключа. Отсюда проблема - если строка длиннее 32 символов, лишние символы просто не будут зашифрованы. Как по мне, это нелогично.
Через класс:
import string
import random
class Cipher:
def __init__(self, user_data=""):
self.__encryption_key = ""
self.__user_data = user_data
self.__encrypted_data = ""
@property
def user_data(self):
if not self.__user_data:
return "Данных нет"
return self.__user_data
@user_data.setter
def user_data(self, value):
self.__user_data = value
@property
def encryption_key(self):
if not self.__encryption_key:
return "Ключ шифрования не был сгенерирован."
return self.__encryption_key
@property
def encrypted_data(self):
if not self.__encrypted_data:
return "Зашифрованных данных нет."
return self.__encrypted_data
def generate_encryption_key(self, length_key=32) -> str:
self.__encryption_key = "".join(random.choices(string.ascii_letters, k=length_key))
return self.__encryption_key
def encrypt_user_string(self) -> str:
if not self.__encryption_key:
raise ValueError("Ключ шифрования не был сгенерирован.")
if not self.__user_data:
raise ValueError("Нет данных для шифрования.")
extended_key = (self.__encryption_key * (len(self.__user_data) // len(self.__encryption_key) + 1))[:len(self.__user_data)]
self.__encrypted_data = "".join(chr(ord(p) ^ ord(k)) for p, k in zip(self.__user_data, extended_key))
return self.__encrypted_data
def decrypt_user_string(self) -> str:
if not self.__encrypted_data:
raise ValueError("Нет данных для расшифровки.")
if not self.__encryption_key:
raise ValueError("Ключ шифрования не был сгенерирован.")
extended_key = (self.__encryption_key * (len(self.__encrypted_data) // len(self.__encryption_key) + 1))[:len(self.__encrypted_data)]
return "".join(chr(ord(c) ^ ord(k)) for c, k in zip(self.__encrypted_data, extended_key))
if __name__ == "__main__":
user_data = "Привет, мир! Длинная строка для шифрования. Длинная строка для шифрования. Длинная строка для шифрования. Длинна > 32"
cipher = Cipher()
print(cipher.user_data)
print(cipher.encryption_key)
print(cipher.encrypted_data)
cipher.user_data = user_data
print(f"Данные: {cipher.user_data}")
encryption_key = cipher.generate_encryption_key()
print(f"Ключ шифрования данных: {encryption_key}")
print(f"Ключ: {cipher.encryption_key}")
encrypted_data = cipher.encrypt_user_string()
print(f"Зашифрованные данные: {encrypted_data}")
print(f"Зашифрованные: {cipher.encrypted_data}")
decrypted_data = cipher.decrypt_user_string()
print(f"Расшифрованные данные: {decrypted_data}")
Вывод:
Данных нет
Ключ шифрования не был сгенерирован.
Зашифрованных данных нет.
Данные: Привет, мир! Длинная строка для шифрования. Длинная строка для шифрования. Длинная строка для шифрования. Длинна > 32
Ключ шифрования данных: CTLhjjBALdqkMaqBOEpUqmsPVpzfJrUX
Ключ: CTLhjjBALdqkMaqBOEpUqmsPVpzfJrUX
Зашифрованные данные: ќДѴњџШnaѰќбJmѵъѺѲѸрКQЬбАѨъъFѾщКxЋѬЈШєјѲѼѴЫ_KљњщѿѲѵпuаЯгѮѬрZђѱнuАѻАЌіјњѿѹЃJQѿѶљьѿѿЊPДгЭэѪѦPюѝЅRНѠЇДѲњњїѺЎbDѥѐѵќьѲo{PfC
Зашифрованные: ќДѴњџШnaѰќбJmѵъѺѲѸрКQЬбАѨъъFѾщКxЋѬЈШєјѲѼѴЫ_KљњщѿѲѵпuаЯгѮѬрZђѱнuАѻАЌіјњѿѹЃJQѿѶљьѿѿЊPДгЭэѪѦPюѝЅRНѠЇДѲњњїѺЎbDѥѐѵќьѲo{PfC
Расшифрованные данные: Привет, мир! Длинная строка для шифрования. Длинная строка для шифрования. Длинная строка для шифрования. Длинна > 32
На уровне модуля:
import string
import random
def generate_encryption_key(length_key=32) -> str:
return "".join(random.choices(string.ascii_letters, k=length_key))
def encrypt_string(user_data: str, encryption_key: str) -> str:
if not encryption_key:
raise ValueError("Ключ шифрования не был передан.")
if not user_data:
raise ValueError("Нет данных для шифрования.")
extended_key = (encryption_key * (len(user_data) // len(encryption_key) + 1))[:len(user_data)]
return "".join(chr(ord(p) ^ ord(k)) for p, k in zip(user_data, extended_key))
def decrypt_string(encrypted_data: str, encryption_key: str) -> str:
if not encrypted_data:
raise ValueError("Нет данных для расшифровки.")
if not encryption_key:
raise ValueError("Ключ шифрования не был передан.")
extended_key = (encryption_key * (len(encrypted_data) // len(encryption_key) + 1))[:len(encrypted_data)]
return "".join(chr(ord(c) ^ ord(k)) for c, k in zip(encrypted_data, extended_key))
if __name__ == "__main__":
user_data = "Привет, мир! Длинная строка для шифрования. Длинная строка для шифрования. Длинная строка для шифрования. Длинна > 32"
encryption_key = generate_encryption_key()
print(f"Ключ шифрования данных: {encryption_key}")
encrypted_data = encrypt_string(user_data, encryption_key)
print(f"Зашифрованные данные: {encrypted_data}")
decrypted_data = decrypt_string(encrypted_data, encryption_key)
print(f"Расшифрованные данные: {decrypted_data}")
Вывод:
Ключ шифрования данных: VxWnsvSsPzbPhxcIZytTQXTKAeMqgzll
Зашифрованные данные: щиѯќцдSѬтТqHѬјѱѧффЛqЙЖЋѿџѽQѓсУLОрГЮэфѣюѨеLpѼућѴѧщлtАКДѵѻѕmхќеLФѮмЗѐсцѮыПTBфѓрўѴѪжTЕГИѪѱѱEѹъШZФєВиѩќуыѫм~ZѶѫѐхўѹzGTgc
Расшифрованные данные: Привет, мир! Длинная строка для шифрования. Длинная строка для шифрования. Длинная строка для шифрования. Длинна > 32
Всё же если хочется сделать через класс, но при этом создание объекта не предполагается, то вместо @staticmethod
лучше использовать @classmethod
(так мы ЯВНО сохраним доступ к атрибутам-класса), а доступ к приватным атрибутам получать через геттеры и сеттеры:
import string
import random
class Cipher:
__encryption_key = ""
__encrypted_data = ""
def __new__(cls):
raise TypeError("Как вариант, можно запретить создание экземпляра класса Cipher")
@classmethod
def generate_encryption_key(cls, length_key=32) -> str:
cls.__encryption_key = "".join(random.choices(string.ascii_letters, k=length_key))
return cls.__encryption_key
@classmethod
def set_encrypted_data(cls, data: str):
cls.__encrypted_data = data
@classmethod
def get_encryption_key(cls) -> str:
return cls.__encryption_key
@classmethod
def get_encrypted_data(cls) -> str:
return cls.__encrypted_data
@classmethod
def encrypt_string(cls, user_data: str) -> str:
if not cls.__encryption_key:
raise ValueError("Ключ шифрования не был сгенерирован.")
if not user_data:
raise ValueError("Нет данных для шифрования.")
extended_key = (cls.__encryption_key * (len(user_data) // len(cls.__encryption_key) + 1))[:len(user_data)]
encrypted_data = "".join(chr(ord(p) ^ ord(k)) for p, k in zip(user_data, extended_key))
cls.set_encrypted_data(encrypted_data) # Сохраняем зашифрованные данные
return encrypted_data
@classmethod
def decrypt_string(cls, encryption_data: str = None, encryption_key: str = None) -> str:
if encryption_data is None:
encryption_data = cls.get_encrypted_data() # Используем хранящиеся данные
if encryption_key is None:
encryption_key = cls.get_encryption_key() # Используем хранящийся ключ
if not encryption_data:
raise ValueError("Нет данных для расшифровки.")
if not encryption_key:
raise ValueError("Ключ шифрования не был передан.")
extended_key = (encryption_key * (len(encryption_data) // len(encryption_key) + 1))[:len(encryption_data)]
return "".join(chr(ord(c) ^ ord(k)) for c, k in zip(encryption_data, extended_key))
if __name__ == "__main__":
user_data = "Привет, мир! Длинная строка для шифрования."
encryption_key = Cipher.generate_encryption_key()
print(f"Ключ шифрования данных: {encryption_key}")
encrypted_data = Cipher.encrypt_string(user_data)
print(f"Зашифрованные данные: {encrypted_data}")
decrypted_data = Cipher.decrypt_string()
print(f"Расшифрованные данные: {decrypted_data}")