In Ruby liegen lokale Variablenreferenzen nur innerhalb des definierten Bereichs.
ruby
a = 1
def func
puts a
end
func #=> error (undefined local variable)
In Python kann auch vom Nachkommenbereich aus darauf verwiesen werden.
python
a = 1
def func():
print(a)
func() #=> 1
Selbst wenn der definierte Bereich verschwindet, wird die lokale Variable nicht gelöscht, solange auf sie vom untergeordneten Bereich verwiesen wird. Sie können diese Eigenschaft auch anwenden, um so etwas wie eine Klasse mit Instanzvariablen zu erstellen. Diese klassenähnliche instanzmethode wird als Abschluss bezeichnet.
python
def cls(): #Klassenartig
x = {} #Instanz variabelartig
def a(): #Schließung
x['a'] = 1
def b(): #Schließung
x['b'] = 1
def g(): #Schließung
return x
return a, b, g
#Der Bereich von x verschwindet, wenn der Funktionsaufruf endet
a, b, g = cls()
a(); b();
print(g()) #=> {'a': 1, 'b': 1}
Selbst bei Rubin, wenn es eine Konstante ist, gibt es einen Verschluss. Bevor ich ein Beispiel gebe, möchte ich ein wenig Rubin erklären.
In Ruby werden Konstanten und Variablen auf völlig unterschiedliche Weise verwaltet. Der Umfang der Variablen ändert sich abhängig von der Funktionsdefinition (ohne Do-Syntax usw.) und der Klassendefinition. Andererseits ändert sich der Umfang der Konstanten nur in Moduldefinitionen (einschließlich Klassendefinitionen). Und die Suche nach Konstanten
Wenn ein Nest vorhanden ist, wird diese Konstante nacheinander in den Elementen dieses Nestes durchsucht. (Aus Automatisches Laden und Neuladen von Konstanten)
Dies geschieht auf diese Weise (im Fall einer offenen Klasse wird jedoch nicht gesucht). Das heißt, Konstanten können auch aus dem Nachkommenbereich referenziert werden.
Mit dieser Eigenschaft können Sie einen Abschluss vornehmen.
ruby
module A
X = 'x' #Instanz variabelartig
module B #Klassenartig
def show #Schließung
puts X
end
end
end
class C #Instanzartig
extend A::B
end
C.show #=> x
Ein Verweis auf eine lokale Variable, deren Definition fehlt, kann tatsächlich ein Instanzmethodenaufruf ohne Argumente sein. Ich treffe mich sehr oft.
ruby
class C
def hoge #Instanzmethode
return "hoge"
end
def show
fuga = "fuga"
puts hoge #Instanzmethodenaufruf
puts fuga #Lokale Variablenreferenz
end
end
Darüber hinaus erleichtern die Klassenmakros attr_accessor, attr_reader und attr_writer das Erstellen von Instanzmethoden, die wie lokale Variablen aussehen. Die Substanz der Variablen ist eine Instanzvariable, deren Name im Argumentensymbol mit @ vorangestellt ist.
ruby
class C
attr_accessor :hoge #Instanzvariable@Hoge ist die Substanz
def initialize
self.hoge = "hoge" #Instanzmethode hoge=Anruf
end
def show
fuga = "fuga" #Definieren Sie die lokale Variable fuga&Initialisieren
puts hoge #Rufen Sie die Instanzmethode hoge auf
puts fuga #Siehe lokale Variable fuga
end
end
C.new.methods.include?(:hoge) #=> true
C.new.methods.include?(:hoge=) #=> true
Im Fall von Python ist es leicht zu unterscheiden, da der Aufruf der Instanzmethode selbst angehängt ist und die Klammern des Funktionsaufrufs nicht weggelassen werden können. Stattdessen ist es schwieriger, zwischen Instanzmethodenaufrufen und Klassenmethodenaufrufen zu unterscheiden.
python
class C:
def hoge(self):
return "hoge"
@classmethod
def piyo(cls):
return "piyo"
def show(self):
fuga = "fuga"
print(self.hoge()) #Instanzmethodenaufruf
print(fuga) #Lokale Variablenreferenz
print(self.piyo()) #Klassenmethodenaufruf
(Hinzugefügt basierend auf Kommentaren von scivola)
Beim Aufruf der Instanzmethode hoge = im vorherigen Beispiel wurde self als Empfänger angegeben.
Rubin (Repost)
class C
attr_accessor :hoge
def initialize
self.hoge = "hoge" #Hier
end
...
Dies liegt daran, dass, wenn Sie nicht self angeben, dies als Definition der lokalen Variablen hoge behandelt wird.
ruby
class C
attr_accessor :hoge
def initialize
hoge = "hoge" #Definition der lokalen Variablen hoge
end
def show
puts hoge
end
end
C.new.show #=> nil
Das gleiche kann mit Python passieren. Beispielsweise kann im Fall der zuvor eingeführten Klasse nicht die Instanzvariable nicht aktualisiert werden.
python
def cls():
x = {} #Benimm dich wie eine Instanzvariable
def u():
x = 'updated' #Eigentlich ist die Definition der lokalen Variablen x
def g():
return x
return u, g
#Der Bereich von x verschwindet, wenn der Funktionsaufruf endet
u, g = cls()
u();
print(g()) #=> {}
Sie können self in Python nicht auslassen, damit Sie beim Aktualisieren von Instanzvariablen keinen Fehler machen.
python
class C:
def __init__(self):
self.hoge = "not updated"
def wrong(self):
hoge = "updated" #Leicht zu erkennende Fehler
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
ruby
module M
def show
puts @message
end
end
class C
include M
def initialize
@message = "accessible"
end
end
C.new.show #=> accessible
Mit Python können Sie etwas Ähnliches tun.
python
class S:
def show(self):
print(self.message)
class C(S):
def __init__(self):
self.message = "accessible"
C().show() #=> accessible
In Ruby können Sie die Klammern des Funktionsaufrufs weglassen. Daher ist es nicht möglich, einer Variablen eine Funktion zuzuweisen.
ruby
def func
return "called"
end
a = func #Rufen Sie die Funktion func auf
puts a #=> called
Object # -Methode Mit der Instanzmethode können Sie eine Funktion in ein Methodenobjekt konvertieren und einer Variablen zuweisen.
ruby
def func
return "called"
end
a = method(:func) #Zuweisung von Methodenobjekten
puts a #=> #<Method: main.func>
puts a.call #=> called
Andererseits können Sie in Python Variablen Funktionen zuweisen.
python
def func():
return "called"
a = func #Zuordnung der Funktion func
print(func) #=> <function func at 0x...>