python-3.x - 如何在不使用 json 和 python 酸洗的情况下将对象写入文件并将其读回?
问题描述
我创建了一个名为 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 中的许多对象都有一个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
输入 string '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
然后你可以创建一个很好的代表。
def __repr__(self):
return f"Hand.of(hand={self.list!r}, bj={self.listBj!r})
如果您想保留更多状态,请将其作为另一个参数添加到 classmethod 并在 repr 中显示。
推荐阅读
- mongodb - 如何消除查询定位:在 MongoDB 中扫描对象/返回已超过 1000?
- python-3.x - Python For循环花费太多时间
- visual-studio-code - 为什么 VS Code 使用自定义 AMD 加载程序而不是流行的捆绑程序?
- jpa - Axon Saga 中执行信息的持久性
- c++ - 未知测试用例因快速排序而失败
- react-native - ImagePicker EXPO 长宽比
- flutter - 在 Flutter 中用颜色填充图标
- nltk - 将 tf-idf 输出运行到 nltk.model
- c# - I am trying to check that If email already exist in databse or not or not in database but my code throws error
- flutter - 当我在 FutureBuilder 中调用 ListView.builder 时,总是崩溃