newbie question

Nick Coghlan ncoghlan at iinet.net.au
Sun Dec 19 14:44:24 CET 2004


David Wurmfeld wrote:
> I am new to python; any insight on the following would be appreciated, even 
> if it is the admonition to RTFM (as long as you can direct me to a relevant 
> FM)

Your questions are esoteric enough that, even though the relevant information 
*is* in the FM, RTFM would be a really slow and painful way to learn it. . .

> Is there a standard approach to enumerated types? I could create a 
> dictionary with a linear set of keys, but isn't this overkill?

The problem is that enumerated types get used for so many different things that 
it isn't easy to come up with One Obvious Way To Do It.

A fairly simple version:

Py> class Enum(object):
...  def __init__(self, attrs):
...    for num, attr in enumerate(attrs):
...      setattr(self, attr, num)
...    self._values = attrs
...  def get_name(self, value):
...    return self._values[value]
...
Py> Fruit = Enum(["apple", "banana", "pear"])
Py> Fruit.pear
2
Py> Fruit.banana
1
Py> Fruit.apple
0
Py> Fruit.get_name(0)
'apple'
Py> Fruit.get_name(1)
'banana'
Py> Fruit.get_name(2)
'pear'
Py> Fruit.get_name(3)
Traceback (most recent call last):
   File "<stdin>", line 1, in ?
   File "<stdin>", line 7, in get_name
IndexError: list index out of range

A more complete answer can be found at the link Miki gave:
http://www.norvig.com/python-iaq.html (look for Enumerated Types)

(Don't get too concerned about some of the other things Peter says on the rest 
of that page - the more glaring omissions he mentions have been addressed for 
Python 2.4)

> There is 
> afterall a "True" and "False" enumeration for Boolean.

True/False isn't actually an enumeration - they're special objects for boolean 
values (i.e. "True is 1" and "False is 0" both return False)

> Is there a way to ignore case in string comparisons? I want 'Oranges' to 
> equal 'oranges' when using the evaluation operator (==). I don't care about 
> string inequalities (<, >)

The standard way is to invoke the string .lower() method, and compare the forced 
lowercase versions instead.

> If I am compelled to use dictionaries for enumerated types, is there a way 
> to generate unique keys automatically: something like 
> "myDict.appendWithAutoKey("Persimmons")"?

The enumerate() function is generally the easiest way to get hold of a unique 
index for each item in a sequence.

> Is there a way to overload operators to accommodate an enumeration? For 
> example,
> 
> newFruit = enumerationFruit('Cumquat')        #use it like you would use 
> list()
> new = newFruit + 14        # this should throw an exception because of 
> different types

Certainly - Python allows almost all operations to be overridden (id() is the 
only one I can think of that is off limits!)

Again, Miki already pointed you in the right direction:
http://www.python.org/doc/2.4/ref/specialnames.html

(I'd advise *against* inheriting from int or long though - trying to prevent the 
base type from leaking through the API is a serious PITA)

> Finally, (for now at least) consider the following list.
> 
> myList = [apple, 13, plum, cherry, 'Spam', tomato, 3.35]
> 
> Exactly how does the "for x in myList" work?

The specified operation is applied to each item in the sequence. The behaviour 
on heterogenous types will depend on the exact operation and how it handles type 
differences.

> evaluation and move along? Do I have to manually interrogate each iteration 
> for the proper type before I test?

It depends on the operation - checking the type can work, as can looking for an 
appropriate attribute:

[abs(x) for x in myList if hasattr(x, "__abs__")]

> Think about it; the interpreter has to evaluate disparate types for 
> equality. How exactly does the it "know" that for this iteration, x is an 
> integer, and the evaluation (if x == 'spam') is False, and doesn't throw an 
> exception for a type mismatch?

Easy: if the types are different, the objects are almost certainly different, so 
the interpreter applies that rule as the default.

It *is* possible to alter that determination though:
Py> from decimal import Decimal
Py> Decimal(1) == int(1)
True
Py> type(Decimal(1))
<class 'decimal.Decimal'>
Py> type(int(1))
<type 'int'>

The reason your __abs__ example blows up is because the relevant attribute is 
missing for string objects - and there's nothing the interpreter can do about 
that. If you don't care, you need to tell the interpreter so (using either 
hasattr() or try/except)

Cheers,
Nick.

-- 
Nick Coghlan   |   ncoghlan at email.com   |   Brisbane, Australia
---------------------------------------------------------------
             http://boredomandlaziness.skystorm.net



More information about the Python-list mailing list