在python中替换字符串时的奇怪行为

时间:2013-09-21 13:01:38

标签: python replace

我的格式为“2010年10月28日”(或simillar)。现在我想将月份的全名更改为更短版本(在本例中为Oct)。为此,我准备了一本字典:

_mapping = {'January': 'Jan', 
            'February': 'Feb', 
            'March': 'Mar', 
            'April': 'Apr', 
            'May': 'May', 
            'June': 'Jun', 
            'July': 'Jul', 
            'August': 'Aug', 
            'September': 'Sep', 
            'October': 'Oct', 
            'November': 'Nov', 
            'December': 'Dec'}

并且在替换的方法中,我写了以下内容:

def fetch(self, pno):
    ...
    date = #get data (working fine)
    for l, s in self._mapping.iteritems():
        pubdate = date.replace(l, s)
        print l + " -> " + pubdate #this is only for debug
    (pubd_month, self.pubd_day, self.pubd_year) = pubdate.split(' ')
    print pubd_month, self.pubd_day, self.pubd_year
    print pubdate

执行结果是:

February -> October 28, 2008
October -> Oct 28, 2008
January -> October 28, 2008
April -> October 28, 2008
November -> October 28, 2008
March -> October 28, 2008
August -> October 28, 2008
May -> October 28, 2008
December -> October 28, 2008
June -> October 28, 2008
September -> October 28, 2008
July -> October 28, 2008
October
October 28, 2008

正如你所看到的那样,当它找到十月但是在循环之外时,替换就没问题了,我又得到了满月的名字。我做错了什么?

另一个问题是:有更短的方法吗?

2 个答案:

答案 0 :(得分:3)

由于您始终使用pubdate上的替换替换date,因此您将覆盖任何成功匹配。

如果月份在替换之前的字符串中,则首先测试,或者将pubdate替换为pubdate.replace()结果:

pubdate = #get data (working fine)
for l, s in self._mapping.iteritems():
    pubdate = pubdate.replace(l, s)

或者,使用测试:

date = #get data (working fine)
for l, s in self._mapping.iteritems():
    if l in date:
        pubdate = date.replace(l, s)

如果找到超过一个月的名称,后者仍会导致pubdate被覆盖。或者,如果只有一个月匹配,请使用break提前结束循环:

date = #get data (working fine)
for l, s in self._mapping.iteritems():
    if l in date:
        pubdate = date.replace(l, s)
        break

警告:如果找不到没有匹配,则永远不会分配pubdate,您将获得UnboundLocal例外。

答案 1 :(得分:3)

不需要_mapping。如果您使用datetime.datetime个对象,strftime方法可以为您返回缩写的月份:

import datetime as DT

def short_date(date):
    date = DT.datetime.strptime(date, '%B %d, %Y')
    return date.strftime('%b %d, %Y')

print(short_date('October 28, 2010'))

打印

Oct 28, 2010

如果您的日期字符串有多种格式,那么您可以使用dateutil的parser.parse方法,而不是使用strptime(date, '%B %d, %Y')解析它们。为了获得最大的灵活性,您可能最好尽早将日期字符串解析为datetime.datetime个对象,并尽可能使用strftime格式化它们。