Vấn đề là bạn đã biến equipped_weapon
một thuộc tính lớp, không phải là thuộc tính thể hiện. del instance.attribute
Chỉ xóa các thuộc tính thể hiện, nó thậm chí không tìm kiếm các thuộc tính lớp.
Nếu mục tiêu chỉ là thay đổi thể hiện, bạn có thể xóa hoàn toàn del
; Dòng tiếp theo sẽ thêm [nếu không có thuộc tính thể hiện tồn tại, theo dõi thuộc tính lớp] hoặc thay thế [nếu một thuộc tính thể hiện đã tồn tại] vũ khí cụ thể của phiên bản.
Nếu mục tiêu là thay đổi lớp, bạn cần thay đổi bài tập để vận hành trên lớp:
type[player].equipped_weapon = new_weapon_code
hoặc đặt tên rõ ràng cho lớp học:
Player.equipped_weapon = new_weapon_code
Dù bằng cách nào, del
không cần thiết; Việc gán giá trị mới thay thế giá trị cũ, hoàn toàn bỏ tham chiếu đến giá trị cũ theo cùng một cách mà del
không rõ ràng. Sẽ là hoàn toàn hợp pháp khi làm del type[player].equipped_weapon
hoặc del Player.equipped_weapon
để xóa thuộc tính lớp một cách cụ thể, nhưng nó vô nghĩa; Dù hành vi mong muốn, việc gán đơn giản cho lớp hoặc thuộc tính thể hiện sẽ loại bỏ tham chiếu cũ.
Cập nhật: Như bạn đã lưu ý, việc loại bỏ del
ngăn chặn ngoại lệ, nhưng đầu ra của bạn [từ ____11] không bao giờ thay đổi. Đó là bởi vì
1 đang xem xét Player.equipped_weapon = new_weapon_code
3, từ đó chứa một tham chiếu đến giá trị ban đầu của Player.equipped_weapon = new_weapon_code
4. Vấn đề là, trong khi Player.equipped_weapon = new_weapon_code
5 và Player.equipped_weapon = new_weapon_code
equipped_weapon
được khởi tạo dựa trên cùng một vũ khí mặc định, chúng không được đồng bộ hóa với nhau; Thay đổi người này không có tác dụng đối với cái kia [và do đó thay đổi equipped_weapon
, trên lớp hoặc thể hiện, không ảnh hưởng đến
8, do đó Player.equipped_weapon = new_weapon_code
1 không bao giờ thay đổi].: As you noted, removing the Player.equipped_weapon = new_weapon_code
del
prevents the exception, but your output [from
Player.equipped_weapon = new_weapon_code
1] never changes. That's because Player.equipped_weapon = new_weapon_code
1 is looking at Player.equipped_weapon = new_weapon_code
3, which in turn contains a reference to the original value of Player.equipped_weapon = new_weapon_code
4. Problem is, while Player.equipped_weapon = new_weapon_code
5 and equipped_weapon
are initialized based on the same default weapon, they're not synced to one another; changing one has no effect on the other [and
therefore changing equipped_weapon
, on the class or instance, doesn't affect Player.equipped_weapon = new_weapon_code
8, so Player.equipped_weapon = new_weapon_code
1 never changes].Thực sự, giải pháp ở đây là tạo ra một lớp lành mạnh. Không có thuộc tính lớp nào của bạn có ý nghĩa; Tất cả chúng đều thuộc tính thể hiện về mặt logic và nên được xác định như vậy. Trong một vài trường hợp, chúng chỉ là các phép biến đổi hướng đến sự thuận tiện của một thuộc tính khác; Trong những trường hợp đó, chúng hoàn toàn không nên là thuộc tính, mà là các ____2020, điều này tự động tính toán giá trị của chúng dựa trên một thuộc tính khác, ngăn không cho chúng thoát khỏi đồng bộ hóa.
Dưới đây là một bản viết lỗi thực sự nhanh [không được kiểm tra, có thể có lỗi chính tả nhỏ] di chuyển tất cả các thuộc tính chính đáng của bạn sang thể hiện và chuyển đổi phần còn lại thành các thuộc tính chỉ đọc có được giá trị của chúng từ thuộc tính thể hiện khác:
import copy
# Factored out to avoid repetition
def clean_armor[armor]:
return {k.rstrip[':']: v
for k, v in armor.items[] if k in {'Name:', 'Defense:'}}
class Person:
DEFAULT_WEAPON = weapon_rusty_sword
DEFAULT_ARMOR = {
"Head Protection:": clean_armor[armor_head_rusty_cap],
"Chest Protection:": clean_armor[armor_chest_rusty_mail],
"Legs Protection:": clean_armor[armor_legs_rash_leggings],
}
def __init__[self, name="Cavalex",
equipped_weapon=DEFAULT_WEAPON, equipped_armor=DEFAULT_ARMOR,
base_attack=1, base_defense=1,
hp=20, gold=10,
potions=[potion_hp["Name:"],]]:
self.name = name
# deepcopy is defensive [so changing defaults doesn't retroactively
# alter existing instance]; can be removed if you guarantee defaults
# won't be changed, or you want changes to defaults to affect
# Players still wielding default items
self.equipped_weapon = copy.deepcopy[equipped_weapon]
self.equipped_armor = copy.deepcopy[equipped_armor]
self.base_attack = int[base_attack]
self.base_defense = int[base_defense]
self.HP = int[hp]
self.gold = int[gold]
# potions only used as dictionary, but it's silly to store it as one
# Just store list of potion names in protected attribute,
# property can construct the expected dict on demand
self._potions = list[potions]
@property
def ATTACK[self]:
return self.base_attack + self.equipped_weapon[add_attack]
@property
def DEFENSE[self]:
return self.base_defense + sum[armor['Defense'] for armor in self.equipped_armor.values[]]
@property
def potions[self]:
return {"Potions: ": self._potions}
@property
def ui_gold[self]:
return {"Gold: ": self.gold}
@property
def ui_equipped_weapon[self]:
return {"Equipped Weapon: {}".format[self.equipped_weapon]: ""}
@property:
def inv[self]:
return [
self.equipped_armor,
self.ui_equipped_weapon,
self.potions,
self.ui_gold,
]
def see_inventory[self]:
for element in self.inv:
for k, v in element.items[]:
if isinstance[v, list]:
print[k, ' '.join[v]]
else:
print[k, v]
Điều này vẫn có rất nhiều lựa chọn đáng ngờ [đặt tên thuộc tính/thuộc tính không nhất quán; tên khóa kỳ lạ trong
import copy
# Factored out to avoid repetition
def clean_armor[armor]:
return {k.rstrip[':']: v
for k, v in armor.items[] if k in {'Name:', 'Defense:'}}
class Person:
DEFAULT_WEAPON = weapon_rusty_sword
DEFAULT_ARMOR = {
"Head Protection:": clean_armor[armor_head_rusty_cap],
"Chest Protection:": clean_armor[armor_chest_rusty_mail],
"Legs Protection:": clean_armor[armor_legs_rash_leggings],
}
def __init__[self, name="Cavalex",
equipped_weapon=DEFAULT_WEAPON, equipped_armor=DEFAULT_ARMOR,
base_attack=1, base_defense=1,
hp=20, gold=10,
potions=[potion_hp["Name:"],]]:
self.name = name
# deepcopy is defensive [so changing defaults doesn't retroactively
# alter existing instance]; can be removed if you guarantee defaults
# won't be changed, or you want changes to defaults to affect
# Players still wielding default items
self.equipped_weapon = copy.deepcopy[equipped_weapon]
self.equipped_armor = copy.deepcopy[equipped_armor]
self.base_attack = int[base_attack]
self.base_defense = int[base_defense]
self.HP = int[hp]
self.gold = int[gold]
# potions only used as dictionary, but it's silly to store it as one
# Just store list of potion names in protected attribute,
# property can construct the expected dict on demand
self._potions = list[potions]
@property
def ATTACK[self]:
return self.base_attack + self.equipped_weapon[add_attack]
@property
def DEFENSE[self]:
return self.base_defense + sum[armor['Defense'] for armor in self.equipped_armor.values[]]
@property
def potions[self]:
return {"Potions: ": self._potions}
@property
def ui_gold[self]:
return {"Gold: ": self.gold}
@property
def ui_equipped_weapon[self]:
return {"Equipped Weapon: {}".format[self.equipped_weapon]: ""}
@property:
def inv[self]:
return [
self.equipped_armor,
self.ui_equipped_weapon,
self.potions,
self.ui_gold,
]
def see_inventory[self]:
for element in self.inv:
for k, v in element.items[]:
if isinstance[v, list]:
print[k, ' '.join[v]]
else:
print[k, v]
1 dường như đã được chọn để hiển thị dễ dàng hơn, nhưng làm cho tất cả các trò chơi không gây khó chịu hơn; sử dụng các chức năng cấp cao nhất cho những thứ Chỉ có ý nghĩa như các phương thức thể hiện, v.v.], nhưng tôi đã bảo tồn những điều đó để giữ cho nó thay thế cho lớp hiện tại của bạn [nhưng với tất cả các thuộc tính mỗi người chơi được đặt trên thể hiện, không phải lớp và tất cả các thuộc tính có nguồn gốc Thông qua các ____20 thay vì đặt tĩnh, vì các thuộc tính tĩnh độc lập làm tăng tỷ lệ cược của cơ sở và các thuộc tính dẫn xuất thoát khỏi đồng bộ hóa].Tôi bảo tồn hành vi cho phép bạn tạo
import copy
# Factored out to avoid repetition
def clean_armor[armor]:
return {k.rstrip[':']: v
for k, v in armor.items[] if k in {'Name:', 'Defense:'}}
class Person:
DEFAULT_WEAPON = weapon_rusty_sword
DEFAULT_ARMOR = {
"Head Protection:": clean_armor[armor_head_rusty_cap],
"Chest Protection:": clean_armor[armor_chest_rusty_mail],
"Legs Protection:": clean_armor[armor_legs_rash_leggings],
}
def __init__[self, name="Cavalex",
equipped_weapon=DEFAULT_WEAPON, equipped_armor=DEFAULT_ARMOR,
base_attack=1, base_defense=1,
hp=20, gold=10,
potions=[potion_hp["Name:"],]]:
self.name = name
# deepcopy is defensive [so changing defaults doesn't retroactively
# alter existing instance]; can be removed if you guarantee defaults
# won't be changed, or you want changes to defaults to affect
# Players still wielding default items
self.equipped_weapon = copy.deepcopy[equipped_weapon]
self.equipped_armor = copy.deepcopy[equipped_armor]
self.base_attack = int[base_attack]
self.base_defense = int[base_defense]
self.HP = int[hp]
self.gold = int[gold]
# potions only used as dictionary, but it's silly to store it as one
# Just store list of potion names in protected attribute,
# property can construct the expected dict on demand
self._potions = list[potions]
@property
def ATTACK[self]:
return self.base_attack + self.equipped_weapon[add_attack]
@property
def DEFENSE[self]:
return self.base_defense + sum[armor['Defense'] for armor in self.equipped_armor.values[]]
@property
def potions[self]:
return {"Potions: ": self._potions}
@property
def ui_gold[self]:
return {"Gold: ": self.gold}
@property
def ui_equipped_weapon[self]:
return {"Equipped Weapon: {}".format[self.equipped_weapon]: ""}
@property:
def inv[self]:
return [
self.equipped_armor,
self.ui_equipped_weapon,
self.potions,
self.ui_gold,
]
def see_inventory[self]:
for element in self.inv:
for k, v in element.items[]:
if isinstance[v, list]:
print[k, ' '.join[v]]
else:
print[k, v]
3 mà không cung cấp bất kỳ đối số nào, mặc dù import copy
# Factored out to avoid repetition
def clean_armor[armor]:
return {k.rstrip[':']: v
for k, v in armor.items[] if k in {'Name:', 'Defense:'}}
class Person:
DEFAULT_WEAPON = weapon_rusty_sword
DEFAULT_ARMOR = {
"Head Protection:": clean_armor[armor_head_rusty_cap],
"Chest Protection:": clean_armor[armor_chest_rusty_mail],
"Legs Protection:": clean_armor[armor_legs_rash_leggings],
}
def __init__[self, name="Cavalex",
equipped_weapon=DEFAULT_WEAPON, equipped_armor=DEFAULT_ARMOR,
base_attack=1, base_defense=1,
hp=20, gold=10,
potions=[potion_hp["Name:"],]]:
self.name = name
# deepcopy is defensive [so changing defaults doesn't retroactively
# alter existing instance]; can be removed if you guarantee defaults
# won't be changed, or you want changes to defaults to affect
# Players still wielding default items
self.equipped_weapon = copy.deepcopy[equipped_weapon]
self.equipped_armor = copy.deepcopy[equipped_armor]
self.base_attack = int[base_attack]
self.base_defense = int[base_defense]
self.HP = int[hp]
self.gold = int[gold]
# potions only used as dictionary, but it's silly to store it as one
# Just store list of potion names in protected attribute,
# property can construct the expected dict on demand
self._potions = list[potions]
@property
def ATTACK[self]:
return self.base_attack + self.equipped_weapon[add_attack]
@property
def DEFENSE[self]:
return self.base_defense + sum[armor['Defense'] for armor in self.equipped_armor.values[]]
@property
def potions[self]:
return {"Potions: ": self._potions}
@property
def ui_gold[self]:
return {"Gold: ": self.gold}
@property
def ui_equipped_weapon[self]:
return {"Equipped Weapon: {}".format[self.equipped_weapon]: ""}
@property:
def inv[self]:
return [
self.equipped_armor,
self.ui_equipped_weapon,
self.potions,
self.ui_gold,
]
def see_inventory[self]:
for element in self.inv:
for k, v in element.items[]:
if isinstance[v, list]:
print[k, ' '.join[v]]
else:
print[k, v]
4 thực sự nên là một đối số không tùy chọn [trừ khi "Cavalex" là một cái tên phổ biến mà bạn có thể giả định một cách an toàn nếu không phải tất cả người chơi có tên đó ].Tôi nhận ra rằng có vẻ như tẻ nhạt khi đánh vần
import copy
# Factored out to avoid repetition
def clean_armor[armor]:
return {k.rstrip[':']: v
for k, v in armor.items[] if k in {'Name:', 'Defense:'}}
class Person:
DEFAULT_WEAPON = weapon_rusty_sword
DEFAULT_ARMOR = {
"Head Protection:": clean_armor[armor_head_rusty_cap],
"Chest Protection:": clean_armor[armor_chest_rusty_mail],
"Legs Protection:": clean_armor[armor_legs_rash_leggings],
}
def __init__[self, name="Cavalex",
equipped_weapon=DEFAULT_WEAPON, equipped_armor=DEFAULT_ARMOR,
base_attack=1, base_defense=1,
hp=20, gold=10,
potions=[potion_hp["Name:"],]]:
self.name = name
# deepcopy is defensive [so changing defaults doesn't retroactively
# alter existing instance]; can be removed if you guarantee defaults
# won't be changed, or you want changes to defaults to affect
# Players still wielding default items
self.equipped_weapon = copy.deepcopy[equipped_weapon]
self.equipped_armor = copy.deepcopy[equipped_armor]
self.base_attack = int[base_attack]
self.base_defense = int[base_defense]
self.HP = int[hp]
self.gold = int[gold]
# potions only used as dictionary, but it's silly to store it as one
# Just store list of potion names in protected attribute,
# property can construct the expected dict on demand
self._potions = list[potions]
@property
def ATTACK[self]:
return self.base_attack + self.equipped_weapon[add_attack]
@property
def DEFENSE[self]:
return self.base_defense + sum[armor['Defense'] for armor in self.equipped_armor.values[]]
@property
def potions[self]:
return {"Potions: ": self._potions}
@property
def ui_gold[self]:
return {"Gold: ": self.gold}
@property
def ui_equipped_weapon[self]:
return {"Equipped Weapon: {}".format[self.equipped_weapon]: ""}
@property:
def inv[self]:
return [
self.equipped_armor,
self.ui_equipped_weapon,
self.potions,
self.ui_gold,
]
def see_inventory[self]:
for element in self.inv:
for k, v in element.items[]:
if isinstance[v, list]:
print[k, ' '.join[v]]
else:
print[k, v]
5 và xác định các ____2020 khi bạn có thể chỉ cần sao chép dữ liệu từ thuộc tính sang thuộc tính dẫn xuất, nhưng về mặt mã mà bạn thực sự có thể sử dụng một cách có ý nghĩa mà không có sự lặp lại cực đoan [và rủi ro đi kèm về lỗi chính tả và lỗi logic], hiểu hành vi của, v.v., đây là cách duy nhất có ý nghĩa; ALý do bạn tạo ra các lớp là để cho phép bạn tạo ra nhiều trường hợp của lớp với các thuộc tính khác nhau, nhưng các hành vi được chia sẻ; Làm cho lớp A gần như-singleton bằng cách sử dụng trạng thái cấp độ hoàn toàn khiến lớp trở nên vô nghĩa, ít nhất là ở Python nơi thiết kế ngôn ngữ đa hướng có nghĩa là mẫu singleton hiếm khi cần thiết, nếu sử dụng trạng thái cấp lớp được xác định tại thời điểm định nghĩa sẽ loại bỏ Lợi thế duy nhất của mẫu, trì hoãn việc khởi tạo singleton cho đến khi cần thiết].