Différence entre Ruby et Python en termes de variables

Portée de la variable locale

Dans ruby, les références de variables locales sont uniquement dans la portée définie.

ruby


a = 1

def func
  puts a
end

func #=> error (undefined local variable)

En python, il peut également être référencé à partir de la portée descendante.

python


a = 1

def func():
  print(a)

func() #=> 1

De plus, même si la portée définie disparaît, la variable locale ne sera pas supprimée tant qu'elle est référencée à partir de la portée descendante. Vous pouvez également appliquer cette propriété pour créer quelque chose comme une classe avec des variables d'instance. Cette instance semblable à une méthode s'appelle une fermeture.

python


def cls(): #Comme une classe
  x = {} #Instance de type variable

  def a(): #Fermeture
    x['a'] = 1

  def b(): #Fermeture
    x['b'] = 1

  def g(): #Fermeture
    return x

  return a, b, g

#La portée de x disparaît lorsque l'appel de fonction se termine
a, b, g = cls()
a(); b();
print(g()) #=> {'a': 1, 'b': 1}

Fermeture constante

Même avec le rubis, si c'est une constante, il y a une fermeture. Avant de donner un exemple, laissez-moi vous expliquer un peu rubis.

Dans ruby, les constantes et les variables sont gérées de manière complètement différente. La portée des variables change en fonction de la définition de la fonction (sans inclure la syntaxe do, etc.) et de la définition de la classe. D'autre part, la portée des constantes ne change que dans les définitions de module (y compris les définitions de classe). Et la recherche de constantes

Si un nid existe, cette constante sera recherchée séquentiellement dans les éléments de ce nid. (Depuis Chargement et rechargement automatique des constantes)

C'est fait comme ça (cependant, dans le cas d'une classe ouverte, elle n'est pas recherchée). Autrement dit, les constantes peuvent également être référencées à partir de la portée descendante.

Vous pouvez utiliser cette propriété pour effectuer une fermeture.

ruby


module A
  X = 'x' #Instance de type variable

  module B #Comme une classe
    def show #Fermeture
      puts X
    end
  end
end

class C #Comme une instance
  extend A::B
end

C.show #=> x

Méthode d'instance qui ressemble à une variable locale

Une référence à une variable locale dont la définition est manquante peut en fait être un appel de méthode d'instance sans argument. Je me rencontre très souvent.

ruby


class C
  def hoge #Méthode d'instance
    return "hoge"
  end

  def show
    fuga = "fuga"

    puts hoge #Appel de méthode d'instance
    puts fuga #Référence de variable locale
  end
end

De plus, les macros de classe attr_accessor, attr_reader et attr_writer facilitent la création de méthodes d'instance qui ressemblent à des variables locales. La substance de la variable est une variable d'instance dont le nom est précédé de @ dans le symbole d'argument.

ruby


class C
  attr_accessor :hoge #Variable d'instance@hoge est la substance

  def initialize
    self.hoge = "hoge" #Méthode d'instance hoge=Appel
  end

  def show
    fuga = "fuga" #Définir la variable locale fuga&Initialisation

    puts hoge #Appelez la méthode d'instance hoge
    puts fuga #Voir la variable locale fuga
  end
end

C.new.methods.include?(:hoge) #=> true
C.new.methods.include?(:hoge=) #=> true

Dans le cas de python, il est facile de le distinguer car l'appel de méthode d'instance est auto-attaché et les parenthèses de l'appel de fonction ne peuvent pas être omises. Au lieu de cela, il est plus difficile de faire la distinction entre les appels de méthode d'instance et les appels de méthode de classe.

python


class C:
  def hoge(self):
    return "hoge"

  @classmethod
  def piyo(cls):
    return "piyo"

  def show(self):
    fuga = "fuga"

    print(self.hoge()) #Appel de méthode d'instance
    print(fuga) #Référence de variable locale

    print(self.piyo()) #Appel de méthode de classe

Écraser avec des variables locales

(Ajouté en fonction des commentaires de scivola)

Lors de l'appel de la méthode d'instance hoge = dans l'exemple précédent, self a été spécifié comme récepteur.

rubis (republier)


class C
  attr_accessor :hoge

  def initialize
    self.hoge = "hoge" #ici
  end
  ...

En effet, si vous ne spécifiez pas self, il sera traité comme la définition de la variable locale hoge.

ruby


class C
  attr_accessor :hoge

  def initialize
    hoge = "hoge" #Définition de la variable locale hoge
  end

  def show
    puts hoge
  end
end

C.new.show #=> nil

La même chose peut arriver avec python. Par exemple, dans le cas du type de classe introduit précédemment, le type de variable d'instance ne peut pas être mis à jour.

python


def cls():
  x = {} #Se comporter comme une variable d'instance

  def u():
    x = 'updated' #En fait, la définition de la variable locale x

  def g():
    return x

  return u, g

#La portée de x disparaît lorsque l'appel de fonction se termine
u, g = cls()
u();
print(g()) #=> {}

Vous ne pouvez pas vous omettre en python, vous ne ferez donc pas d'erreur lors de la mise à jour des variables d'instance.

python


class C:
  def __init__(self):
    self.hoge = "not updated"

  def wrong(self):
    hoge = "updated" #Erreurs faciles à remarquer

  def correct(self):
    self.hoge = "updated"

  def show(self):
    #print(hoge) #=> error (name 'hoge' is not defined)
    print(self.hoge)

c = C()
c.wrong(); c.show(); #=> not updated
c.correct(); c.show(); #=> updated

Reportez-vous à la variable d'instance à inclure

ruby


module M
  def show
    puts @message
  end
end

class C
  include M
  def initialize
    @message = "accessible"
  end
end

C.new.show #=> accessible

Vous pouvez faire quelque chose de similaire avec python.

python


class S:
  def show(self):
    print(self.message)

class C(S):
  def __init__(self):
    self.message = "accessible"

C().show() #=> accessible

Attribuer une fonction à une variable

Dans ruby, vous pouvez omettre les parenthèses de l'appel de fonction. Par conséquent, il n'est pas possible d'affecter une fonction à une variable.

ruby


def func
  return "called"
end

a = func #Appelez la fonction func
puts a #=> called

Méthode Object # Vous pouvez utiliser la méthode d'instance pour convertir une fonction en objet Method et l'assigner à une variable.

ruby


def func
  return "called"
end

a = method(:func) #Affectation d'objet de méthode
puts a #=> #<Method: main.func>
puts a.call #=> called

D'autre part, en python, vous pouvez affecter des fonctions à des variables.

python


def func():
  return "called"

a = func #Affectation de la fonction func
print(func) #=> <function func at 0x...>

Recommended Posts

Différence entre Ruby et Python en termes de variables
[python] Différence entre variable et self. Variable dans la classe
Différence entre Ruby et Python Split
Différence entre list () et [] en Python
Différence entre == et est en python
Différences entre Ruby et Python dans la portée
différence entre les instructions (instructions) et les expressions (expressions) en Python
Différence entre @classmethod et @staticmethod en Python
Différence entre append et + = dans la liste Python
Différence entre non local et global en Python
À propos de la différence entre "==" et "is" en python
[python] Calcul des mois et des années de différence de date / heure
Différence entre return, return None et no return description en Python
Différences dans la façon d'écrire du code source externe entre Ruby et Python
Différence entre la série python2 et la série python3 dict.keys ()
[Python] Différence entre fonction et méthode
Python - Différence entre exec et eval
[Python] Différence entre randrange () et randint ()
[Python] Différence entre trié et trié (Colaboratoire)
Module Python num2words Différence de comportement entre l'anglais et le russe
Méthode de concaténation de liste en python, différence entre list.extend () et opérateur «+»
Ordre de référence des variables de classe et des variables d'instance dans "self. Variables de classe" en Python
[Python] Forces et faiblesses de DataFrame en termes de temps requis
Différence d'authenticité entre Python et JavaScript
Grande différence dans les performances de ruby, python, httpd
Différences entre la syntaxe Python et Java
Différences dans la relation entre PHP et Python enfin et quitter
[Python] Différence entre la méthode de classe et la méthode statique
[Python Iroha] Différence entre List et Tuple
[python] Différence entre la sortie rand et randn
Différences de multithreading entre Python et Jython
Fonction pour ouvrir un fichier en Python3 (différence entre open et codecs.open et comparaison de vitesse)
Différence entre Ruby et Python (syntaxe de base)
Projet Euler # 1 "Multiple de 3 et 5" en Python
Résumé de la correspondance entre les opérations de tableau ruby et python
La réponse de "1/2" est différente entre python2 et 3
Spécification de la plage des tableaux ruby et python
[Python] Chapitre 02-01 Bases des programmes Python (opérations et variables)
Projet Euler # 6 "Différence de somme des carrés" en Python
À propos des copies superficielles et profondes de Python / Ruby
Explication de la distance d'édition et de l'implémentation en Python
Comparaison de Python et Ruby (Environment / Grammar / Literal Edition)
Ruby, Python et carte
Python et Ruby se séparent
Différences dans le traitement des chaînes entre Python, Ruby, JS et PHP (combinaison et expansion de variables)
J'ai comparé la vitesse des expressions régulières en Ruby, Python et Perl (version 2013)
Divise la chaîne de caractères par le nombre de caractères spécifié. En Ruby et Python.
"Régression linéaire" et "Version probabiliste de la régression linéaire" en Python "Régression linéaire de Bayes"
Traitement pleine largeur et demi-largeur des données CSV en Python
Calcul de l'écart type et du coefficient de corrélation en Python
Simulation AtCoder ARC080 D résolue avec Ruby et Python
[Ruby vs Python] Comparaison de référence entre Rails et Flask
Le comportement de retrait de json.dumps est différent entre python2 et python3
Ruby, exécution de fragments de code Python de la sélection dans Emacs
Conversion mutuelle entre JSON et YAML / TOML en Python
Communication inter-processus entre Ruby et Python (file d'attente de messages POSIX)
Comparez la "relation log et infini" avec Gauche (0.9.4) et Python (3.5.1)