static class methods and data members

N

Neil Zanella

Hello,

I would like to know whether it is possible to define static class methods
and data members in Python (similar to the way it can be done in C++ or Java).
These do not seem to be mentioned in "Learning Python" by Mark Lutz and David
Ascher. It seems like they are a relatively new feature... It seems to me that
any truly OO programming language should support these so I'm sure that Python
is no exception, but how can these be defined/implemented in Python? Currently
I have Python version 2.3 installed on my system.

Thanks,

Neil
 
P

Phil Frost

take a look at classmethod and staticmethod with pydoc, in the docs, or
help(). Static data members are done like so:

Class C:
iAmStatic = 1
def __init__(self):
self.iAmNotStatic = 2

Thinking of this in terms of "static" and "automatic" isn't the way to
go, really. That's C's way of doing it, and it's in Java only because
Java is nothing more than C.

Here's how it works: There are classes, and there are instances of those
classes. Each has a namespace. when one does <instance>.name, "name" is
located first in the instance namespace, then in the class namespace.

However, assignment is different. Assignment just looks in the instance
namespace, and if it's not there, it creates it. Thus if one were to do
"self.iAmStatic" in a method of C, that does not change the value of
iAmStatic for all instances of C. However, one can do "C.iAmStatic"
anywhere, and that will change "iAmStatic" for all instances of C that
do not have 'iAmStatic' bound to something at the instance level.

The best way to understand this is through experimentation in the
interactive interpreter. To make things easier, you can peek inside
python's implementation by doing C.__dict__ or anInstanceOfC.__dict__ to
see the dictionary that represents that namespace.

After you have absorbed this, you will probably see the use of
classmethod, as it's not immediately apparent if you aren't familiar with
Python. Happy hacking!
 
N

Neil Zanella

Phil Frost said:
take a look at classmethod and staticmethod with pydoc, in the docs, or
help(). Static data members are done like so:

Class C:
iAmStatic = 1
def __init__(self):
self.iAmNotStatic = 2

Thinking of this in terms of "static" and "automatic" isn't the way to
go, really. That's C's way of doing it, and it's in Java only because
Java is nothing more than C.

Here's how it works: There are classes, and there are instances of those
classes. Each has a namespace. when one does <instance>.name, "name" is
located first in the instance namespace, then in the class namespace.

However, assignment is different. Assignment just looks in the instance
namespace, and if it's not there, it creates it. Thus if one were to do
"self.iAmStatic" in a method of C, that does not change the value of
iAmStatic for all instances of C. However, one can do "C.iAmStatic"
anywhere, and that will change "iAmStatic" for all instances of C that
do not have 'iAmStatic' bound to something at the instance level.

The best way to understand this is through experimentation in the
interactive interpreter. To make things easier, you can peek inside
python's implementation by doing C.__dict__ or anInstanceOfC.__dict__ to
see the dictionary that represents that namespace.

Phil,

Your explanation is so clear, it should be included in just about any
book on Python!!! Thank you so much!!!
After you have absorbed this, you will probably see the use of
classmethod, as it's not immediately apparent if you aren't familiar with
Python. Happy hacking!

The http://www.python.org/2.2.1/descrintro.html#staticmethods you mentioned
really does contain some of the information I was missing pertaining to
classmethod and staticmethod. I wonder how come this file was not
installed on my Fedora Core 2 Linux distro. I also notice that
there is no corresponding file with the same name located at
http://www.python.org/doc/2.3.4/. The document seems to have
been removed from later Python documentation versions... how
come?

So, unlike Python classmethods which are roughly the equivalent
of C++ static class methods, Python staticmethods really know nothing about
the members of the class that encloses them and act pretty much like external
defs. So what's the advantage of a staticmethod over an external def?

The cls first argument to a Python classmethod is analogous to the self
first argument to __init__: when you say Class.cmethod() the Class instance
is passed as the first parameter to the class method, and when you say
instance = Class(), the instance being constructed is passed to __init__
as self, and when you say instance.imethod(), the instance is passed to
imethod() as the first parameter, self. The parameters cls and self are
barely named so by convention: they are not keywords in Python, unlike
say the this pointer which is a keyword in C++.

While qualification within a class is optional in languages like C++ and
Java, in Python you must always qualify instance variables with self within
instance methods, and always qualify class variables with cls within Python
class methods.

Since python static methods know nothing about a class, they are equivalent
to methods defined outside a class, except they may be called with the class
as the first argument (for no good reason).

Feedback, reclarification, or other,
on the above comments greatly appreciated.

Thanks,

Neil

#!/usr/bin/python

class Foo:
x = 0
y = 1
def foo(cls):
print "classmethod: hello"
print cls.x
foo = classmethod(foo)
def bar():
print "staticmethod: hello"
print Foo.x
bar = staticmethod(bar)

if __name__ == "__main__":
Foo.foo()
Foo.bar()
 
J

Jacek Generowicz

Warning: you probably don't want to bother reading all the stuff
between the "==========" lines

========================================================================

So, unlike Python classmethods which are roughly the equivalent of
C++ static class methods, Python staticmethods really know nothing
about the members of the class that encloses them

And what do C++ static methods know about the class in which they are
defined? Well, they know about the class members, but have no way of
acessing any of them (other than the static ones) because there is no
this pointer. You do realize that even in C++ and Java there is a
first parameter equivalent to Python's self ... only in C++ and Java
that parameter is hidden by the surface syntax. Try looking at the
code generated by the compiler for (non-static) member functions, and
you'll see that the first parameter is the class instance ("this"),
just like in Python ... only Python doesn't lie to you about this
fact.

In C++ static methods have no "this" poniter, so they have no means of
accessing any instance attributes, because they have no knowledge of
any paricular instance. But because it is normal in C++ to access
instance attributes without explicitly specifying "this", it is
temping to be fooled that

struct foo {
int i;
static int geti() { return i; }
};

int main() {
foo f;
f.geti();
return 0;
}

might compile.

So, all you gain in C++ static methods is installing the function in
the scope of the class ..
and act pretty much like external defs.

.... just like C++ static methods.

The only practical difference between C++ static methods and Python
staticmethods is that in C++ you can access other _static_ methods (and
static data) of the class without explicitly specifying the scope in
which it is to be found:

struct foo {
static int i;
static int geti() { return i; } // this will access foo::i
};

class foo:

i = 3

def sgeti():
return foo.i # In Python must explicitly give the scope
sgeti = staticmethod(sgeti)

def cgeti(cls):
return cls.i # In Python must explicitly give the scope
cgeti = classmethod(cgeti)

========================================================================
So what's the advantage of a staticmethod over an external def?

It's in a namespace which the author considers to be appropriate.

Now, if you were to ask whether there is anything that can be done
with staticmethods that can's be done whith classmethods ... I'd be
hard pushed to imagine what sort of thing this could be. Anyone?

Maybe there's a minimal efficiency consideration.
The cls first argument to a Python classmethod is analogous to the self
first argument to __init__: when you say Class.cmethod() the Class instance
is passed as the first parameter to the class method,

Careful with your choice of words. The class of which the instance is
an instance (yes, the actual class itself) is passed as the first
parameter to the class method.

(There is another interpretation of the words you wrote, which is more
correct, but it's harder work to interpret your words that way :)
and when you say instance = Class(), the instance being constructed
is passed to __init__ as self, and when you say instance.imethod(),
the instance is passed to imethod() as the first parameter,
self. The parameters cls and self are barely named so by convention:
they are not keywords in Python, unlike say the this pointer which
is a keyword in C++.

While qualification within a class is optional in languages like C++ and
Java, in Python you must always qualify instance variables with self within
instance methods, and always qualify class variables with cls within Python
class methods.

Very lucid indeed.
Since python static methods know nothing about a class, they are equivalent
to methods defined outside a class, except they may be called with the class
as the first argument (for no good reason).

Some people consider organizing things in namespaces to be an
extremely good reason. (Type "import this" into your Python REPL and
read the last line that appears.)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,900
Latest member
Nell636132

Latest Threads

Top