Comment éviter le " moi " explicite en Python?

j'ai appris Python en suivant quelques tutoriels pygame .

J'y ai trouvé l'utilisation extensive du mot clé self , et venant d'un fond principalement Java, je trouve que je continue à oublier de taper self . Par exemple , au lieu de self.rect.centerx , Je taperais rect.centerx , parce que, pour moi, rect est déjà une variable membre de la catégorie.

le parallèle Java que je peux imaginer pour cette situation est d'avoir à préfixer toutes les références aux variables membres avec ce .

suis-je coincé en préfixant toutes les variables membres avec self , ou y a-t-il un moyen de les déclarer qui me permettrait d'éviter d'avoir à le faire?

même si ce que je suggère n'est pas pythonique , j'aimerais savoir si c'est possible.

j'ai jeté un oeil à ces questions connexes, mais ils ne répondent pas tout à fait ce que je suis après:

94
demandé sur Community 2009-12-31 08:50:07

10 réponses

Python nécessite de spécifier soi-même. le résultat est qu'il n'y a jamais de confusion sur ce qui est un membre et ce qui ne l'est pas, même sans la définition complète de la classe visible. Cela conduit à des propriétés utiles, telles que: vous ne pouvez pas ajouter des membres qui font accidentellement de l'ombre à des non-membres et cassent ainsi le code.

un exemple extrême: vous pouvez écrire une classe sans aucune connaissance des classes de base qu'elle pourrait avoir, et toujours savoir si vous accédez membre ou non:

class A(some_function()):
  def f(self):
    self.member = 42
    self.method()

C'est le code complet ! (some_function renvoie le type utilisé comme base.)

un autre, où les méthodes d'une classe sont composées dynamiquement:

class B(object):
  pass

print B()
# <__main__.B object at 0xb7e4082c>

def B_init(self):
  self.answer = 42
def B_str(self):
  return "<The answer is %s.>" % self.answer
# notice these functions require no knowledge of the actual class
# how hard are they to read and realize that "members" are used?

B.__init__ = B_init
B.__str__ = B_str

print B()
# <The answer is 42.>

rappelez-vous, ces deux exemples sont extrêmes et vous ne les verrez pas tous les jours, pas plus que je ne suggère que vous devriez souvent écrire du code comme ceci, mais ils montrent clairement les aspects de l'être de soi explicitement requis.

83
répondu 2009-12-31 06:27:25

en fait self n'est pas un mot-clé, c'est juste le nom donné conventionnellement au premier paramètre des méthodes d'instance en Python. Et ce premier paramètre ne peut pas être ignoré, car c'est le seul mécanisme dont dispose une méthode pour savoir sur quelle instance de votre classe elle est appelée.

23
répondu Michał Marczyk 2009-12-31 05:56:37

Vous pouvez utiliser n'importe quel nom que vous voulez, par exemple

class test(object):
    def function(this, variable):
        this.variable = variable

ou même

class test(object):
    def function(s, variable):
        s.variable = variable

mais vous êtes bloqué avec l'utilisation d'un nom pour le scope.

Je ne vous recommande pas d'utiliser quelque chose de différent pour vous-même à moins que vous ayez une raison convaincante, car il ferait étranger pour les Pythonistas expérimentés.

21
répondu Esteban Küber 2009-12-31 06:18:24

oui, vous devez toujours spécifier self , parce qu'explicites est mieux qu'implicite, selon python philosophie.

vous découvrirez aussi que la façon dont vous programmez en python est très différente de la façon dont vous programmez en java, donc l'utilisation de self a tendance à diminuer parce que vous ne projetez pas tout à l'intérieur de l'objet. Plutôt, vous faites un plus grand usage de la fonction de niveau de module, qui peut être mieux testé.

soit dit en passant. Je détesté au début, maintenant je déteste le contraire. idem pour la commande de débit entraînée par le retrait.

9
répondu Stefano Borini 2009-12-31 05:59:37

self fait partie de la syntaxe python pour accéder aux membres des objets, donc j'ai bien peur que vous soyez coincés avec

5
répondu Charles Ma 2009-12-31 05:53:27

Le "soi" est le classique de l'espace réservé de l'objet en cours d'instance d'une classe. Il est utilisé lorsque vous voulez renvoyer à la propriété ou au champ ou à la méthode de l'objet à l'intérieur d'une classe comme si vous faisiez référence à "lui-même". Mais pour le rendre plus court, quelqu'un dans le domaine de programmation de Python a commencé à utiliser "self" , d'autres royaumes utilisent "this" mais ils en font un mot-clé qui ne peut pas être remplacé. J'ai plutôt utilisé "son" pour augmenter la lisibilité du code. C'est une des bonnes choses en Python - vous avez un liberté de choisir votre propre emplacement pour l'instance de l'objet autre que "soi". Exemple pour moi-même:

class UserAccount():    
    def __init__(self, user_type, username, password):
        self.user_type = user_type
        self.username = username            
        self.password = encrypt(password)        

    def get_password(self):
        return decrypt(self.password)

    def set_password(self, password):
        self.password = encrypt(password)

maintenant nous remplaçons 'self' par 'its':

class UserAccount():    
    def __init__(its, user_type, username, password):
        its.user_type = user_type
        its.username = username            
        its.password = encrypt(password)        

    def get_password(its):
        return decrypt(its.password)

    def set_password(its, password):
        its.password = encrypt(password)

qui est plus lisible maintenant?

5
répondu LEM Adane 2015-11-29 22:16:33

les réponses Précédentes sont essentiellement des variantes de "vous ne pouvez pas" ou "vous ne devriez pas". Bien que je sois d'accord avec ce dernier sentiment, la question demeure techniquement sans réponse.

en outre, il y a des raisons légitimes pour lesquelles quelqu'un pourrait vouloir faire quelque chose dans le sens de ce que la question actuelle pose. Une chose que je croise parfois de longues équations mathématiques où l'utilisation de noms longs rend l'équation méconnaissable. Voici quelques façons dont vous pourriez faites ceci dans un exemple en conserve:

import numpy as np
class MyFunkyGaussian() :
    def __init__(self, A, x0, w, s, y0) :
        self.A = float(A)
        self.x0 = x0
        self.w = w
        self.y0 = y0
        self.s = s

    # The correct way, but subjectively less readable to some (like me) 
    def calc1(self, x) :
        return (self.A/(self.w*np.sqrt(np.pi))/(1+self.s*self.w**2/2)
                * np.exp( -(x-self.x0)**2/self.w**2)
                * (1+self.s*(x-self.x0)**2) + self.y0 )

    # The correct way if you really don't want to use 'self' in the calculations
    def calc2(self, x) :
        # Explicity copy variables
        A, x0, w, y0, s = self.A, self.x0, self.w, self.y0, self.s
        sqrt, exp, pi = np.sqrt, np.exp, np.pi
        return ( A/( w*sqrt(pi) )/(1+s*w**2/2)
                * exp( -(x-x0)**2/w**2 )
                * (1+s*(x-x0)**2) + y0 )

    # Probably a bad idea...
    def calc3(self, x) :
        # Automatically copy every class vairable
        for k in self.__dict__ : exec(k+'= self.'+k)
        sqrt, exp, pi = np.sqrt, np.exp, np.pi
        return ( A/( w*sqrt(pi) )/(1+s*w**2/2)
                * exp( -(x-x0)**2/w**2 )
                * (1+s*(x-x0)**2) + y0 )

g = MyFunkyGaussian(2.0, 1.5, 3.0, 5.0, 0.0)
print(g.calc1(0.5))
print(g.calc2(0.5))
print(g.calc3(0.5))

le troisième exemple - c.-à-d. utiliser for k in self.__dict__ : exec(k+'= self.'+k) est fondamentalement ce que la question demande réellement, mais laissez-moi être clair que je ne pense pas que ce soit généralement une bonne idée.

pour plus d'information, et des façons d'itérer à travers des variables de classe, ou même des fonctions, voir les réponses et la discussion de cette question . Pour une discussion d'autres façons de nommer dynamiquement des variables, et pourquoi c'est généralement pas une bonne idée voir ce billet de blog .

4
répondu argentum2f 2018-03-15 19:13:19

oui, le moi est ennuyeux. Mais, est-il mieux?

class Test:

    def __init__(_):
        _.test = 'test'

    def run(_):
        print _.test
1
répondu 2013-04-25 02:48:21

en fait, vous pouvez utiliser la recette "implicite" de la présentation D'Armin Ronacher "5 ans de mauvaises idées" ( google it).

c'est une recette très intelligente, comme presque tout D'Armin Ronacher, mais je ne pense pas que cette idée est très attrayante. Je pense que je préférerais explicite ce en C#/Java.

mise à jour. Lien vers "recette de la mauvaise idée": https://speakerdeck.com/mitsuhiko/5-years-of-bad-ideas?slide=58

1
répondu Ingaz 2018-04-06 12:31:38

De: l'Autonomie de l'Enfer Plus dynamique des fonctions.

...une approche hybride fonctionne mieux. Toutes vos méthodes de classe qui en fait do computation devrait être déplacé dans les fermetures, et les extensions pour nettoyer la syntaxe devraient être conservées dans les classes. Mettez les fermetures dans les classes, traitant la classe comme un espace de noms. Les fermetures sont essentiellement des fonctions statiques, et ne nécessitent donc pas de selfs*, même dans la classe...

0
répondu user5554473 2015-11-12 17:37:57