[Edu-sig] a question on java attributes vs. python
Kirby Urner
urnerk@qwest.net
Tue, 29 Apr 2003 07:34:08 -0700
At 03:35 AM 4/29/2003 -0400, Leif Johnson wrote:
>On Tue, 29 Apr 2003, ali wrote:
>
> > is there a python counterpart for the declaration of class attributes in
> > java like static, private, protected???
>
>AFAIK there's no protected attribute. however, here's a class definition
>with a static and a private variable :
>
>class MyObject:
> ## this is shared among all class instances (static). it's accessed
> ## using self.instances
>
> instances = 0
>
> def __init__(self, attr):
> self.instances += 1
>
> ## this is a private variable because it starts with '__'. within
> ## this class instance it's accessed using self.__myvar, but the
> ## interpreter does some name mangling so external objects can't
> ## have direct access, for example :
> ##
> ## >>> obj = MyObject('a')
> ## >>> print obj.__myvar # (error)
>
> self.__myvar = attr
>
> def get_myvar(self): return self.__myvar
> def set_myvar(self, val): self.__myvar = val
>
> def instance_info(self):
> print self.instances, 'instances of MyObject have been created'
>
>As I learn more Python I'm increasingly pleased with it. In this case, you
>can think of all function definitions in a class as being static, just like
>the static 'instances' variable above ; the function and data symbols are
>simply shared among MyObject instances (although this is a bit more complex
>with inheritance involved ; that's why class functions require the 'self'
>parameter first, from what I understand it's how the static function code
>is tied to a real class instance when called).
Your static instances variable is being overridden by your instantiated
version of instances when you write self.instances += 1. Every new object
will see instances = 0 at the class level, then add 1 to it, referring
to its own self's dictionary.
If you want "group access" to class-level instances for all objects of
type MyObject, then your increment statement should read:
MyObject.instances += 1.
Also, what static classes allow in Java are class methods which do not
require any instances at all in order to be used. This is relatively
new an Python and is accomplished with the staticmethod() builtin:
class Foo:
instances = 0
def add(a,b): return a+b
add = staticmethod(add)
def __init__(self):
Foo.instances += 1
>>> Foo.add(6,7)
13
>>> Foo.instances
0
Note how Foo's add method got used yet no instances of Foo were created.
However, instances would also be able to use add as well.
Your observation that all instances share the same method code (belonging
to the class) is a feature of OO in general, i.e. it's true of Java
methods whether or not they're static. It's not like every instance
duplicates all the method code in its own patch of memory.
However, having an instance does mean you might bind a method to just
the one instance, such that the other objects of the same type wouldn't
have it:
>>> obj = Foo()
>>> def newadd(a,b): return "%s %s" % (a,b)
>>> obj.add = newadd # replace instance method with new version
>>> obj.add(5,6)
>>> '5 6'
>>> obj2 = Foo() # unaffected by the fact that obj has own version
>>> obj2.add(1,2)
3
Such an instance-specific method *would* have its own patch of
memory.
You can rebind a static method as well, in which case the behavior
of the instances will be changed (unless they already have their
own versions):
>>> def newadd2(a,b): return "%s%s" % (a,b) # taking out space
>>> Foo.add = staticmethod(newadd2) # replace static method
>>> obj.add(1,2) # obj already had its own version
'1 2'
>>> obj2.add(1,2) # but obj2 now invokes the class version
'12'
To add to the mix, there's yet another builtin called classmethod which
has no exact equivalent in Java. It binds the class (vs. an instance)
to an implicit first variable, just as ordinary class methods bind
the specific instance to self.
Below, we see two classes derived from Foo, both using Foo's classmethod
to update their respective *class variables* (instances), i.e. we update
the two class variables independently, using a common class method.
>>> class Foo:
def addinstance(cls):
cls.instances += 1
print cls.instances
addinstance = classmethod(addinstance)
>>> class Spam(Foo):
instances = 0
def __init__(self):
self.addinstance()
>>> class Bar(Foo):
instances = 0
def __init__(self):
self.addinstance()
>>> obj1 = Spam()
1
>>> obj2 = Spam()
2
>>> obj3 = Bar()
1
>>>
>I think this is another good example of how Python and Scheme are really
>not so different---functions are data are functions.
I've yet to comprehend OO in Scheme. It seems to be an "advanced topic" in
that language, whereas in Python "everything is an object" so it makes sense
to start thinking in OO terms fairly early.
Kirby
>leif
>
>--
>Leif Morgan Johnson . http://ambient.2y.net/leif/
>IAESTE trainee . http://www.iaeste.org/
>Salomon Automation . http://www.salomon.at/
>
>_______________________________________________
>Edu-sig mailing list
>Edu-sig@python.org
>http://mail.python.org/mailman/listinfo/edu-sig