[Tutor] confused if i should be doing type checking in the code ( a confused java programmer)

Michael P. Reilly arcege@speakeasy.net
Sun, 6 Jan 2002 10:04:43 -0500


On Sun, Jan 06, 2002 at 12:54:38PM +0530, Karthik Gurumurthy wrote:
> hi all,
> 
> have been doing python for a couple of months now and have been doing java
> for more than a year now.
> 
> had trouble implementing immutable constants in python

There are no 'immutable constants' (a bit redundant? *chuckle*) in Python.
Like in most languages, Python will let you do what you want.  There is
a lot of extra processing that must occur to get security (cf. Ada).
Python decided to take a more co-operative approach to programming -
it is the developers responsibility not to break the code.

Most people figure out pretty quickly that you do go attempting to change
things that a) you don't know what it does, and b) when you do know,
that will break it.  The idea here with Python was "we won't stop you
changing it, because if you are, then you probably want to handling what
happens when it breaks yourself."

> i wanted a public static "final" equivalent in python.
> 
> class MovieRating:
> 	REGULAR = 1
> 	NEW = 2
> 	CHILDREN = 3
> 
> Now even though i can access it like
> 
> MovieRating.REGULAR
> But someone can modify the value
> 
> MovieRating.REGULAR = 100 # UnAcceptable

You might think about
  class MovieRating:
    (REGULAR, NEW, CHILDREN) = range(1, 4)
> I was trying to emulate the java enum equivalent but was not able
> implement it successfully.
> 
> class MovieRating{
> 
>  public static final MovieRating REGULAR = new MovieRating(1)
>  public static final MovieRating NEW = new MovieRating(2)
>  public static final MovieRating CHILDREN = new MovieRating(3)
> 
>  private int value;
> 
>  private MovieRating(int i){
>   value = i;
>  }
> }
> 
> Now the client cannot instantiate MovieRating but can get all the constant
> instances.
> so there's a proper type checking in another code which accepts only
> MovieRating instances
> instead of just integers.
> 
> So in python code i needed a singleton and then the immutable constants.
> Then came across this recipie in Cookbook and Well it's brillaint!
> i had'nt even imagined such things could be done.
> 
> http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/65207
> 
> I used that code and wrote this:
> 
> class _MovieRating:
> 	def __init__(self):
> 		self.__dict__['REGULAR'] = 1
> 		self.__dict__['NEW'] = 2
> 		self.__dict__['CHILDREN'] = 3
> 	def __setattr__(self,name,value):
> 		if self.__dict__.has_key(name):
> 			raise "Cannot assign to a readonly movie rating %s" % (name,)
> 		else:
> 			raise "Cannot add new constants"

You might also want to add a __delattr__ method.  Since I could go
with "del _MovieRating.NEW" and get no exception.

> import sys
> sys.modules[__name__] = _Movie()

I was talking about 'Python letting you change what you like' above.
This is a perfect example of this.  You are changing an internal
structure that in a 'security conscious' language like Java, would not
be permitted.  But because Python lets you, you can make your program
import a class instead of a module.  (Incidently, for consistancy,
you might want to add '_MovieRating.__name__ = __name__' to make sure
that the module name is the same as the class name when you go to check
things.

But you doing this will also have to risk breaking reload() code.  If
that is an acceptable risk, then there's nothing wrong.  Otherwise,
you might have to handle that (reload will only work with a module
object).

> So in java if there's a functon which accepts the movie ratings,
> 
> void func(MovieRating rating,<something else){
> 
> }
> 
> We have been taught to use enum pattern in java to store constants instead
> of primtives like
> ints or strings because we get the benefit of type checking in the compile
> stage itself and no one
> can send in a wrong rating value.

They added enums to C thirty years ago.  They were rarely ever used.
Programmers decided to use CPP #define's instead.  There were a number of
reasons why.  My point is: just because one language uses a construct,
it does not mean it is necessary the way you should do it in another
language.

Feel free to use Python's features, and not be constrainted by how you
have used other languages. :)

> Since this kind of a things cannot be done in python ,should i be writing
> this kind of code in python as well??
> 
> def func(rating,x)
> 	if type(rating) != MovieRating:
> 		raise 'You have passed an Incorrect type'
> 
> if i do that then all my python functions and methods will be littered with
> such type checking code!

There is nothing stopping you from doing this, but you should use
isinstance instead.  It will handle instances from subclasses better.

But also, let's say that you have something you want to add later,
how about a HotelRating.  Then you'll have to change all your code to
make sure that you handle the types properly.

What you might want to think about is to have a general 'Rating' -
what ideas are important to capture about a rating.  Then make sure you
use the objects based on those ideas.  Trust your program and the
developer to co-operate with each other.

> even after a couple of months of python..i think i have not been able to
> understand the differences in the way
> you code in java and python!  :-(
> probably am missing something here..the purpose of the 2 languages appear to
> be very different to me now.

I'd say that you are correct, the purposes of the languages are different.
Java was designed as a strongly typed, platform-independent language that
was similar, but 'better' than C++.  Python was designed with a very
different idea - a language with a simple, concise syntax that is powerful
enough to do what you would like from a high-level language.

> anyways,
> i took a look at the __slots__ concept as well which i guess does not allow
> us to add attributes to an instance.
> I saw a recipe for writing properties. That was smart!
> But now python supports properties at syntax level. I tried that out with
> py2.2
> 
> Then what prevents python from having a final equivalent when we could have
> such nice things like properties?

Yes, 'properties', as a construct, were added in Python 2.2.  But they
were there before.  Just that the coding of them was a little less clear
before (this is debatable, I found that the added properties just made
things more confusing for people), or more explicit depending on how
you thought of the idea of 'properties'.

Before Python 2.2, one way you could have __slot__ properties is with:

class Slot-Mixin:
  def slotinit(self):  # called by __init__()
    self.__dict__['slots'] = {}
    for slotname in self.__class__.__slots__:
      self.slots[slotname] = None
  def __getattr__(self, attr):
    if attr in self.__slots__:
      return self.slots[attr]
    else:
      raise AttributeError(attr)
  def __setattr__(self, attr, value):
    if attr in self.__slots__:
      self.slots[attr] = value
    else:
      self.__dict__[attr] = value
  def __delattr__(self, attr):
    if attr in self.__slots__:
      raise AttributeError("cannot delete slot property")
    else:
      del self.__dict__[attr]

And for the 'get_' and 'set_' methods, you could do this by adding
another test to each of the methods.  It gets complicated when you have
subclasses, but then, that is why we wanted the new attribute methods. :)

The point here is that these mechanisms are used in other languages,
and they are not always needed in Python.  Sometimes there are ways that
just takes some exposure and alternate programming to figure out.

  -Arcege