Instructions système |
Vous êtes un développeur Python de premier plan et un tuteur spécialisé dans l'enseignement de Python et des concepts de programmation fondamentaux aux nouveaux développeurs. Vous expliquez chaque concept clairement et en termes simples, en décomposant les idées complexes étape par étape.
|
Je suis débutant en Python et j'essaie d'apprendre les fonctionnalités de syntaxe Python illustrées dans le code suivant. Pouvez-vous identifier les trois instructions @ , puis expliquer leur signification ? Lorsque vous expliquez les choses, vous devez générer des exemples de code pour illustrer leur fonctionnement. N'incluez pas de blocs de code qui ne sont pas des exemples de code que vous avez générés.
AdventurerGame.py :
from dataclasses import dataclass, field
from typing import List
from enum import Enum
from collections import namedtuple
class LootCategory(Enum):
WEAPON = "Weapon"
ARMOR = "Armor"
POTION = "Potion"
LootAttributes = namedtuple('LootAttributes', ['attack_boost', 'defense_boost'])
@dataclass
class Loot:
name: str
category: LootCategory
attributes: LootAttributes = LootAttributes(attack_boost=0, defense_boost=0)
class LootForge:
@staticmethod
def craft_weapon(name: str, attack_boost: int) -> Loot:
return Loot(name, LootCategory.WEAPON, LootAttributes(attack_boost, 0))
@staticmethod
def craft_armor(name: str, defense_boost: int) -> Loot:
return Loot(name, LootCategory.ARMOR, LootAttributes(0, defense_boost))
@staticmethod
def brew_potion(name: str) -> Loot:
return Loot(name, LootCategory.POTION)
@dataclass
class Ability:
name: str
impact: int
energy_cost: int
class AbilityTome:
@staticmethod
def create_offensive_ability(name: str, impact: int, energy_cost: int) -> Ability:
return Ability(name, impact, energy_cost)
@staticmethod
def create_healing_ability(name: str, healing: int, energy_cost: int) -> Ability:
return Ability(name, -healing, energy_cost)
@dataclass
class Adventurer:
name: str
health: int
stamina: int
base_damage: int
base_resilience: int
backpack: List[Loot] = field(default_factory=list)
abilities: List[Ability] = field(default_factory=list)
@property
def calculate_attack_damage(self) -> int:
return self.base_damage + sum(item.attributes.attack_boost for item in self.backpack)
@property
def total_resilience(self) -> int:
return self.base_resilience + sum(item.attributes.defense_boost for item in self.backpack)
class BackpackOrganizer:
@staticmethod
def add_loot(adventurer: Adventurer, loot: Loot):
adventurer.backpack.append(loot)
class AbilityMaster:
@staticmethod
def teach_ability(adventurer: Adventurer, ability: Ability):
adventurer.abilities.append(ability)
@staticmethod
def use_ability(user: Adventurer, ability_name: str, target: Adventurer) -> str:
ability = next((a for a in user.abilities if a.name == ability_name), None)
if ability and user.stamina >= ability.energy_cost:
user.stamina -= ability.energy_cost
target.health -= ability.impact
return f"{user.name} invokes {ability_name} on {target.name} with an impact of {ability.impact}!"
return f"{user.name} attempted to invoke {ability_name} but failed due to insufficient energy or lack of knowledge."
class BattleController:
@staticmethod
def execute_attack(attacker: Adventurer, defender: Adventurer) -> str:
impact = max(0, attacker.calculate_attack_damage - defender.total_resilience)
defender.health -= impact
return f"{attacker.name} strikes {defender.name} and inflicts {impact} damage!"
class AdventurerCrafter:
@staticmethod
def create_adventurer(name: str, health: int, stamina: int, base_damage: int, base_resilience: int) -> Adventurer:
return Adventurer(name, health, stamina, base_damage, base_resilience)
class AdventurerLogger:
@staticmethod
def log_adventurer(adventurer: Adventurer) -> str:
loot = ', '.join(item.name for item in adventurer.backpack) or "No loot"
abilities = ', '.join(ability.name for ability in adventurer.abilities) or "No abilities"
return (f"Adventurer({adventurer.name}, Health: {adventurer.health}, Stamina: {adventurer.stamina}, "
f"Damage: {adventurer.calculate_attack_damage}, Resilience: {adventurer.total_resilience}, "
f"Loot: [{loot}], Abilities: [{abilities}])")
if __name__ == "__main__":
champion = AdventurerCrafter.create_adventurer(name="Champion", health=100, stamina=100, base_damage=10, base_resilience=10)
rogue = AdventurerCrafter.create_adventurer(name="Rogue", health=65, stamina=80, base_damage=35, base_resilience=2)
sword = LootForge.craft_weapon("Sword", 10)
shield = LootForge.craft_armor("Shield", 10)
fireball = AbilityTome.create_offensive_ability("Fireball", 20, 10)
heal = AbilityTome.create_healing_ability("Heal", 15, 8)
BackpackOrganizer.add_loot(champion, sword)
AbilityMaster.teach_ability(champion, fireball)
BackpackOrganizer.add_loot(rogue, shield)
AbilityMaster.teach_ability(rogue, heal)
print(AdventurerLogger.log_adventurer(champion))
print(AdventurerLogger.log_adventurer(rogue))
print(BattleController.execute_attack(champion, rogue))
print(AbilityMaster.use_ability(rogue, "Heal", rogue))
print(AbilityMaster.use_ability(champion, "Fireball", rogue))
Réponse
Les trois symboles @ du code fourni représentent des décorateurs en Python. Examinons-les :
@dataclass : ce décorateur permet de générer automatiquement du code récurrent pour les classes. Il simplifie la création de classes qui stockent principalement des données. Il ajoute automatiquement des méthodes telles que __init__ , __repr__ et d'autres, en fonction des champs que vous définissez dans la classe.
from dataclasses import dataclass
@dataclass
class Dog:
name: str
breed: str
age: int
my_dog = Dog("Buddy", "Golden Retriever", 3)
print(my_dog) # Output: Dog(name='Buddy', breed='Golden Retriever', age=3)
Sans @dataclass , il faudrait écrire manuellement la méthode __init__ et éventuellement d'autres :
class Dog:
def __init__(self, name, breed, age):
self.name = name
self.breed = breed
self.age = age
my_dog = Dog("Buddy", "Golden Retriever", 3)
print(my_dog) # Output: <__main__.Dog object at 0x...> (less informative)
@staticmethod : ce décorateur définit une méthode liée à la classe et non à l'instance de la classe. Il n'a pas accès à self (l'instance) ou à cls (la classe elle-même) de manière implicite. Les méthodes statiques sont essentiellement des fonctions utilitaires qui appartiennent logiquement à une classe, mais qui n'ont pas besoin d'interagir avec l'état de la classe.
class MathHelper:
@staticmethod
def add(x, y):
return x + y
result = MathHelper.add(5, 3) # No need to create a MathHelper object
print(result) # Output: 8
Si vous essayez d'appeler add en tant que méthode d'instance, une erreur s'affiche, car elle n'utilise pas self :
class MathHelper:
def add(self, x, y): # Incorrect - instance method needs self
return x + y
helper = MathHelper()
result = helper.add(5,3) # This would work, but is not a static method
@property : ce décorateur transforme une méthode en attribut en lecture seule. Il vous permet d'accéder à une méthode à l'aide de la syntaxe d'attribut (par exemple, object.attribute ), mais il exécute le code de la méthode en arrière-plan. Cette option est utile pour les attributs calculés ou les attributs qui nécessitent un traitement avant d'être renvoyés.
class Circle:
def __init__(self, radius):
self._radius = radius # Note the underscore - convention for internal attributes
@property
def area(self):
return 3.14159 * self._radius * self._radius
my_circle = Circle(5)
print(my_circle.area) # Output: 78.53975 (no parentheses needed)
Sans le décorateur @property , vous devez appeler area en tant que méthode :
class Circle:
def __init__(self, radius):
self._radius = radius
def area(self):
return 3.14159 * self._radius * self._radius
my_circle = Circle(5)
print(my_circle.area()) # Output: 78.53975 (parentheses are needed)
|
Modèle : |
gemini-1.5-flash-002 |
Température : |
0,2 |
Nombre maximal de jetons de sortie : |
8 192 |
TopK : |
40,0 |
TopP : |
0,95 |
|