staticmethod and classmethod

C

C Gillespie

Hi,

Does anyone know of any examples on how (& where) to use staticmethods and
classmethods?

Thanks

Colin
 
S

Steven Bethard

C said:
Does anyone know of any examples on how (& where) to use staticmethods and
classmethods?

My personal experience is that I almost *never* want a staticmethod.
The things that I would have written as a staticmethod in Java I simply
write as a module-level function in Python.

I do occasionally used classmethods though to build alternate
constructors. I recently had a class with a constructor that looked like:

class C(object):
def __init__(self, *args):
...

I already had code working with this constructor, but I needed to add an
optional 'index' parameter. I found the clearest way to do this was
something like:

class C(object):
def __init__(self, *args):
...
@classmethod
def indexed(cls, index, *args):
...
obj = cls(*args)
obj.index = index
...
return obj

Then the classes that needed the 'index' parameter simply use
C.indexed() as the constructor instead of C().

STeVe
 
J

John Roth

C Gillespie said:
Hi,

Does anyone know of any examples on how (& where) to use staticmethods and
classmethods?

A python class method is closer to a Java static method than a python static
method.
Class methods can be useful if you want to be able to change objects in the
class, or if you want to be able to use inheritance, neither of which python
static
methods allow you to do cleanly.

Another, and rather esoteric use, is to use the class as its own instance.

I find that static methods are useful when I want to import a class from
a module, and don't want to import the module itself or a lot of bits and
pieces from the module. The class gives a place to park the method, and
also lets you use inheritance, neither of which putting it into the module
does.

John Roth
 
B

Bruno Desthuilliers

C Gillespie a écrit :
Hi,

Does anyone know of any examples on how (& where) to use staticmethods and
classmethods?

Here's an example from a ldap lib (work in progress, not finished, and
all other disclaimers).

The class methods are here:

# ----------------------------------------------------------------------
# Base class for LDAP Objects
# ----------------------------------------------------------------------
class LdapObject(object):
"""
Base class for LDAP data objects.
"""

(snip)

# ------------------------------------------------------------------
def query_class(cls):
return "(objectClass=%s)" % cls.query_object_class
query_class = classmethod(query_class)

# ------------------------------------------------------------------
def query_id(cls, ldap_id):
return "(& %s (%s=%s))" % (cls.query_class(), cls.id_attribute,
ldap_id)
query_id = classmethod(query_id)

# ------------------------------------------------------------------
def query(cls, filters=None):
if filters is None:
return cls.query_class()
else:
return cls._decorate_query(filters(cls))
query = classmethod(query)

# ------------------------------------------------------------------
def _decorate_query(cls, query):
return "(& %s %s)" % (cls.query_class(), query)
_decorate_query = classmethod(_decorate_query)


class LdapContact(LdapObject):
"""
Wraps a MozillaAbPersonObsolete/OpenLDAPperson entry.
"""

# ldap objectClass(es)
object_classes =('OpenLDAPperson',
'MozillaAbPersonObsolete', )

# which one we'll use for queries
query_object_class = 'MozillaAbPersonObsolete'
id_attribute = 'uid'
sort_keys = ('displayName',)

(snip)


They are used here (LdapItemKlass is supposed to be a subclass of
LdapObject, like LdapContact above):

# ----------------------------------------------------------------------
# The LdapConnection itself.
# ----------------------------------------------------------------------
class LdapConnection(object):

(snip)

# ------------------------------------------------------------------
def list_items(self, ldapItemKlass, sort_keys=None,
filters=None):
items = [ldapItemKlass(self, entry) \
for entry in self._search( \
ldapItemKlass.query(filters, match_op) \
)]
if sort_keys is None:
sort_keys = ldapItemKlass.sort_keys
return self.sort(items, sort_keys)

# ------------------------------------------------------------------
def get_item(self, ldapItemKlass, ldap_id):
entry = self._get_item(ldapItemKlass, ldap_id)
if entry is not None:
entry = ldapItemKlass(self, entry)
return entry

(snip)


And client code may look like this (LdapContact being a subclass of
LdapObject):

cnx = LdapConnection(...).connect()
all_contacts = cnx.list_items(LdapContact)
someone = cnx.get_item(LdapContact, 'uid=someone')


Since we don't have any instance before running the query, we can't use
instance methods... Still, most of the knowledge required to build the
appropriate query belongs to the LdapContact (or whatever) class.

HTH
Bruno
 
?

=?iso-8859-1?Q?Fran=E7ois?= Pinard

[Bruno Desthuilliers]
C Gillespie a écrit :
Here's an example from a ldap lib [...]

I recently had a use case for class methods while converting a PL/I
program to Python: a lot of global declarations, where in many cases,
procs could be regrouped around well identified subsets of globals.

The idea is to create a class for each related group of globals. The
global declarations themselves become class variables of that class, and
related procs become class methods meant to act on these class variables.

For best clarity and legibility while doing so, one should use all
lowercase class names in such cases, and use `self' instead of `cls' for
the first formal argument of class methods[1].

Then, one use these classes as if they were each the single instance
of a similar class with usual methods. If one later changes his/her
mind and wants more usual objects, and not allocated statically (!),
merely remove all classmethod declarations, capitalise the first letter
of class names, and create one instance per class into the all lowercase
name of the class. That's seemingly all.
 

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

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,581
Members
45,057
Latest member
KetoBeezACVGummies

Latest Threads

Top