0
votes

Quand est-il approprié d'organiser du code en utilisant une classe avec python?

Bien que j'ai une bonne expérience en utilisant Python, j'ai constaté qu'il est parfois assez difficile de déterminer si des fonctions et des attributs pertinents devraient être mis à l'intérieur d'une classe. Plus spécifiquement, j'ai une fonction qui utilise les attributs de la classe et les fonctions suivantes utilisent séquentiellement la valeur renvoyée de la fonction précédente. Par exemple, fonction 1 -> fonction 2 -> fonction 3 et ainsi de suite avec chaque fonction renvoyant quelque chose.

Je souhaite comprendre s'il est logique d'utiliser une classe dans des situations comme celle-ci, car elle est une occurrence commune avec moi. Je veux m'assurer que l'objet (table de vente) est créé de manière logique et propre. P>

Jusqu'à présent, j'ai créé juste une classe simple avec certains attributs et méthodes d'instance. Je ne sais pas comment je peux y aller sinon. J'ai regardé de nombreux postes sur des piles, des articles et de nombreuses autres ressources. Je crois avoir une bonne compréhension du but d'une classe mais moins quand il est approprié de l'utiliser. P>

Pour être clair, je ne demande pas d'aide sur les fonctions elles-mêmes ou de leur logique (bien que j'apprécie toutes les suggestions!). Je veux juste savoir si l'utilisation d'une classe est la voie à suivre. Je n'ai compris aucun code dans les fonctions, car je ne pense pas que leur logique est pertinente pour ma question (je peux ajouter si nécessaire!) P>

class SalesTable:

    def __init__(self, banner, start_year, start_month, end_year, end_month):
        """These attributes act as filters when searching for the relevant data."""
        self.banner = banner
        self.start_year = start_year
        self.start_month = start_month
        if not end_year:
            self.end_year = start_year
        else:
            self.end_year = end_year
        if not end_month:
            self.end_month = start_month
        else:
            self.end_month = end_month

    def sales_periods(self):
        """Will create a dict with a key as the year and each year will have a list of months as the value. The
        stated attributes are used ONLY here as filters to determine what years and months are included"""
        pass

    def find_sales_period_csv(self):
        """Using the dictionary returned from the function above, will search through the relevant directories and 
        subdirectories to find all the paths for individual csvs where the sales data is stored as determined by the
        value in the dictionary and store the paths in a list"""
        pass

    def csv_to_df(self):
        """Using the list returned from the function above, will take each csv path in the list and convert them into a
        dataframe and store those dateframes in another list"""
        pass

    def combine_dfs(self):
        """Using the list return from the function above, will concatenate all dfs into a single dataframe"""

    def check_data(self):
        """Maybe do some checking here to ensure all relevant data concatenated properly (i.e total row count etc.)"""


3 commentaires

Déplacez n'importe quelle méthode qui n'utilise pas auto hors de la classe. Fondamentalement, vous posez des questions sur la composition, f (g (h (x))) , qui ne dépend de aucun des f , g , ou h être des méthodes ou des fonctions régulières. Est-ce que autre chose que sales_periods utilise les attributs salestables ?


Et, si, après éjecter toutes les fonctions "régulières" de votre classe, si vous n'êtes laissé avec rien que __ init __ et une autre méthode, il est bon de savoir que l'autre méthode doit aussi Il suffit d'être une fonction qui prend les paramètres supplémentaires à partir de la méthode Message Mod-SpunCt __ init __ et la classe doit être supprimée.


Oui, seule la fonction Sales_Periods prend les attributs. Il serait donc correct de dire qu'il n'a aucun sens d'utiliser une classe lorsque plusieurs méthodes utilisent les attributs d'instance spécifiés. Merci pour votre explication, c'était vraiment clair!


5 Réponses :


0
votes

Si un tas de données et de fonctions semblent vivre ensemble, ce qui signifie que vous les appelez généralement à la fois en même temps, vous avez une bonne raison de penser que vous pourriez avoir un objet sur vos mains.

Une autre bonne raison est si il y a un nom naturel pour l'objet. Bizarre, je sais, mais c'est vraiment un principe de guidage utile.

lire sur Solid peut également vous donner des aliments à la pensée.


1 commentaires

Merci pour le conseil! C'est une "table" alors je pensais que cela semblait naturel, bien qu'il semble plus abstrait que réel. Je vais prendre une lecture, merci pour le lien!



3
votes

Idéalement, il y a deux utilisations principales pour une classe :

1) pour prévenir la répétition. Si vous créez le même objet plusieurs fois plus que cela devrait être dans une classe.

2) Pour regrouper les choses ensemble. Il est beaucoup plus facile de lire le code de quelqu'un si toutes les fonctions et attributs associés sont regroupés. Cela fait également la maintenabilité et la portabilité plus facile.

Il est courant que les méthodes s'appliquent mutuellement dans une classe puisque les méthodes ne doivent idéalement pas être supérieures à 30 lignes (bien que différents groupes ont des normes différentes). Si vous appelez des méthodes uniquement à partir d'une classe que cette méthode doit être privée et vous devez ajouter __ (deux soulignements) avant cette méthode.


4 commentaires

Ainsi, l'objet de la table de vente ne sera créé qu'une seule fois, en fonction du numéro 1, j'imagine qu'une classe serait inappropriée. Cependant, mes fonctions et attribuées sont liées en ce que vous avez besoin des attributs pour la première fonction et la première fonction pour le second, etc., donc je pense que le numéro 2 est applicable. Est-ce juste une question de jugement? Je garderai aussi les soulignements à l'esprit! Merci!


@Oskituranoglu typiquement, oui c'est une question de jugement. Si l'une des deux utilisations s'applique, vous devriez probablement utiliser une classe. Vous constaterez que par encapsulant votre code que vous aurez plus facile à fixer des bugs et de modifier depuis toute la logique se fait par .


Dans mon expérience personnelle, j'essaie toujours de mettre mon code dans des classes. Il y a très peu d'instances lorsque je n'utilise pas de classe.


La seule exception est si je fais un script rapide / court pour faire quelque chose de simple, comme Renommer tous les fichiers d'un répertoire.



0
votes

Les gens nouveaux à OOP ont tendance à créer trop de cours (je sais que j'ai fait au début). Un problème avec celui-ci est la lisibilité du code: lorsque le code utilise une classe personnalisée, il est souvent nécessaire de lire la définition de la classe pour déterminer ce que la classe est censée faire. Si le code utilise des types intégrés uniquement, il est généralement plus facile de comprendre. En outre, l'état interne complexe qui est une caractéristique naturelle des classes est souvent une source de bogues subtils et rend le code plus difficile à raisonner.


1 commentaires

Je vois. Donc, je dois réellement créer 4 tables, toutes différentes en termes de données, mais éventuellement tous doivent être des cadres de données individuellement (même sortie que ci-dessus). Je pensais faire un module séparé pour chaque table et chaque module aurait une classe pour créer une instance d'une facture faciliterait les modifications et la transférabilité. Diriez-vous que simplement faire 4 modules différents sans cours, ne pas aller?



0
votes

Ce livre est assez utile

Chacune de vos méthodes ci-dessus semble être liée à la classe. Donc, disons que vous aviez défini un tas de fonctions en dehors de la classe, et vous passez le même ensemble de dix variables que des arguments à chacun d'eux. Ce serait un signe qu'ils devraient être dans la classe. Accéder à de trop nombreuses variables et les transmettre à d'autres fonctions comme arguments au lieu de les avoir comme des attributs de classe qui sont modifiés à l'intérieur de chacune des méthodes seraient un signe que vous n'aviez pas réussi à tirer parti de l'un des classes. Dans ce livre, je me souviens d'une section où ils sont entrés en détail sur divers signes que votre code a besoin d'OOP.


0 commentaires

2
votes

Depuis seulement Sales_Periods utilise réellement les attributs d'instance et renvoie un dict , pas une autre instance de salestable , toutes les autres méthodes peuvent être déplacé de la classe et défini comme des fonctions régulières: xxx

et vous les appellerez tous dans une mode chaînée: xxx

Regardez maintenant votre classe: vous avez seulement deux méthodes, __ init __ et Sales_Periods . Sauf si __ init __ fait quelque chose de coûteux que vous ne voulez pas répéter (et que vous appelleriez sales_periods sur la même instance plusieurs fois), la classe entière peut être réduite à un seul. Fonction qui combine __ init __ et le Sales_Period méthode: xxx


3 commentaires

Cela a du sens. Serait-il inapproprié d'utiliser des méthodes statiques comme alternative, puisqu'elles n'utilisent aucun attribut?


Vous pouvez, mais ces fonctions ne semblent pas avoir quelque chose à voir avec salestable sinon. Les méthodes statiques sont généralement moins budgétaires, ne sont généralement définies que comme des assistants pour des méthodes «régulières» ou du moins quelque peu liées à la classe, sinon une instance particulière de la classe.


Gotcha, donc si disait que j'avais une autre fonction qui a fait quelque chose à ou pour sales_Periods (comme peut-être une sorte de formatage de et.c) et il n'a pas utilisé les attributs d'instance, il serait plus approprié de l'avoir comme une méthode statique.