[issue41899] Poor example for Element.remove()

New submission from WoodyWoo <saulmatchless@163.com>: We can remove elements using Element.remove(). Let’s say we want to remove all countries with a rank higher than 50:
When the original xml has over 2 country with rank>50,and they are one by one neighborly siblings element,the upper code will delete the 1st 3rd 5th and more odd No. country. A proper example should be: index=0 while index < len(root.findall("./*")): rank = int (root[index].find("rank").text) if rank>50: root.remove(root[index]) index=index+0 continue index=index+1 I think "for each in list" should not work by index,but should work by pointer like thing,could be a list of pointers. A finial solution should be like this --- when the "for each in list" was acting,the pointers list would be fixed,and you need not to worry about the "list" changing. ---------- assignee: docs@python components: Documentation messages: 377726 nosy: WoodyWoo, docs@python priority: normal severity: normal status: open title: Poor example for Element.remove() type: behavior versions: Python 3.8 _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue41899> _______________________________________

WoodyWoo <saulmatchless@163.com> added the comment: #new code to avoid an err index=0 count=len(root.findall("./*")) while index <count: rank = int (root[index].find("rank").text) if rank>50: root.remove(root[index]) index=index+0 count=count-1 # avoid index err continue index=index+1 ---------- _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue41899> _______________________________________

WoodyWoo <saulmatchless@163.com> added the comment: My fault. "for country in root.findall('country')“ is not working as same as "for country in root" all 3 method below: import xml.etree.ElementTree as ET xmlstr=\ r'''<?xml version="1.0"?> <data> <country name="Liechtenstein"> <rank updated="yes">2</rank> <year>2008</year> <gdppc>141100</gdppc> <neighbor name="Austria" direction="E"/> <neighbor name="Switzerland" direction="W"/> </country> <country name="Singapore"> <rank updated="yes">5</rank> <year>2011</year> <gdppc>59900</gdppc> <neighbor name="Malaysia" direction="N"/> </country> <country name="Panama1"> <rank updated="yes">69</rank> <year>2011</year> <gdppc>13600</gdppc> <neighbor name="Costa Rica" direction="W"/> <neighbor name="Colombia" direction="E"/> </country> <country name="Panama2"> <rank updated="yes">69</rank> <year>2011</year> <gdppc>13600</gdppc> <neighbor name="Costa Rica" direction="W"/> <neighbor name="Colombia" direction="E"/> </country> </data>''' print(xmlstr) #orginal code root = ET.fromstring(xmlstr) for country in root.findall('country'): rank = int(country.find('rank').text) if rank > 50: root.remove(country) print("___orginal___") for country in root.findall('country'): print (country.get("name")) print("^^^orginal^^^^\n") #wrong code in my mind root = ET.fromstring(xmlstr) for country in root: rank = int(country.find('rank').text) if rank > 50: root.remove(country) print("___bad___") for country in root.findall('country'): print (country.get("name")) print("^^^bad^^^^\n") #my code root = ET.fromstring(xmlstr) index=0 count=len(root.findall("./*")) while index <count: rank = int (root[index].find("rank").text) if rank>50: root.remove(root[index]) index=index+0 count=count-1 # avoid index err continue index=index+1 print("___new___") for country in root.findall('country'): print (country.get("name")) print("^^^new^^^^\n") ---------- _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue41899> _______________________________________

WoodyWoo <saulmatchless@163.com> added the comment: The docs should specially tell that when need root.remove(child) must works with "for child in root.findall()". And my code with "while if continue" could make root.insert(index,newchild) easily. ---------- _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue41899> _______________________________________

Eric V. Smith <eric@trueblade.com> added the comment: As you've seen, the example is correct. I made the same mistake earlier today. For others: see also #41891 for a suggestion to improve the documentation. As was pointed out in that issue, it's generally true in Python that you should not mutate a sequence while iterating over it. ---------- nosy: +eric.smith _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue41899> _______________________________________

WoodyWoo <saulmatchless@163.com> added the comment: Could I say the mutable sequence containing not the object but the pointer like C++. So they can changed in def functions. ---------- _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue41899> _______________________________________

Stefan Behnel <stefan_ml@behnel.de> added the comment: Closing as duplicate of issue 41891. Let's keep the discussion there. ---------- nosy: +scoder resolution: -> duplicate stage: -> resolved status: open -> closed _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue41899> _______________________________________

Change by Stefan Behnel <stefan_ml@behnel.de>: ---------- Removed message: https://bugs.python.org/msg377740 _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue41899> _______________________________________

Stefan Behnel <stefan_ml@behnel.de> added the comment: Closing as duplicate of issue 41892. Let's keep the discussion there. ---------- _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue41899> _______________________________________

WoodyWoo <saulmatchless@163.com> added the comment: #new code to avoid an err index=0 count=len(root.findall("./*")) while index <count: rank = int (root[index].find("rank").text) if rank>50: root.remove(root[index]) index=index+0 count=count-1 # avoid index err continue index=index+1 ---------- _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue41899> _______________________________________

WoodyWoo <saulmatchless@163.com> added the comment: My fault. "for country in root.findall('country')“ is not working as same as "for country in root" all 3 method below: import xml.etree.ElementTree as ET xmlstr=\ r'''<?xml version="1.0"?> <data> <country name="Liechtenstein"> <rank updated="yes">2</rank> <year>2008</year> <gdppc>141100</gdppc> <neighbor name="Austria" direction="E"/> <neighbor name="Switzerland" direction="W"/> </country> <country name="Singapore"> <rank updated="yes">5</rank> <year>2011</year> <gdppc>59900</gdppc> <neighbor name="Malaysia" direction="N"/> </country> <country name="Panama1"> <rank updated="yes">69</rank> <year>2011</year> <gdppc>13600</gdppc> <neighbor name="Costa Rica" direction="W"/> <neighbor name="Colombia" direction="E"/> </country> <country name="Panama2"> <rank updated="yes">69</rank> <year>2011</year> <gdppc>13600</gdppc> <neighbor name="Costa Rica" direction="W"/> <neighbor name="Colombia" direction="E"/> </country> </data>''' print(xmlstr) #orginal code root = ET.fromstring(xmlstr) for country in root.findall('country'): rank = int(country.find('rank').text) if rank > 50: root.remove(country) print("___orginal___") for country in root.findall('country'): print (country.get("name")) print("^^^orginal^^^^\n") #wrong code in my mind root = ET.fromstring(xmlstr) for country in root: rank = int(country.find('rank').text) if rank > 50: root.remove(country) print("___bad___") for country in root.findall('country'): print (country.get("name")) print("^^^bad^^^^\n") #my code root = ET.fromstring(xmlstr) index=0 count=len(root.findall("./*")) while index <count: rank = int (root[index].find("rank").text) if rank>50: root.remove(root[index]) index=index+0 count=count-1 # avoid index err continue index=index+1 print("___new___") for country in root.findall('country'): print (country.get("name")) print("^^^new^^^^\n") ---------- _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue41899> _______________________________________

WoodyWoo <saulmatchless@163.com> added the comment: The docs should specially tell that when need root.remove(child) must works with "for child in root.findall()". And my code with "while if continue" could make root.insert(index,newchild) easily. ---------- _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue41899> _______________________________________

Eric V. Smith <eric@trueblade.com> added the comment: As you've seen, the example is correct. I made the same mistake earlier today. For others: see also #41891 for a suggestion to improve the documentation. As was pointed out in that issue, it's generally true in Python that you should not mutate a sequence while iterating over it. ---------- nosy: +eric.smith _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue41899> _______________________________________

WoodyWoo <saulmatchless@163.com> added the comment: Could I say the mutable sequence containing not the object but the pointer like C++. So they can changed in def functions. ---------- _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue41899> _______________________________________

Stefan Behnel <stefan_ml@behnel.de> added the comment: Closing as duplicate of issue 41891. Let's keep the discussion there. ---------- nosy: +scoder resolution: -> duplicate stage: -> resolved status: open -> closed _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue41899> _______________________________________

Change by Stefan Behnel <stefan_ml@behnel.de>: ---------- Removed message: https://bugs.python.org/msg377740 _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue41899> _______________________________________

Stefan Behnel <stefan_ml@behnel.de> added the comment: Closing as duplicate of issue 41892. Let's keep the discussion there. ---------- _______________________________________ Python tracker <report@bugs.python.org> <https://bugs.python.org/issue41899> _______________________________________
participants (3)
-
Eric V. Smith
-
Stefan Behnel
-
WoodyWoo