开发者

Python replace not working with list

My code reads a directory and stores the filename with extention into a list. What I am trying to do is get rid of the extention with replace. However, it is not saving into the list.

 print projectFilenames

 for f in projectFilenames:
  print f
  f = f.replace('.txt','')
  f = f.replace('.mdown','')
  f = f.replace('.markdown','')
  print f

 print projectFilenames

and this is my output

['2010-10-30-markdown-example.txt', '2010-12-29-hello-world.mdown', '2011-1-1-tester.markdown']

2010-10-30-markdown-example.txt

2010-10-30-markdown-example

2010-12-29-hello-world.mdown

2010-12-29-hello-world

开发者_运维问答2011-1-1-tester.markdown

2011-1-1-tester

['2010-10-30-markdown-example.txt', '2010-12-29-hello-world.mdown', '2011-1-1-tester.markdown']

What am I doing wrong?


The list doesn't change, because you aren't updating it. You aren't touching the projectFilenames list in any way (nor the strings in the list. Python variables are not pointers) Here is one way to do it:

newlist = []
for f in projectFilenames:
    f = f.replace('.txt','')
    f = f.replace('.mdown','')
    f = f.replace('.markdown','')
    newlist.append(f)

projectFilenames = newlist

Also, look at the os.path module, there are functions there to cut off file extensions. os.path.splitext() specifically. So another way of doing it would be:

newlist = []
for f in projectFilenames:
    f = os.path.splitext(f)[0]
    newlist.append(f)

projectFilenames = newlist

That in turn can be simplified to (and made compliant with PEP 8):

>>> import os
>>> project_filenames = ['2010-10-30-markdown-example.txt', '2010-12-29-hello-world.mdown', '2011-1-1-tester.markdown']
>>> project_filenames = [os.path.splitext(f)[0] for f in project_filenames]
>>> project_filenames
['2010-10-30-markdown-example', '2010-12-29-hello-world', '2011-1-1-tester']


You are replacing the f object not the projectFileNames , do it like this;

>>> [x.split(".")[0] for x in projectFileNames]
['2010-10-30-markdown-example', '2010-12-29-hello-world', '2011-1-1-tester']

Removes the extension.


list slice replacement using list comprehension (updates contents of original list):

l[:] = [f.replace('.txt','').replace('.mdown','').replace('.markdown','') for f in l]

splitext (suggested by @lennart, @ sukhbir)

import os
l[:] = [os.path.splitext(f)[0] for f in l]

using enumerate:

import os
for idx, filename in enumerate(l):
    newfilename = os.path.splitext(filename)[0]
    if newfilename != filename:
        l[idx] = newfilename

Anecdotal: splitext()[0], str.replace('.txt') and str.split('.txt')[0] return the original string untouched if it has no extension or match. (at least in Python 2.6)


As mentioned in other answers, the reason the filename list doesn't change is because your code doesn't change it. There's a number of ways of fixing that, including building a new list and replacing the original with it.

I think the simplest approach would be to just modify the list as you're iterating over its elements (but you have to be careful when doing this that you don't modify parts of the list not yet seen). Python has a built-in function called enumerate() which makes this kind of task easy to code. What enumerate() does is return an "iterator" object which counts out the items as it provides each one from the sequence -- so the count is also the item's index in that sequence, and when necessary that index can be used to update the corresponding list element.

Since your code is dealing with filenames, it could be improved further by making use of the built-in module named os.path which is available for dealing with paths and filenames. That module has a splitext() function for breaking filenames into two parts, the "root" and the extension. It's called root instead of filename in the documentation because it could have directory path information prefixed onto it.

If your code was rewritten using enumerate() and os.path.splitext() it might look something like this:

import os
projectFilenames = ['2010-10-30-markdown-example.txt',
                    '2010-12-29-hello-world.mdown',
                    '2011-1-1-tester.markdown']

for i,f in enumerate(projectFilenames):
    root,ext = os.path.splitext(f)
    if ext in ('.txt', '.mdown', '.markdown'):
        projectFilenames[i] = root  # update filename list leaving ext off

print projectFilenames
# ['2010-10-30-markdown-example', '2010-12-29-hello-world', '2011-1-1-tester']

If you wanted to remove all file extensions, not just specific ones, you could just change the if ext in ('.txt', '.mdown', '.markdown'): to just if ext:.


Such operations on files should always be done with os.path.splitext. Because it is easier to maintain, portable and you don't have to reinvent the wheel.

>>> os.path.splitext('/home/Desktop/foo.py')[0]
'/home/Desktop/foo'

So say that you have a list, x, which has all all the files:

[os.path.splitext(files)[0] for files in x]
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜