2010-10-22 2 views
3

Supposons que j'ai plusieurs fonctions pour un RPG Je travaille sur ...Comment puis-je créer des classes globales en Python (si possible)?

def name_of_function(): 
    action 

et voulait mettre en œuvre la classe de hache (voir ci-dessous) dans chaque fonction sans avoir à réécrire chaque classe. Comment pourrais-je créer la classe en tant que classe globale. Je ne suis pas sûr si j'utilise la bonne terminologie ou non, mais aidez s'il vous plaît. Cela m'a toujours empêché de créer des jeux RPG basés sur le texte. Un exemple de classe globale serait génial!

class axe: 
    attack = 5 
    weight = 6 
    description = "A lightweight battle axe." 
    level_required = 1 
    price = 10 
+0

Si vous êtes juste stocker un tas de propriétés, vous pouvez utiliser un dictionnaire. – Seth

+2

Vous n'avez pas besoin d'une classe globale pour y parvenir, utilisez simplement la notation 'module.class' de Python pour accéder à la classe à partir d'autres modules du paquet. –

Répondre

6

Vous ne pouvez pas créer tout ce qui est vraiment mondiale en Python - qui est quelque chose qui est disponible comme par magie à tout module, peu importe quoi. Mais peu importe une fois que vous comprenez comment les modules et l'importation fonctionnent.

Généralement, vous créez des classes et les organisez en modules. Ensuite, vous les importez dans n'importe quel module, ce qui ajoute la classe à la table de symboles du module.

Ainsi, par exemple, vous pouvez créer un module appelé weapons.py et créer une classe dans WeaponBase, puis Axe et Broadsword classes dérivées de WeaponsBase. Ensuite, dans tout module qui devait utiliser des armes, vous devez mettre

import weapons 

en haut du fichier. Une fois que vous faites cela, weapons.Axe renvoie la classe Axe, weapons.Broadsword renvoie la classe Broadsword, et ainsi de suite. Vous pouvez également utiliser:

from weapons import Axe, Broadsword 

qui ajoute Axe et Broadsword à la table des symboles du module, ce qui permet le code de faire à peu près exactement ce que vous dites que vous voulez qu'il fasse.

Vous pouvez également utiliser

from weapons import * 

mais cela est généralement pas une bonne idée pour deux raisons. Tout d'abord, il importe tout dans le module si vous allez l'utiliser ou non - WeaponsBase, par exemple. Deuxièmement, vous rencontrez toutes sortes de problèmes confus s'il y a une fonction dans weapons qui a le même nom qu'une fonction dans le module d'importation.

Il y a beaucoup de subtilités dans le système import. Vous devez veiller à ce que les modules n'essaient pas de s'importer les uns les autres, par exemple. Et finalement votre projet devient assez grand pour que vous ne vouliez pas mettre tous ses modules dans le même répertoire, et vous devrez en apprendre davantage sur des choses comme __init__.py. Mais vous pouvez vous inquiéter à ce sujet sur la route.

+0

Donc, dites-vous que j'aurais des classes à l'intérieur des classes, quand vous avez dit le mot "dériver"? –

+0

Bien sûr, vous pouvez créer quelque chose de vraiment global en Python, en utilisant le mot clé global. –

+0

Il aurait l'air soemthing comme celui-ci isnide des armes de classe fichier de weapons.py: classe axe_1: level_required = 2 attaque = 4 description = « Une hache de combat léger avec une base en bois et une lame de bronze. » durabilité = 10 poids = 2 –

1

Je ne suis pas d'accord avec l'idée que vous ne pouvez pas créer quelque chose de vraiment global en python. en fait, c'est facile. en Python 3.1, il ressemble à ceci:

def get_builtins(): 
    """Due to the way Python works, ``__builtins__`` can strangely be either a module or a dictionary, 
    depending on whether the file is executed directly or as an import. I couldn’t care less about this 
    detail, so here is a method that simply returns the namespace as a dictionary.""" 
    return getattr(__builtins__, '__dict__', __builtins__) 

comme un tas d'autres choses, builtins sont un point où PY3 diffère en détail de la façon dont il travaillait dans py2. lisez les documents "Quoi de neuf dans Python X.X" sur python.org pour plus de détails. je n'ai aucune idée de la raison de la convention mentionnée ci-dessus; Je veux juste ignorer ce genre de choses. i pense que le code ci-dessus devrait également fonctionner dans Py2.

donc le point ici est qu'il y a un __builtins__ thingie qui contient beaucoup de choses qui viennent, bien, intégré dans Python. tous les sum, max, range des trucs que vous avez appris à aimer. eh bien, presque tout. mais vous n'avez pas besoin des détails, vraiment. la chose la plus simple que vous pourriez faire est de dire

G   = get_builtins() 
G[ 'G' ] = G 
G[ 'axe' ] = axe 

à un point de votre code dont l'exécution est toujours garantie. G représente l'espace de noms globalement disponible, et depuis que j'ai enregistré G lui-même dans G, G transcende maintenant magiquement son existence dans l'arrière-plan de chaque module. signifie que vous devriez l'utiliser avec soin. Lorsque des collisions de noms se produisent entre tout ce qui est détenu dans G et dans l'espace de nom d'un module, l'espace de noms du module devrait être gagner (car il est inspecté en premier). aussi, préparez-vous à ce que tout le monde vous saute dessus quand vous leur dites que vous êtes en train de critiquer le DAMMIT du NAMESPACE GLOBAL. Je suis surpris que personne n'en ait encore parlé, ici.

Eh bien, ces gens auraient raison, d'une certaine façon. Personnellement, cependant, c'est une de mes principales techniques de composition d'application: ce que vous faites, c'est vous éloigner du module polyvalent (qui ne devrait pas faire une telle chose) vers un espace de noms spécifique à l'application. vos modules sont tenus de ne pas travailler en dehors de cet espace de noms, mais ils ne le sont pas non plus. J'ai effectivement commencé ce style de programmation comme une rébellion expérimentale contre (1) les vues établies, hah !, et (2) le désespoir qui me frappe chaque fois que je veux accomplir quelque chose de moins que trivial en utilisant l'instruction import de Python. ces jours-ci, je n'utilise que import pour les bibliothèques standard et les modules installés régulièrement; pour mes propres affaires, j'utilise un système interne. que puis-je dire, ça marche!

ah oui, deux autres points: faites-vous une faveur, si vous aimez cette solution, et écrivez-vous une méthode publish() ou similaire qui vous permet de ne jamais publier un nom qui a déjà été pris. Dans la plupart des cas, vous ne le voulez pas. Enfin, permettez-moi d'appuyer le premier commentateur: j'ai programmé exactement le style que vous montrez ci-dessus, parce que c'est ce que vous trouvez dans les exemples de manuels (la plupart du temps en utilisant car s, pas axe s pour être sûr) . pour un nombre assez important de raisons, j'ai à peu près abandonné à ce sujet. Considérons ceci: JSON ne définit que sept types de données: nul, vrai, faux, nombres, textes, listes, dictionnaires, c'est tout. Je prétends que vous pouvez modéliser tout autre type de données utile avec ceux-ci.

Il y a encore beaucoup de justification pour des choses comme des ensembles, des sacs, des dictionnaires ordonnés et ainsi de suite. la revendication ici n'est pas qu'il est toujours commode ou approprié de se rabattre sur une forme pure, directement compatible avec JSON; l'affirmation est seulement qu'il est possible de simuler. en ce moment, je suis l'implémentation d'une liste clairsemée pour une utilisation dans un système de messagerie, et que type de données i faire mettre en œuvre dans OOP classique. c'est pour ça que c'est bon.

mais je ne définis jamais de classes qui vont au-delà de ces types de données génériques. J'écris plutôt des bibliothèques qui prennent des types de données génériques et qui fournissent la fonctionnalité dont vous avez besoin. toutes mes données d'affaires (dans votre cas, probablement des représentations de joueurs, des scènes, des outils et ainsi de suite) vont dans un conteneur de données génériques (en règle générale, dict s). Je sais qu'il y a des questions ouvertes avec cette façon d'architecturer les choses, mais la programmation est devenue tellement plus facile, tellement plus fluide puisque j'ai cassé la BS que la partie de la propagande OOP est (en dehors des choses vraiment utiles et agréables qu'une autre partie de POO est).Oh oui, et ai-je mentionné que tant que vous conservez vos données professionnelles dans des objets compatibles JSON, vous pouvez toujours les écrire et les ressusciter à partir du disque? ou les envoyer sur le fil de sorte que vous pouvez interagir avec des joueurs à distance? et comment incroyablement tordu l'activité de sérialisation peut devenir dans OOP classique si vous voulez faire cela (lire this pour la pointe de l'iceberg)? La plupart des détails techniques que vous devez connaître dans ce domaine sont totalement insignifiants pour le reste de votre vie.

2

Vous pouvez ajouter (ou modifier) ​​des fonctions intégrées Python et des classes en effectuant l'une des opérations suivantes, au moins dans Py 2.x. Par la suite, tout ce que vous ajouterez sera disponible pour tout le code par défaut, mais pas de manière permanente.

Clause de non-responsabilité: Faire ce genre de chose peut être dangereux en raison de possibles conflits de noms et problématique car il est extrêmement non-explicite. Mais, comme on dit, nous sommes tous des adultes ici, n'est-ce pas?

class MyCLass: pass 

# one way 
setattr(__builtins__, 'MyCLass', MyCLass) 

# another way 
import __builtin__ 
__builtin__.MyCLass = MyCLass 
+0

disons que vous avez intégré (singulier) et builtins (pluriel) ici. Je n'ai jamais compris la pensée qui a causé la différence entre les deux, et je pense que le singulier est parti dans py3.1, n'est-ce pas? quelqu'un qui veut commenter? – flow

+0

@flow: Voici ma conjecture. Comme le disent les docs "La plupart des modules ont le nom' __builtins__' (notez le 's') disponible dans le cadre de leurs globals ", donc le module' __builtin__' a reçu un nom (légèrement) différent de sorte qu'il puisse coexister dans le même namespace (comme ne pas cacher le premier ou vice-versa). – martineau

0

Une autre façon est de créer un singleton:

class Singleton(type): 
    def __init__(cls, name, bases, dict): 
     super(Singleton, cls).__init__(name, bases, dict) 
     cls.instance = None 

class GlobalClass(object): 
    __metaclass__ = Singleton 
    def __init__(): 
     pinrt("I am global and whenever attributes are added in one instance, any other instance will be affected as well.") 
Questions connexes