Как мне записать объект в файл и прочитать его обратно без использования json и травления в python? - PullRequest
0 голосов
/ 02 декабря 2018

Я создал класс с именем Hand и объект h1.Я записал результат моего объекта в файл (handtest.txt) с кодом:

h1 = Hand(3)

datafile = open('handtest.txt', 'w')

datafile.write(str(h1))

datafile.close()

Я хочу прочитать то, что находится в файле, обратно и сохранить его как другой объект.Однако когда я записал объект в текстовый файл, я уже изменил формат в виде строки.Как мне снова сохранить его как объект?Можно ли это сделать без использования травления и JSON?Вот мой класс Hand:

from card import Card
import random
"""
Defines class Hand, in file hand.py
"""

class Hand:
    """
    One object of class Hand represents a hand of cards
    and so one object stores a number of Card objects.
    """

    def __init__(self, numCardsInHand):
        """
        Initializes a Hand object with numCardsInHand Card objects inside it.
        """
        # Creates a list for storing a hand of cards.
        self.list = []
        # Creates a list for storing bj value.
        self.listBJ = []

        # Uses a loop to store a hand of cards to a list and stores the bj values of the cards to another list.
        for count in range(numCardsInHand):
           #call hitMe()
            Hand.hitMe(self)

    def bjValue(self):
        """
        Returns the blackjack value for the whole Hand of cards
        """
        BJ = ""
        # Sums up all the bj values in self.listBJ and returns it to the bjValue method.
        BJ = sum(self.listBJ)
        return BJ

    def __str__(self):
        """
        Calls the __str__( ) method and uses the returned value
        from the __str__( ) method as the string that is required.
        Returns the local variable in the string method.
        """
        # Tranforms the self.list from list type to string type and saves it as a local variable.
        all_items = '\n'.join(map(str, self.list))
        return all_items

    def hitMe(self):
        """
        Adds one randomly generated Card to the Hand.
        Randomly chooses a rank number and a suit type and save them as local variables.
        Uses the variables as the Card argument in an object. Then append the object to the self.list
        """
        # Randomly chooses a number from 1-13 and stores it as a local variable.
        all_rank = random.randint(1, 13)
        # Lists suit types.
        random_suit = ['d', 'c', 'h', 's']
        # Randomly chooses a suit type in the random_suit list and stores it as a local variable.
        all_suit = random.choice(random_suit)
        # Uses the local variables as arguments of one object of the class Card and appends the object to the self.list.
        self.list.append(Card(all_rank, all_suit))
        # Appends all_rank to self.listBJ.
        self.listBJ.append(all_rank)

1 Ответ

0 голосов
/ 02 декабря 2018

Многие объекты в Python имеют repr(), что соответствует коду Python, который использовался для его создания.Поэтому сначала измените строку, чтобы использовать repr вместо str.(Хотя для некоторых объектов метод __str__ просто вызывает __repr__.)

datafile.write(repr(h1))

Вы можете использовать repr, подобный этому, чтобы восстановить объект, используя eval() на нем.Это не так надежно, как использование pickle, потому что некоторые повторы не являются допустимым кодом Python.

with open('handtest.txt') as datafile:
    h1 = eval(datafile.read())

Обратите внимание, что это угроза безопасности.Не читайте и eval() содержимое файлов, которым вы не доверяете, поскольку вредоносный код Python может привести к плохим вещам, таким как удаление всех ваших файлов.

Конечно, это работает, только если repr является допустимым Pythonкод.Возможно, вам придется написать правильный __repr__ метод для вашего класса рук.Кроме того, иногда это требует соответствующей работы по импорту.Например, если вы eval вводите строку 'Hand(3)', вы должны были импортировать Hand, чтобы это работало.


Оценка repr работает только в том случае, если все состояние объекта может бытьустановить в одном выражении.В настоящее время ваш класс не предназначен для этого, потому что он рандомизирует вещи в __init__.Поэтому правильное выражение repr, хотя и возможно, было бы довольно неловко.

Это не должно вас останавливать.Вы можете создать альтернативные инициализаторы в Python, используя @classmethod.Сделайте тот, который может создать экземпляр и установить все его состояние.Может быть, что-то вроде

@classmethod
def of(cls, hand, bj):
    hand = super().__new__(cls)
    hand.list = hand
    hand.listBj = bj
    return hand

Тогда вы могли бы создать хороший repr с точки зрения этого.

def __repr__(self):
    return f"Hand.of(hand={self.list!r}, bj={self.listBj!r})

Если есть еще состояние, которое вы хотите сохранить, добавьте его в качестве еще одного аргумента для метода класса.и покажите это в отчете.

...