【问题标题】:How do I write an object to a file and read it back without using json and pickling in python?如何在不使用 json 和 python 酸洗的情况下将对象写入文件并将其读回?
【发布时间】:2018-12-01 23:40:30
【问题描述】:

我创建了一个名为 Hand 的类和一个对象 h1。我用代码将我的对象的结果写在一个文件(handtest.txt)中:

h1 = Hand(3)

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

datafile.write(str(h1))

datafile.close()

我想读回文件中的内容并将其另存为另一个对象。但是,当我在文本文件中写入对象时,我已经将格式更改为字符串。如何再次将其另存为对象?是否可以在不使用酸洗和 json 的情况下这样做? 这是我的手类:

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)

【问题讨论】:

  • 这取决于该对象包含的内容。这里没有足够的信息。

标签: python-3.x object text-files readfile writefile


【解决方案1】:

Python 中的许多对象都有一个repr(),它对应于最初用于创建它的 Python 代码。因此,首先将行更改为使用repr 而不是str。 (虽然对于某些对象,__str__ 方法只是调用__repr__。)

datafile.write(repr(h1))

您可以使用这样的 repr 来重构对象,方法是在对象上使用 eval()。这不如使用 pickle 可靠,因为某些 repr 不是有效的 Python 代码。

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

请注意,这是一个安全风险。不要阅读和eval()您不信任的文件的内容,因为恶意 Python 代码可能会做坏事,例如删除所有文件。

当然,这只有在 repr 是有效的 Python 代码时才有效。您可能需要为您的手部课程编写一个正确的__repr__ 方法。此外,有时这需要适当的导入工作。例如,如果您在 eval 输入字符串 'Hand(3)',则必须导入 Hand 才能使其正常工作。


仅当可以在单个表达式中设置整个对象状态时,评估 repr 才有效。目前,您的课程不适合这样做,因为它会随机化 __init__ 中的内容。所以一个有效的 repr 表达式,虽然可能,但会很尴尬。

这不必阻止你。您可以使用 @classmethod 在 Python 中创建备用初始化程序。制作一个可以创建实例并设置其所有状态的实例。也许像

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

那么你就可以创建一个很好的代表了。

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

如果您想保留更多状态,请将其作为另一个参数添加到 classmethod 并在 repr 中显示。

【讨论】:

  • 谢谢。你能解释一下我的 Hand 类的 repr 方法应该写什么吗?
  • @ChiaJuiHung 没有看到你的手课,没有。使其输出代码以将自身构造为字符串。例如。 return f'Hand({self.foo})',其中foo 是适当的属性。
  • 我将代码更改为 datafile.write(repr(h1)) 而不是 datafile.write(str(h1)),但是手测将没有我的 Hand 对象的输出字符串。
  • 我将我的手课添加到原始帖子中。我将repr方法写为:def __repr__(self): return f'Hand({self.__str__()})'. 但是当我测试它时,它在这一行显示错误:h1 = eval(datafile.read())。错误是File "<string>", line 1 Hand(3 of Hearts ^ SyntaxError: invalid syntax 对不起,我是 python 新手。你知道我的代码哪里有问题吗?非常感谢。
  • 我也改了repr方法返回Hand.__str__(self)但是测试错误显示print(h1.bjValue()) AttributeError: 'str' object has no attribute 'bjValue'
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-10-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-25
  • 2019-11-29
相关资源
最近更新 更多