看似独立的对象在初始化时相互干扰
Seemingly seperate objects interfere with eachother during initialization
我 100% 确定这是我的错。我敢打赌这是非常明显的事情。因此,当我说我在发布之前已经检查了我的代码一段时间时,请相信我。
我只需要某人的帮助来找到这些错误的原因,我相信我能够从那里解决它。也许只要用一双新鲜的眼睛检查代码就足以快速发现错误。
使用 python 3.9
问题
我第一次创建 Command 对象时,所有输出看起来都很好。
但是如果我创建第二个 Command 对象,第一个 Command 对象的输出会改变。
如果我例如运行这个:
test_command = Command("Power to comms", {REGULAR_RESOURCE_NAMES["power"]: Power(value=1)},
{REGULAR_RESOURCE_NAMES["comms"]: Comms(value=2)})
我在调试器中得到以下输出:
Power to comms [Command]
Input resources: {'Power': <data_structure.Power object at 0x7f17e56e78b0>}
Output resources: {'Comms': <data_structure.Comms object at 0x7f17e56e77c0>}
但如果我之后 运行 这个:
test_command2 = Command("Comms and power to navs", {REGULAR_RESOURCE_NAMES["comms"]: Comms(value=2),
REGULAR_RESOURCE_NAMES["power"]: Power(value=1)},
{REGULAR_RESOURCE_NAMES["navs"]: Navs(value=5)})
我在调试器中得到以下输出:
Power to comms [Command]
Input resources: {'Power': <data_structure.Power object at 0x7f17e57135b0>, 'Comms': <data_structure.Comms object at 0x7f17e5713610>}
Output resources: {'Comms': <data_structure.Comms object at 0x7f17e56e77c0>, 'Navs': <data_structure.Navs object at 0x7f17e56e78b0>}
Comms and power to navs [Command]
Input resources: {'Power': <data_structure.Power object at 0x7f17e57135b0>, 'Comms': <data_structure.Comms object at 0x7f17e5713610>}
Output resources: {'Comms': <data_structure.Comms object at 0x7f17e56e77c0>, 'Navs': <data_structure.Navs object at 0x7f17e56e78b0>}
首先,我们可以看到两个Command对象中的Power对象共享同一个地址。这不是我想要的。所以这是第一个错误。
其次,为什么第一个命令的资源突然比以前多了input/output?
我在下面包含了相关代码:
我的代码
class Command:
"""
Contains a ratio for exchanging input resources into output resources
"""
name: str
input_resources: dict[str, type(Resource)] = {}
output_resources: dict[str, type(Resource)] = {}
def __init__(self, name: str,
input_resources: dict[str, type(Resource)], output_resources: dict[str, type(Resource)]):
self.name: str = name
for input_resource_name, input_resource in input_resources.items():
self.input_resources[input_resource_name]: type(Resource) = input_resource.copy()
for output_resource_name, output_resource in output_resources.items():
self.output_resources[output_resource_name]: type(Resource) = output_resource.copy()
def __str__(self) -> str:
output: str = self.name + " [Command]" + "\n\t" \
+ "Input resources: " + str(self.input_resources) + "\n\t" \
+ "Output resources: " + str(self.output_resources) + "\n"
return remove_trailing_newlines(output)
def copy(self) -> type(__name__):
input_resources_copy: dict[str, type(Resource)] = {}
for input_resource_name, input_resource in self.input_resources.items():
input_resources_copy[input_resource_name]: type(Resource) = input_resource.copy()
output_resources_copy: dict[str, type(Resource)] = {}
for output_resource_name, output_resource in self.output_resources.items():
output_resources_copy[output_resource_name]: type(Resource) = output_resource.copy()
return Command(self.name, input_resources_copy, output_resources_copy)
class Resource:
"""
The base class for all resource types, such as Comms, Navs, Data, Heat, Drift, Thrust
"""
name: str
value: int
min_value: int
max_value: int
def __init__(self, name: str, value: int = 0, min_value: int = 0, max_value: int = 999):
self.name: str = name
self.value: int = value
self.min_value: int = min_value
self.max_value: int = max_value
def is_valid_value(self) -> bool:
"""
Checks if the numerical validity of the resource value based on init parameters
"""
return self.min_value <= self.value <= self.max_value
class Power(Resource):
"""
This subclass of Resource, contains variables and methods specific to this particular in-game resource.
This is what's considered a regular resource.
"""
def __init__(self, value: int = 0):
super().__init__(REGULAR_RESOURCE_NAMES["power"], value=value)
def next_turn(self) -> bool:
return self.is_valid_value()
def is_valid_end_of_route(self) -> bool:
return self.is_valid_value()
def copy(self) -> type(__name__):
return Power(value=self.value)
其他资源,如 Comms、Navs、Data,与 Power class 完全相同,除了名称。
下面是在全局范围内实例化的:
REGULAR_RESOURCE_NAMES = {
"comms": "Comms",
"navs": "Navs",
"data": "Data",
"power": "Power"
}
当您像这样为 class 定义变量时
class Command:
"""
Contains a ratio for exchanging input resources into output resources
"""
name: str
input_resources: dict[str, type(Resource)] = {}
output_resources: dict[str, type(Resource)] = {}
这些变量被分配给 class 而不是一个实例。在您的 __init__
函数中,您分配给 class 的变量而不是实例拥有的变量。如果您删除 class 级别定义,并按照弗兰克在下面提到的那样在 __init__
中单独初始化它们,它应该可以工作。
我 100% 确定这是我的错。我敢打赌这是非常明显的事情。因此,当我说我在发布之前已经检查了我的代码一段时间时,请相信我。 我只需要某人的帮助来找到这些错误的原因,我相信我能够从那里解决它。也许只要用一双新鲜的眼睛检查代码就足以快速发现错误。
使用 python 3.9
问题
我第一次创建 Command 对象时,所有输出看起来都很好。 但是如果我创建第二个 Command 对象,第一个 Command 对象的输出会改变。
如果我例如运行这个:
test_command = Command("Power to comms", {REGULAR_RESOURCE_NAMES["power"]: Power(value=1)},
{REGULAR_RESOURCE_NAMES["comms"]: Comms(value=2)})
我在调试器中得到以下输出:
Power to comms [Command]
Input resources: {'Power': <data_structure.Power object at 0x7f17e56e78b0>}
Output resources: {'Comms': <data_structure.Comms object at 0x7f17e56e77c0>}
但如果我之后 运行 这个:
test_command2 = Command("Comms and power to navs", {REGULAR_RESOURCE_NAMES["comms"]: Comms(value=2),
REGULAR_RESOURCE_NAMES["power"]: Power(value=1)},
{REGULAR_RESOURCE_NAMES["navs"]: Navs(value=5)})
我在调试器中得到以下输出:
Power to comms [Command]
Input resources: {'Power': <data_structure.Power object at 0x7f17e57135b0>, 'Comms': <data_structure.Comms object at 0x7f17e5713610>}
Output resources: {'Comms': <data_structure.Comms object at 0x7f17e56e77c0>, 'Navs': <data_structure.Navs object at 0x7f17e56e78b0>}
Comms and power to navs [Command]
Input resources: {'Power': <data_structure.Power object at 0x7f17e57135b0>, 'Comms': <data_structure.Comms object at 0x7f17e5713610>}
Output resources: {'Comms': <data_structure.Comms object at 0x7f17e56e77c0>, 'Navs': <data_structure.Navs object at 0x7f17e56e78b0>}
首先,我们可以看到两个Command对象中的Power对象共享同一个地址。这不是我想要的。所以这是第一个错误。 其次,为什么第一个命令的资源突然比以前多了input/output?
我在下面包含了相关代码:
我的代码
class Command:
"""
Contains a ratio for exchanging input resources into output resources
"""
name: str
input_resources: dict[str, type(Resource)] = {}
output_resources: dict[str, type(Resource)] = {}
def __init__(self, name: str,
input_resources: dict[str, type(Resource)], output_resources: dict[str, type(Resource)]):
self.name: str = name
for input_resource_name, input_resource in input_resources.items():
self.input_resources[input_resource_name]: type(Resource) = input_resource.copy()
for output_resource_name, output_resource in output_resources.items():
self.output_resources[output_resource_name]: type(Resource) = output_resource.copy()
def __str__(self) -> str:
output: str = self.name + " [Command]" + "\n\t" \
+ "Input resources: " + str(self.input_resources) + "\n\t" \
+ "Output resources: " + str(self.output_resources) + "\n"
return remove_trailing_newlines(output)
def copy(self) -> type(__name__):
input_resources_copy: dict[str, type(Resource)] = {}
for input_resource_name, input_resource in self.input_resources.items():
input_resources_copy[input_resource_name]: type(Resource) = input_resource.copy()
output_resources_copy: dict[str, type(Resource)] = {}
for output_resource_name, output_resource in self.output_resources.items():
output_resources_copy[output_resource_name]: type(Resource) = output_resource.copy()
return Command(self.name, input_resources_copy, output_resources_copy)
class Resource:
"""
The base class for all resource types, such as Comms, Navs, Data, Heat, Drift, Thrust
"""
name: str
value: int
min_value: int
max_value: int
def __init__(self, name: str, value: int = 0, min_value: int = 0, max_value: int = 999):
self.name: str = name
self.value: int = value
self.min_value: int = min_value
self.max_value: int = max_value
def is_valid_value(self) -> bool:
"""
Checks if the numerical validity of the resource value based on init parameters
"""
return self.min_value <= self.value <= self.max_value
class Power(Resource):
"""
This subclass of Resource, contains variables and methods specific to this particular in-game resource.
This is what's considered a regular resource.
"""
def __init__(self, value: int = 0):
super().__init__(REGULAR_RESOURCE_NAMES["power"], value=value)
def next_turn(self) -> bool:
return self.is_valid_value()
def is_valid_end_of_route(self) -> bool:
return self.is_valid_value()
def copy(self) -> type(__name__):
return Power(value=self.value)
其他资源,如 Comms、Navs、Data,与 Power class 完全相同,除了名称。
下面是在全局范围内实例化的:
REGULAR_RESOURCE_NAMES = {
"comms": "Comms",
"navs": "Navs",
"data": "Data",
"power": "Power"
}
当您像这样为 class 定义变量时
class Command:
"""
Contains a ratio for exchanging input resources into output resources
"""
name: str
input_resources: dict[str, type(Resource)] = {}
output_resources: dict[str, type(Resource)] = {}
这些变量被分配给 class 而不是一个实例。在您的 __init__
函数中,您分配给 class 的变量而不是实例拥有的变量。如果您删除 class 级别定义,并按照弗兰克在下面提到的那样在 __init__
中单独初始化它们,它应该可以工作。