newbie question
Nick Coghlan
ncoghlan at iinet.net.au
Sun Dec 19 08:44:24 EST 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