In Python und Ruby ist die Zuweisung im Gegensatz zu PHP keine Kopie, und die Zuweisung bedeutet "Erstellen einer Einschränkung zwischen dem Ziel und dem Objekt". Es war schwierig, die Bedeutung von "Schaffung einer Beschränkung zwischen dem Ziel und dem Objekt" zu verstehen, und ich habe es als Memorandum belassen, um das Verständnis der Bedeutungen von "unveränderlich" und "veränderlich" basierend auf der Stichprobe zu vertiefen. Hier wurden Python3.6.2 und Ruby2.4.1 verwendet.
Aus den Ergebnissen von Python 3.6 und Ruby 2.4 geht hervor, dass sich die "ID" von "a" ändert, wenn die Variable "a" manipuliert wird, und sie ist unveränderlich (kann nicht geändert werden), da sie für das ganzzahlige Objekt "3" nicht geändert werden kann. Hier wird ein solches Objekt der Einfachheit halber als unveränderliches Objekt behandelt.
a = 3
print("id_3:%d, id_a:%d" % (id(3), id(a)))
b = a
print("id_b:%d" % id(b))
a += 1
print("id_3:%d, id_4:%d, id_a:%d, id_b:%d" % (id(3), id(4), id(a), id(b)))
Ausgabeergebnis
id_3:1623654960, id_a:1623654960
id_b:1623654960
id_3:1623654960, id_4:1623654992, id_a:1623654992, id_b:1623654960
Im Fall von Python3.6 gibt es Fälle, in denen sich die ID sogar für Ganzzahlen mit demselben Wert wie unten gezeigt unterscheidet.
class A:
def get(self):
print(id(99999999999999999999999999999))
class B:
def get(self):
print(id(99999999999999999999999999999))
A().get()
B().get()
Ausgabeergebnis
2812564670744
2812564671464
a = 3
puts 'id_3:%d, id_a:%d' % [3.object_id, a.object_id]
b = a
puts 'id_b:%d' % [b.object_id]
a += 1
puts 'id_3:%d, id_4:%d, id_a:%d, id_b:%d' % [3.object_id, 4.object_id, a.object_id, b.object_id]
Ausgabeergebnis
id_3:7, id_a:7
id_b:7
id_3:7, id_4:9, id_a:9, id_b:7
Selbst im Fall von Ruby gibt es Fälle, in denen die "ID" auch für Ganzzahlen mit demselben Wert wie unten gezeigt unterschiedlich ist.
p 99999999999999999999999.object_id
p 99999999999999999999999.object_id
Ausgabeergebnis
25133964
25133856
Aus den Ergebnissen von Python 3.6 und Ruby 2.4 geht hervor, dass der Wert, selbst wenn er durch die Operation "a" geändert wird, dieselbe "ID" ist und in einen anderen Wert geändert werden kann. Das heißt, es ist veränderlich (veränderbar). Hier wird ein solches Objekt der Einfachheit halber als veränderliches Objekt behandelt. Wenn der Wert von "a" "b" zugewiesen wird, ist die "id" dieselbe. Wenn also der Wert durch Manipulieren von "a" geändert wird, ändert sich auch "b".
a = [1,2,3]
b = a
print("id_a:%d, id_b:%d" % (id(a), id(b)))
print(a, b)
a[1] = 4
print("id_a:%d, id_b:%d" % (id(a), id(b)))
print(a, b)
Ausgabeergebnis
id_a:4332032456, id_b:4332032456
[1, 2, 3] [1, 2, 3]
id_a:4332032456, id_b:4332032456
[1, 4, 3] [1, 4, 3]
a = [1,2,3]
b = a
puts 'id_a:%d, id_b:%d' % [a.object_id, b.object_id]
p a, b
a[1] = 4
puts 'id_a:%d, id_b:%d' % [a.object_id, b.object_id]
p a, b
Ausgabeergebnis
id_a:70131497645860, id_b:70131497645860
[1, 2, 3]
[1, 2, 3]
id_a:70131497645860, id_b:70131497645860
[1, 4, 3]
[1, 4, 3]
Im Fall eines veränderlichen Objekts, wie im obigen Beispiel, ist, wenn der Wert von "a" "b" zugewiesen ist, die "id" dieselbe. Wenn also der Wert durch Manipulieren von "a" geändert wird, "b" `Ändert sich auch. Sie müssen eine Kopie erstellen, um den Wert von "b" unabhängig von "a" zu machen. Im Fall der Liste oder des Arrays in diesem Beispiel kann dies durch Erstellen einer flachen Kopie realisiert werden. Im folgenden Beispiel ändert sich durch Erstellen einer flachen Kopie der Wert von "b" nicht, selbst wenn der Wert durch die Operation "a" geändert wird.
Eine flache Kopie kann durch Ersetzen der Funktion "copy.copy" oder "a [:]" erstellt werden.
import copy as cp
a = [1,2,3]
b = cp.copy(a)
print("id_a:%d, id_b:%d" % (id(a), id(b)))
print(a, b)
a[1] = 4
print("id_a:%d, id_b:%d" % (id(a), id(b)))
print(a, b)
b = a[:]
print("id_a:%d, id_b:%d" % (id(a), id(b)))
print(a, b)
a[1] = 3
print("id_a:%d, id_b:%d" % (id(a), id(b)))
print(a, b)
Ausgabeergebnis
id_a:4460690760, id_b:4460690888
[1, 2, 3] [1, 2, 3]
id_a:4460690760, id_b:4460690888
[1, 4, 3] [1, 2, 3]
id_a:4460690760, id_b:4460691272
[1, 4, 3] [1, 4, 3]
id_a:4460690760, id_b:4460691272
[1, 3, 3] [1, 4, 3]
Eine flache Kopie kann mit "Object.clone" oder "Object.dup" erstellt werden. Darüber hinaus [hier](https://ja.stackoverflow.com/questions/27101/ruby%E3%81%AEclone%E3%81%A8dup%E3%81%A8activerecord%E3%81%AEclone%E3%81% Das Verhalten unterscheidet sich von "ActiveModel.clone" und "ActiveModel.dup" von "Rails" wie A8dup% E3% 81% AF% E5% 88% A5% E7% 89% A9).
a = [1,2,3]
b = a.clone
puts 'id_a:%d, id_b:%d' % [a.object_id, b.object_id]
p a, b
a[1] = 4
puts 'id_a:%d, id_b:%d' % [a.object_id, b.object_id]
p a, b
b = a.dup
puts 'id_a:%d, id_b:%d' % [a.object_id, b.object_id]
p a, b
a[1] = 3
puts 'id_a:%d, id_b:%d' % [a.object_id, b.object_id]
p a, b
Ausgabeergebnis
id_a:70245067666580, id_b:70245067666520
[1, 2, 3]
[1, 2, 3]
id_a:70245067666580, id_b:70245067666520
[1, 4, 3]
[1, 2, 3]
id_a:70245067666580, id_b:70245067665580
[1, 4, 3]
[1, 4, 3]
id_a:70245067666580, id_b:70245067665580
[1, 3, 3]
[1, 4, 3]
Im folgenden Beispiel, in dem das Element der Liste eine Liste und das Element des Arrays ein Array ist, gibt es beispielsweise ein anderes veränderbares Objekt aus dem veränderlichen Objekt, selbst wenn eine flache Kopie erstellt wird, indem "a [0]" manipuliert wird. Der Wert von "b [0]" wird geändert. Dies verhält sich für Python 3.6 und Ruby 2.4 gleich.
import copy as cp
a = [[1,2,3], "abc"]
b = cp.copy(a)
print("id_a:%d, id_b:%d" % (id(a), id(b)))
print("id_a[0]:%d, id_b[0]:%d" % (id(a[0]), id(b[0])))
print("id_a[1]:%d, id_b[1]:%d" % (id(a[1]), id(b[1])))
print(a, b)
a[0][1] = 4
a[1] = "def"
print("id_a:%d, id_b:%d" % (id(a), id(b)))
print("id_a[0]:%d, id_b[0]:%d" % (id(a[0]), id(b[0])))
print("id_a[1]:%d, id_b[1]:%d" % (id(a[1]), id(b[1])))
print(a, b)
b = a[:]
print("id_a:%d, id_b:%d" % (id(a), id(b)))
print("id_a[0]:%d, id_b[0]:%d" % (id(a[0]), id(b[0])))
print("id_a[1]:%d, id_b[1]:%d" % (id(a[1]), id(b[1])))
print(a, b)
a[0][1] = 3
a[1] = "abc"
print("id_a:%d, id_b:%d" % (id(a), id(b)))
print("id_a[0]:%d, id_b[0]:%d" % (id(a[0]), id(b[0])))
print("id_a[1]:%d, id_b[1]:%d" % (id(a[1]), id(b[1])))
print(a, b)
Ausgabeergebnis
id_a:4393106888, id_b:4393107272
id_a[0]:4393106760, id_b[0]:4393106760
id_a[1]:4391239728, id_b[1]:4391239728
[[1, 2, 3], 'abc'] [[1, 2, 3], 'abc']
id_a:4393106888, id_b:4393107272
id_a[0]:4393106760, id_b[0]:4393106760
id_a[1]:4392739984, id_b[1]:4391239728
[[1, 4, 3], 'def'] [[1, 4, 3], 'abc']
id_a:4393106888, id_b:4393112648
id_a[0]:4393106760, id_b[0]:4393106760
id_a[1]:4392739984, id_b[1]:4392739984
[[1, 4, 3], 'def'] [[1, 4, 3], 'def']
id_a:4393106888, id_b:4393112648
id_a[0]:4393106760, id_b[0]:4393106760
id_a[1]:4391239728, id_b[1]:4392739984
[[1, 3, 3], 'abc'] [[1, 3, 3], 'def']
a = [[1,2,3], "abc"]
b = a.clone
puts 'id_a:%d, id_b:%d' % [a.object_id, b.object_id]
puts 'id_a[0]:%d, id_b[0]:%d' % [a[0].object_id, b[0].object_id]
puts 'id_a[1]:%d, id_b[1]:%d' % [a[1].object_id, b[1].object_id]
p a, b
a[0][1] = 4
a[1] = "def"
puts 'id_a:%d, id_b:%d' % [a.object_id, b.object_id]
puts 'id_a[0]:%d, id_b[0]:%d' % [a[0].object_id, b[0].object_id]
puts 'id_a[1]:%d, id_b[1]:%d' % [a[1].object_id, b[1].object_id]
p a, b
b = a.dup
puts 'id_a:%d, id_b:%d' % [a.object_id, b.object_id]
puts 'id_a[0]:%d, id_b[0]:%d' % [a[0].object_id, b[0].object_id]
puts 'id_a[1]:%d, id_b[1]:%d' % [a[1].object_id, b[1].object_id]
p a, b
a[0][1] = 3
a[1] = "abc"
puts 'id_a:%d, id_b:%d' % [a.object_id, b.object_id]
puts 'id_a[0]:%d, id_b[0]:%d' % [a[0].object_id, b[0].object_id]
puts 'id_a[1]:%d, id_b[1]:%d' % [a[1].object_id, b[1].object_id]
p a, b
Ausgabeergebnis
id_a:70199714913920, id_b:70199714913860
id_a[0]:70199714913960, id_b[0]:70199714913960
id_a[1]:70199714913940, id_b[1]:70199714913940
[[1, 2, 3], "abc"]
[[1, 2, 3], "abc"]
id_a:70199714913920, id_b:70199714913860
id_a[0]:70199714913960, id_b[0]:70199714913960
id_a[1]:70199714912900, id_b[1]:70199714913940
[[1, 4, 3], "def"]
[[1, 4, 3], "abc"]
id_a:70199714913920, id_b:70199714912200
id_a[0]:70199714913960, id_b[0]:70199714913960
id_a[1]:70199714912900, id_b[1]:70199714912900
[[1, 4, 3], "def"]
[[1, 4, 3], "def"]
id_a:70199714913920, id_b:70199714912200
id_a[0]:70199714913960, id_b[0]:70199714913960
id_a[1]:70199714911480, id_b[1]:70199714912900
[[1, 3, 3], "abc"]
[[1, 3, 3], "def"]
Wenn ein veränderbares Objekt ein anderes veränderbares Objekt enthält, bei dem es sich um eine "flache Kopie ist nicht genug" handelt, müssen Sie eine tiefe Kopie anstelle einer flachen Kopie erstellen, um den Wert von "b" nach "a" vollständig zu kopieren. Es gibt.
Eine tiefe Kopie kann mit copy.deepcopy
erreicht werden.
import copy as cp
a = [[1,2,3], "abc"]
b = cp.deepcopy(a)
print("id_a:%d, id_b:%d" % (id(a), id(b)))
print("id_a[0]:%d, id_b[0]:%d" % (id(a[0]), id(b[0])))
print("id_a[1]:%d, id_b[1]:%d" % (id(a[1]), id(b[1])))
print(a, b)
a[0][1] = 4
a[1] = "def"
print("id_a:%d, id_b:%d" % (id(a), id(b)))
print("id_a[0]:%d, id_b[0]:%d" % (id(a[0]), id(b[0])))
print("id_a[1]:%d, id_b[1]:%d" % (id(a[1]), id(b[1])))
print(a, b)
Ausgabeergebnis
id_a:4306767304, id_b:4306767688
id_a[0]:4306767176, id_b[0]:4306773064
id_a[1]:4304900144, id_b[1]:4304900144
[[1, 2, 3], 'abc'] [[1, 2, 3], 'abc']
id_a:4306767304, id_b:4306767688
id_a[0]:4306767176, id_b[0]:4306773064
id_a[1]:4306400400, id_b[1]:4304900144
[[1, 4, 3], 'def'] [[1, 2, 3], 'abc']
Eine tiefe Kopie kann mit Marshal.load
und Marshal.dump
erreicht werden.
a = [[1,2,3], "abc"]
b = Marshal.load(Marshal.dump(a))
puts 'id_a:%d, id_b:%d' % [a.object_id, b.object_id]
puts 'id_a[0]:%d, id_b[0]:%d' % [a[0].object_id, b[0].object_id]
puts 'id_a[1]:%d, id_b[1]:%d' % [a[1].object_id, b[1].object_id]
p a, b
a[0][1] = 4
a[1] = "def"
puts 'id_a:%d, id_b:%d' % [a.object_id, b.object_id]
puts 'id_a[0]:%d, id_b[0]:%d' % [a[0].object_id, b[0].object_id]
puts 'id_a[1]:%d, id_b[1]:%d' % [a[1].object_id, b[1].object_id]
p a, b
Ausgabeergebnis
id_a:70274700700880, id_b:70274700700800
id_a[0]:70274700700940, id_b[0]:70274700700780
id_a[1]:70274700700900, id_b[1]:70274700700760
[[1, 2, 3], "abc"]
[[1, 2, 3], "abc"]
id_a:70274700700880, id_b:70274700700800
id_a[0]:70274700700940, id_b[0]:70274700700780
id_a[1]:70274700699900, id_b[1]:70274700700760
[[1, 4, 3], "def"]
[[1, 2, 3], "abc"]
In Ruby 2.4 wird das Zeichenfolgenliteral wie unten gezeigt zu einem veränderlichen Objekt. Soweit auf hier verwiesen wird, ist das String-Literal ein unveränderliches Objekt in Ruby3.
In Python3.6 muss in einen Listentyp mit b = list (a)
konvertiert werden, um wie folgt damit umgehen zu können.
a = "abc"
puts 'id_a:%d' % [a.object_id]
a[0] = "A"
puts 'id_a:%d' % [a.object_id]
Ausgabeergebnis
id_a:70186456022160
id_a:70186456022160
Entspricht die Zuordnung bei PHP einer tiefen Kopie? Selbst wenn im folgenden Beispiel "$ a = [5];", "$ b" auf "$ a" verweist, handelt es sich also um den Wert, auf den "$ a" verweist. Eine Substitution durch Referenz wie "$ a = & $ b;" in PHP kann in Python oder Ruby nicht realisiert werden.
<?php
$a = [3];
$b = &$a;
$a = [5];
print_r($a);
print_r($b);
Ausgabeergebnis
Array
(
[0] => 5
)
Array
(
[0] => 5
)
In diesem Beispiel werden Listen und Arrays als Beispiele verwendet, aber der Unterschied zwischen flacher und tiefer Kopie kann auch in den folgenden Fällen unterschieden werden.
import copy
class Test1:
def __init__(self):
self.a = 0
def set(self, n):
self.a = n
def get(self):
print(self.a)
class Test2:
def __init__(self, t):
self.t1 = t
def set(self, n):
self.t1.set(n)
def get(self):
self.t1.get()
a = Test2(Test1())
b = copy.copy(a)
c = copy.deepcopy(a)
a.set(3)
b.set(5)
c.set(7)
a.get()
b.get()
c.get()
Ausgabeergebnis
5
5
7
class Test1
def initialize
@a = 0
end
def set(n)
@a = n
end
def get()
puts @a
end
end
class Test2
def initialize(t1)
@t1 = t1
end
def set(n)
@t1.set(n)
end
def get()
@t1.get
end
end
a = Test2.new(Test1.new)
b = a.clone
c = Marshal.load(Marshal.dump(a))
a.set(3)
b.set(5)
c.set(7)
a.get
b.get
c.get
Ausgabeergebnis
5
5
7
Recommended Posts