l=[1,2,3,4] ; l=l.replace([2,3], "X") ???
@jens: Ja, aber Listen sind keine Zeichenketten. Ich hätte halt erwartet das das erste Argument das Element ist welches man ersetzen will und das zweite wodurch es ersetzt wird. Wie würdest Du denn *so* eine Methode nennen wenn Deine schon `replace()` heisst? Und da Listen veränderbar sind, hätte ich erwartet das die Liste verändert wird und nicht eine neue zurück gegeben wird. Dazu hätte die Methode `replaced()` heissen müssen. Bei Zeichenketten geht es ja nicht anders weil die unveränderbar sind.
- jens
- Python-Forum Veteran
- Beiträge: 8502
- Registriert: Dienstag 10. August 2004, 09:40
- Wohnort: duisburg
- Kontaktdaten:
Hä? Das ist doch genau so auch gemacht. Schau noch mal die DocTests vom letzten code.BlackJack hat geschrieben: Ich hätte halt erwartet das das erste Argument das Element ist welches man ersetzen will und das zweite wodurch es ersetzt wird.
Das stimmt, wäre auch eine sehr gute Idee!BlackJack hat geschrieben:Und da Listen veränderbar sind, hätte ich erwartet das die Liste verändert wird und nicht eine neue zurück gegeben wird.
@jens: Nein das macht Dein Code eben nicht. Da gibst Du als erstes Argument kein Element sondern eine Teilsequenz an. Das finde ich überraschend, denn wenn ich etwas mit `replace()` austausche erwarte ich zum Beispiel das ich mit ``in`` prüfen könnte ob es überhaupt enthalten ist. Mit ``in`` kann ich bei Listen aber nur einzelne Elemente prüfen und keine Teilsequenzen. Ich würde das nicht `replace()` sondern beispielsweise `replace_sequence()` nennen. Und auch erwarten das beide Argumente Sequenzen sind.
- jens
- Python-Forum Veteran
- Beiträge: 8502
- Registriert: Dienstag 10. August 2004, 09:40
- Wohnort: duisburg
- Kontaktdaten:
Aber das mit dem ``in`` ist doch genauso doof. Warum kann ich nicht sagen: if [2,3] in [1,2,3,4]: Wäre doch auch nett!
Nun wird die selbe Liste nur modifiziert und zurück geliefert:
Nun wird die selbe Liste nur modifiziert und zurück geliefert:
Code: Alles auswählen
class List2(list):
def replace(self, src, dst):
"""
>>> l=List2([1,2,3,4])
>>> l
[1, 2, 3, 4]
>>> l.replace((2,3), "X")
[1, 'X', 4]
>>> l=List2([1,2,3,4])
>>> l.replace([2], "X")
[1, 'X', 3, 4]
>>> l=List2([1,2,3,4,5])
>>> l.replace([2,3,4], "X")
[1, 'X', 5]
>>> l=List2([1,2,3,4,5])
>>> l.replace((4,5), "X")
[1, 2, 3, 'X']
>>> l=List2([1,2,3,4,5])
>>> l.replace((1,2), "X")
['X', 3, 4, 5]
>>> l=List2([1,2,3,3,3,4,5])
>>> l.replace((3,3), "X")
[1, 2, 'X', 3, 4, 5]
>>> l=List2(["A",1,2,"B",1,2,"C"])
>>> l.replace((1,2), "*")
['A', '*', 'B', '*', 'C']
>>> l=List2(["X", 1,2,3, 1,2,3, 1,2,3, "Y"])
>>> l.replace([1,2,3], ".")
['X', '.', '.', '.', 'Y']
>>> l=List2([(1,2),(3,4), (5,6), (1,2),(3,4)])
>>> l.replace([(1,2), (3,4)], "X")
['X', (5, 6), 'X']
"""
src=list(src)
src_len=len(src)
dst_len=len(dst)
index = 0
while index < len(self):
element = self[index:index+src_len]
if element == src:
del(self[index:index+src_len])
self.insert(index, dst)
index += dst_len
else:
index += 1
return self
if __name__ == "__main__":
import doctest
print doctest.testmod(verbose=0)
print " --- END --- "
- jens
- Python-Forum Veteran
- Beiträge: 8502
- Registriert: Dienstag 10. August 2004, 09:40
- Wohnort: duisburg
- Kontaktdaten:
Und warum geht das nicht:
Code: Alles auswählen
l=[1,2,3,4,5]
print l.index([3,4])
Traceback (most recent call last):
File "test.py", line 60, in <module>
print l.index([3,4])
ValueError: [3, 4] is not in list
- jens
- Python-Forum Veteran
- Beiträge: 8502
- Registriert: Dienstag 10. August 2004, 09:40
- Wohnort: duisburg
- Kontaktdaten:
So, auch index, und __contains__ mit gemacht:
Was fehlt da noch?
EDIT: Der Code ist nun auch hier: https://gist.github.com/jedie/a1c25c520dc314340c26
Code: Alles auswählen
class List2(list):
def replace(self, src, dst):
"""
>>> l=List2([1,2,3,4])
>>> l
[1, 2, 3, 4]
>>> l.replace((2,3), "X")
[1, 'X', 4]
>>> l=List2([1,2,3,4])
>>> l.replace([2], "X")
[1, 'X', 3, 4]
>>> l=List2([1,2,3,4,5])
>>> l.replace([2,3,4], "X")
[1, 'X', 5]
>>> l=List2([1,2,3,4,5])
>>> l.replace((4,5), "X")
[1, 2, 3, 'X']
>>> l=List2([1,2,3,4,5])
>>> l.replace((1,2), "X")
['X', 3, 4, 5]
>>> l=List2([1,2,3,3,3,4,5])
>>> l.replace((3,3), "X")
[1, 2, 'X', 3, 4, 5]
>>> l=List2(["A",1,2,"B",1,2,"C"])
>>> l.replace((1,2), "*")
['A', '*', 'B', '*', 'C']
>>> l=List2(["X", 1,2,3, 1,2,3, 1,2,3, "Y"])
>>> l.replace([1,2,3], ".")
['X', '.', '.', '.', 'Y']
>>> l=List2([(1,2),(3,4), (5,6), (1,2),(3,4)])
>>> l.replace([(1,2), (3,4)], "X")
['X', (5, 6), 'X']
"""
src=list(src)
src_len=len(src)
dst_len=len(dst)
index = 0
while index < len(self):
element = self[index:index+src_len]
if element == src:
del(self[index:index+src_len])
self.insert(index, dst)
index += dst_len
else:
index += 1
return self
def __contains__(self, item):
"""
>>> [2,3] in List2([1,2,3,4])
True
>>> (2,3) in List2([1,2,3])
True
>>> 2 in List2([1,2,3])
True
"""
if not isinstance(item, (list, tuple)):
return super(List2, self).__contains__(item)
if not isinstance(item, list):
item=list(item)
item_len=len(item)
for index in xrange(len(self)):
element = self[index:index+item_len]
if element == item:
return True
return False
def index(self, item):
"""
>>> List2([1,2,3,4]).index([2,3])
1
>>> List2([1,2,3,4]).index((3,4))
2
>>> List2([1,2,3]).index("X")
Traceback (most recent call last):
...
ValueError: 'X' is not in list
>>> List2([1,2,3]).index([5,6])
Traceback (most recent call last):
...
ValueError: [5, 6] is not in list
"""
if not isinstance(item, (list, tuple)):
return super(List2, self).index(item)
if not isinstance(item, list):
item=list(item)
item_len=len(item)
for index in xrange(len(self)):
element = self[index:index+item_len]
if element == item:
return index
raise ValueError("%r is not in list" % item)
if __name__ == "__main__":
import doctest
print doctest.testmod(verbose=0)
print " --- END --- "
Was fehlt da noch?
EDIT: Der Code ist nun auch hier: https://gist.github.com/jedie/a1c25c520dc314340c26
Was erwartet man bei so einer Liste?
oder noch verwirrender:
Code: Alles auswählen
l = [1, 2, 3, 4, [2, 3]]
l.replace([2,3], "X")
Code: Alles auswählen
l = ['A', 'B', 'C', 'ABC']
l.replace('ABC', 'X')
- jens
- Python-Forum Veteran
- Beiträge: 8502
- Registriert: Dienstag 10. August 2004, 09:40
- Wohnort: duisburg
- Kontaktdaten:
Aktuell passiert das:
Wobei l.replace([[2,3]], "X") # -> [1, 'X', 4, 'X'] hätte ich nicht erwartet. Sondern: l.replace([[2,3]], "X") # -> [1, 2, 3, 4, 'X']
EDIT: Nett ist doch das:
Ich finde, dadurch das keine "Sonderbehandlungen" stattfinden, ist das doch eine saubere Sache.
Code: Alles auswählen
l=List2([1, 2, 3, 4, [2, 3]])
print l.replace([2,3], "X") # -> [1, 'X', 4, [2, 3]]
print l.replace([[2,3]], "X") # -> [1, 'X', 4, 'X']
l=List2(['A', 'B', 'C', 'ABC'])
print l.replace('ABC', 'X') # -> ['X', 'ABC']
EDIT: Nett ist doch das:
Code: Alles auswählen
>>> List2([1, 2, 3, 4]).replace([2,3], ["X","Y"])
[1, ['X', 'Y'], 4]
- jens
- Python-Forum Veteran
- Beiträge: 8502
- Registriert: Dienstag 10. August 2004, 09:40
- Wohnort: duisburg
- Kontaktdaten:
Wobei ich das so falsch verstanden habjens hat geschrieben:Aktuell passiert das:Code: Alles auswählen
l=List2([1, 2, 3, 4, [2, 3]]) print l.replace([2,3], "X") # -> [1, 'X', 4, [2, 3]] print l.replace([[2,3]], "X") # -> [1, 'X', 4, 'X']

Hier wird die Liste ja zuerst vorn, dann im zweite Beispiel hinten geändert. Also alles gut:
Code: Alles auswählen
>>> List2([1, 2, 3, 4, [2, 3]]).replace([2,3], "X")
[1, 'X', 4, [2, 3]]
>>> List2([1, 2, 3, 4, [2, 3]]).replace([[2,3]], "X")
[1, 2, 3, 4, 'X']
https://gist.github.com/jedie/a1c25c520 ... /revisions
Also nochmal die Frage, was spricht dagegen?
Das man es in der Praxis ehr wenig braucht?
@jens: Ich weiss nicht ob es was bringt das ich *nochmal* wiederhole das die Funktion/Methode IMHO etwas unerwartetes macht.
- jens
- Python-Forum Veteran
- Beiträge: 8502
- Registriert: Dienstag 10. August 2004, 09:40
- Wohnort: duisburg
- Kontaktdaten:
Jetzt verstehe ich was du meinst!BlackJack hat geschrieben: Ich hätte erwartet das die beiden Argumente das alte und das neue Element sind, also bei ``print l.replace([2,3,4],"Y")`` hätte ich keine Änderung erwartet weil in der Liste kein Element mit dem Wert [2,3,4] vorkommt. Bei ``l = [42, [2, 3, 4], 'spam']`` würde ich dann allerdings [42, 'Y', 'spam'] als Ergebnis erwarten.
Stimmt, wie wäre es mit einer 'normalen' replace Methode, die so wie du es erwartest arbeitet und meine Varianten umbenennen in z.b.: seq_replace, seq_index und seq_contains...