Unification of Methods and Functions

David MacQuigg dmq at gain.com
Thu May 6 07:44:14 EDT 2004


On Thu, 06 May 2004 05:46:35 -0000, "Donn Cave" <donn at drizzle.com>
wrote:

>Quoth David MacQuigg <dmq at gain.com>:
>...
>| The second problem with the "avoidance/denial" strategy is that it
>| involves moving the troublesome functions outside of the class
>| definition.  This results in a less-than-optimal structure for your
>| program.  Look at the show() methods in Animals_2.py  They must be
>| callable without any specific instance.  Moving them outside the
>| appropriate classes is not good programming.  When you want to change
>| a class later, you will need to remember to look in some other place
>| for any "static methods" associated with the class.
>|
>| If you could do me one more favor, please take a look at the
>| Animals_2.py example starting on page 7 of the Prototypes document at
>| http://ece.arizona.edu/~edatools/Python  Can you write this in Python?
>| Give it a try, and let me know if you had any difficulties.  Were
>| there any parts you had to stop and think, or look up in a manual?
>
>Mine came out 66 lines, most of it very introductory level
>and nothing exotic.  The first dozen lines deal with the
>inventory problem, which I gather is the issue you're interested
>in.  I don't maintain a count in each class, but rather keep
>the counts in a single data structure in the base class, and
>I provide a single show() function that prints them.  If I were
>writing this in C++, I might make that a static function.
>But then, I hate C++.
>
>Now, you could argue that I changed the problem to suit my
>purposes, but your approach repeats some stuff all over the
>class hierarchy in a kind 'similar but not quite the same'
>way that I don't like at all.  If we need to implement some
>functionality that's general to the hierarchy, then let's
>implement it once.

The "similar but not quite the same" for all the show() methods in my
example was deliberate, though somewhat artificial in this short
example.  I wanted to discourage the "do it all with one external
function" idea, but it seems I failed.

In a more realistic, but longer example, each class will have a large
number of attributes that need a completely different display than any
other class.  For example, the Mammal.show() method might output a
format with all sorts of information on temperature, pulse, and
respiration, and other mammal characteristics.  This format would be
completely different than the format for Cat.show(), and different in
a way that you can't find a simple pattern for your all-in-one
function.

>I can imagine in principle the need for
>a class specific function.  In such a case, I would define
>the function above the class definition, and refer to it
>inside a data structure at the class level.  I have a vague
>notion that there are newer Python features that address
>these issues, but I'm not interested - it isn't important.

We can put the function outside the class definition, or leave it
inside and add the 'staticmethod' wrapper.  I prefer the latter.
Either way its a pain.  The pain is especially severe for my students
and clients, who don't have time to get proficient in Python, and only
figure out that they need a workaround *after* writing some code and
discovering the problem.  Then they have to "refactor" their program,
or search for information on staticmethod (not remembering that
keyword of course).  

This pain can be avoided by eliminating the need for static methods
entirely.  That is one benefit of the proposed syntax.  Static methods
add nothing to the fundamental capabilities of Python.  They are there
to make up for a deficiency in the syntax.

PEP 318 adds function "decorators", which are basically syntax sugar
for staticmethod and other extensions of the normal function syntax.

>	Donn Cave, donn at drizzle.com
>-----------------------------------
>def show():
>	for k, v in Animal.inventory.items():
>		if v == 1:
>			f = '%s: %s'
>		else:
>			f = '%ss: %s'
>		print f % (k, v)

You left out the parts that are unique to each class.

>class Animal:
>	home = 'Earth'
>	inventory = {}
>	def __init__(self):
>		self.register('Animal')
>	def register(self, name):
>		i = self.inventory.get(name, 0)
>		self.inventory[name] = i + 1
>
>class Reptile(Animal):
>	pass
>
>class Mammal(Animal):
>	def __init__(self, sound = 'Maa... Maa...'):
>		self.sound = sound
>		self.register('Mammal')
>		Animal.__init__(self)
>	def talk(self):
>		print 'Mammal sound: ', self.sound
>
>class Bovine(Mammal):
>	pass
>
>class Canine(Mammal):
>	pass
>
>class Feline(Mammal):
>	genus = 'feline'
>	def __init__(self):
>		Mammal.__init__(self)
>		self.register('Feline')
>
>class Cat(Feline):
>	def __init__(self, name='unknown', sound='Meow'):
>		Feline.__init__(self)
>		self.register('Cat')
>		self.name = name
>		self.sound = sound
>	def talk(self):
>		print 'My name is ...', self.name
>		print 'I am', self.genus, 'from', self.home
>		Mammal.talk(self)

How did you know to add self in Mammal.talk(self)?  This is a perfect
example of an experienced Python programmer sailing right past a
problem that trips up less proficient users, and not even being aware
that the problem exists.  What surprises me is that even after
pointing out a problem like this, I will get someone telling me --
It's real simple, dummy.  Mammal is a class.  When you call a method
from a class, you get an unbound method, which requires an explicit
'self'.

Yes, I know that.  I remember it because I use Python almost every
day.  My students and clients, three months after learning it, will
not remember.

I appreciate your time in working on this example.  I hope that I was
able to communicate the reasons for my continuing dis-satisfaction
with existing method syntax.

I am beginning to see that my needs are somewhat special.  Most users
get past these difficulties and never look back.  My clients and
students, however, will always be in the "never fully proficient"
mode.  This is not a lack of intelligence or motivation.  IC designers
are some of the smartest and hardest-working technical professionals
on the planet.  It is simply that their minds are 110% occupied with
the intricacies of their designs.  Anything we can do to reduce the
time they spend on "tool problems" will be worth millions in
productivity.

-- Dave




More information about the Python-list mailing list