tags:

views:

72

answers:

4

So. The following isn't very 'smart' ;)

MONTHS = (
    ('Jan', 'Jan'),
    ('Feb', 'Feb'),
    ('Mar', 'Mar'),
    ('Apr', 'Apr'),
    ('May', 'May'),
    ('Jun', 'Jun'),
    ('Jul', 'Jul'),
    ('Aug', 'Aug'),
    ('Sep', 'Sep'),
    ('Oct', 'Oct'),
    ('Nov', 'Nov'),
    ('Dec', 'Dec'),
)

YEARS = (
    ('1995', '1995'),
    ('1996', '1996'),
    ('1997', '1997'),
    ('1998', '1998'),
    ('1999', '1999'),
    ('2000', '2000'),
    ('2001', '2001'),
    ('2002', '2002'),
    ('2003', '2003'),
    ('2004', '2004'),
    ('2005', '2005'),
    ('2006', '2006'),
    ('2007', '2007'),
    ('2008', '2008'),
    ('2009', '2009'),
    ('2010', '2010'),
)

I'm newer to python, and would love to produce stuff like this 'pythonically'.

Such as,

  • a list of year tuples from 1995 to current year.
  • a list of the abbreviated months of the year

Thanks Stackers'

+2  A: 

See module time.

>>> import time

For the months we can use strptime to turn a month number 1-12 into a struct_time, and then use strftime to pull the month name out.

>>> [time.strftime('%b', time.strptime(str(i), '%m')) for i in range(1, 13)]
['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']

The years are more straightforward, we just need to know the current year (plus one, due to the way range works).

>>> [str(i) for i in range(1995, time.localtime().tm_year + 1)]
['1995', '1996', '1997', '1998', '1999', '2000', '2001', '2002', '2003', '2004', '2005', '2006', '2007', '2008', '2009', '2010']

I added str(i) to have the years returned as strings since that's the way you wrote them. If integers are okay then you can drop the whole list comprehension and simply use range(...).

John Kugelman
+8  A: 
In [17]: from datetime import datetime

In [18]: tuple((str(n), str(n)) for n in range(1995, datetime.now().year + 1))
Out[18]:
(('1995', '1995'),
 ('1996', '1996'),
 ('1997', '1997'),
 ('1998', '1998'),
 ('1999', '1999'),
 ('2000', '2000'),
 ('2001', '2001'),
 ('2002', '2002'),
 ('2003', '2003'),
 ('2004', '2004'),
 ('2005', '2005'),
 ('2006', '2006'),
 ('2007', '2007'),
 ('2008', '2008'),
 ('2009', '2009'),
 ('2010', '2010'))

In [19]: import calendar

In [20]: tuple((m, m) for m in calendar.month_abbr[1:])
Out[20]:
(('Jan', 'Jan'),
 ('Feb', 'Feb'),
 ('Mar', 'Mar'),
 ('Apr', 'Apr'),
 ('May', 'May'),
 ('Jun', 'Jun'),
 ('Jul', 'Jul'),
 ('Aug', 'Aug'),
 ('Sep', 'Sep'),
 ('Oct', 'Oct'),
 ('Nov', 'Nov'),
 ('Dec', 'Dec'))
ars
Calendar module also provides an attribute called month_abbr which is probably more suitable here.
ecik
@ecik: it is indeed, thanks.
ars
To get the current year you should do `import datetime; datetime.datetime.now().year + 1` as the second arg of the range.
sdolan
@sdolan: good point, thank you.
ars
A: 

Although some of the other answers might be "smarter", I dislike the idea of using a loop to define a tuple. Perhaps the following is a more readable compromise :

MONTHS = (
    ('Jan',) * 2,
    ('Feb',) * 2,
    ('Mar',) * 2,
    ('Apr',) * 2,
    ('May',) * 2,
    ('Jun',) * 2,
    ('Jul',) * 2,
    ('Aug',) * 2,
    ('Sep',) * 2,
    ('Oct',) * 2,
    ('Nov',) * 2,
    ('Dec',) * 2,
)

YEARS = (
    ('1995',) * 2,
    ('1996',) * 2,
    ('1997',) * 2,
    ('1998',) * 2,
    ('1999',) * 2,
    ('2000',) * 2,
    ('2001',) * 2,
    ('2002',) * 2,
    ('2003',) * 2,
    ('2004',) * 2,
    ('2005',) * 2,
    ('2006',) * 2,
    ('2007',) * 2,
    ('2008',) * 2,
    ('2009',) * 2,
    ('2010',) * 2,
)
Nimmy Lebby
why don't you like using a comprehension to define a tuple?
aaronasterling
Personally, for constants, I rather be more verbose and stick to tuples as oppose to defining a list with list comprehensions. It's more for personal taste and readability than anything else.
Nimmy Lebby
+1 to Adam Backstrom's answer. Most elegant answer IMHO.
Nimmy Lebby
+2  A: 

Try using zip() to make a list of two-tuples.

MONTHS = ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec')
somemonth = models.TextField(max_length=3, choices=zip(MONTHS,MONTHS))

choices will be set to [('Jan', 'Jan'), ('Feb', 'Feb'), ...].


In response to the comments on this answer, the "tuple" list comprehension version would be:

tuple((m, m) for m in MONTHS)

Versus the zip version:

tuple(zip(MONTHS, MONTHS))

But strictly speaking, Django doesn't need a tuple of choices, so:

zip(MONTHS, MONTHS)
Adam Backstrom
Hey I like the 'zip()' method... but using the tuple() seems much less work!
Daryl
@Daryl I've updated the answer to compare the list comprehension to `zip()`.
Adam Backstrom