[Tutor] SENTINEL, & more

spir ☣ denis.spir at gmail.com
Sun May 30 12:10:53 CEST 2010


On Sun, 30 May 2010 00:36:24 +0200
Eike Welk <eike.welk at gmx.net> wrote:

> Hey Denis!
> 
> I waited for a thread like this to appear, because I have a quirky, but IMHO 
> elegant, solution for those kinds of variables:
> 
> class EnumMeta(type):
>     def __repr__(self):
>         return self.__name__
>     
> class Enum(object):
>     __metaclass__ = EnumMeta
> 
> 
> Objects are created by inheriting from the Enum class. (Not by instantiating 
> it.)
> 
>     >>> class EAST(Enum): pass
>     >>> class WEST(Enum): pass
>     >>> class NORTH(Enum): pass
>     >>> class SOUTH(Enum): pass
> 
> 
> The objects know their name, and when printed their name is printed. In this 
> respect they behave similarly to None.
> 
>     >>> print NORTH, SOUTH, EAST, WEST
>     NORTH SOUTH EAST WEST

Great from the pov of practicality, but severely distorts the language's semantics, no?
*The* issue is custom objects don't know their names. I have always wanted named objects to systematically know their own name. In python, classes, funcs, methods (possible a few other more) know it.
>>> def f():pass
... 
>>> f.__name__
'f'

But sure, the double trick of using classes instead of instances, plus the metaclass to define repr as __name__ works great :-)

> I call the class Enum, but this is certainly the wrong term since the values 
> are not enumerated. But is Sentinel the right term for something like this? I 
> thought a sentinel is a soldier who guards something. Hello English native 
> speakers! What is a good name? 

Enum is wrong, indeed.
I call that "mark" (as you know). Perfect for me; but do not know if it fits sell in english. The meaning is about the same as the one of "token", but "token" is loaded in the field of programming. "Code" would also be great, but its sense is rather too open.

I have a kind of simulation for pascal enums. See code below (at the time, I used the term "code".)
* The user must explicitely specifiy code name.
* Automatically gives a code an ordinal value if none defined.
* The user can define a code/mark suite in one go: passing a name list if implicitely valued, a dict if explicitely valued. Individuals become attributes of the class. This allows clear naming such as "direction.NORTH".

> Eike.
> 
> P.S. By the way Denis, an earlier thread from you on the subject got me 
> thinking about it. 

;-)

Denis

================================
#!/usr/bin/env python
# coding: utf-8

from sys import exit as exit
from copy import copy as copy

class Code(object):
	value = 1
	def __init__(self, name=None, value=None):
		self.name = '_' if name is None else name
		self.value = Code.value if value is None else value
		Code.value = self.value + 1
	def __eq__(self, other):
		if not isinstance(other,Code):
			raise TypeError("Can compare Code object only with other Code.")
			return self.value == other.value
	def __lt__(self, other):
		if not isinstance(other,Code):
			raise TypeError("Can compare Code object only with other Code.")
		return self.value < other.value
	def __repr__(self):
		return "Code(%s,%s)" %(self.name,self.value)
	def __str__(self):
		return "%s:%s" %(self.name,self.value)

class CodeSuite(object):
	def __init__(self, code_defs):
		if isinstance(code_defs, list):
			for code_def in code_defs:
				code = Code(code_def)
				setattr(self, code_def, code)
		elif isinstance(code_defs, dict):
			for code_def in code_defs.items():
				(name,value) = code_def
				code = Code(name,value)
				setattr(self, name, code)
		else:
			raise TypeError("A code suite definition must be a list or dict")
	def __getattr__(self, name):
		raise NameError("CodeSuite does not hold code '%s'." %name)
	def __iter__(self):
		codes = self.__dict__.values()
		codes.sort(key = lambda c:c.value)
		return iter(codes)
	def __repr__(self):
		cs = ",".join("'%s':%s" %(c.name,c.value) for c in self)
		return "CodeSuite({%s})" %cs
	def __str__(self):
		codes = " ".join(str(code) for code in self)
		return "CodeSuite:(%s)" %codes

### fast test ###
def test():
	print "=== code suite without values ==="
	suits = CodeSuite(['diamond','club','heart','spade'])
	print suits
	print repr(suits)
	print suits.heart
	print suits.heart>suits.club, suits.heart>suits.spade
	
	print
	print "=== code suite with values ==="
	cards = CodeSuite({'_7_':0,'_8_':0,'_9_':0, 'V':2,'D':3,'R':4, '_10_':10,'_1_':11})
	print cards
	print repr(cards)
	print cards.D
	print cards.D>cards.R, cards.D>cards._9_
	print cards.x	# ==> error
test()
================================
________________________________

vit esse estrany ☣

spir.wikidot.com


More information about the Tutor mailing list