I was looking into the following code.
On many occasions the __init__ method is not really used but there is a custom initialize function like in the following example:
def __init__(self):
pass
def initialize(self, opt):
# ...
This is then called as:
data_loader = CustomDatasetDataLoader()
# other instance method is called
data_loader.initialize(opt)
I see the problem that variables, that are used in other instance methods, could still be undefined, if one forgets to call this custom initialize function. But what are the benefits of this approach?
Some APIs out in the wild (such as inside setuptools) have similar kind of thing and they use it to their advantage. The __init__ call could be used for the low level internal API while public constructors are defined as classmethods for the different ways that one might construct objects. For instance, in pkg_resources.EntryPoint, the way to create instances of this class is to make use of the parse classmethod. A similar way can be followed if a custom initialization is desired
class CustomDatasetDataLoader(object):
#classmethod
def create(cls):
"""standard creation"""
return cls()
#classmethod
def create_with_initialization(cls, opt):
"""create with special options."""
inst = cls()
# assign things from opt to cls, like
# inst.some_update_method(opt.something)
# inst.attr = opt.some_attr
return inst
This way users of the class will not need two lines of code to do what a single line could do, they can just simply call CustomDatasetDataLoader.create_with_initialization(some_obj) if that is what they want, or call the other classmethod to construct an instance of this class.
Edit: I see, you had an example linked (wish underlining links didn't go out of fashion) - that particular usage and implementation I feel is a poor way, when a classmethod (or just rely on the standard __init__) would be sufficient.
However, if that initialize function were to be an interface with some other system that receives an object of a particular type to invoke some method with it (e.g. something akin to the visitor pattern) it might make sense, but as it is it really doesn't.
Related
I have one class with multiple inheritance. I would like to concat the output from some parents' methods that share the same name. Ideally, I would be able to do this without going through all parent class but selecting explicitly the cases I want.
class my_class1:
def common_method(self): return ['dependency_1']
class my_class2:
def common_method(self): return ['dependency_2']
class my_class3:
def whatever(self): return 'ANYTHING'
class composite(my_class1, my_class2, my_class3):
def do_something_important(self):
return <my_class1.common_method()> + <my_class2.common_method()>
Since you don't want to use the langage mechanisms to call super-methors (which are designed to go through all the methods in the superclasses, even ones that are not known at the time the code is written), just call the methods explitly on the classes you want - by using the class name.
The only thing different that has to be done is that you have to call the method from the class, not from the instance, and then insert the instance manually as first parameter. Python's automatic self reference is only good when calling the method in the most derived sub-class (from which point, in a more common design, it will use super to run its coutnerparts in the superclasses)
For your example to work, you simply have to write it like this:
class my_class1:
def common_method(self): return ['dependency_1']
class my_class2:
def common_method(self): return ['dependency_2']
class my_class3:
def whatever(self): return 'ANYTHING'
class composite(my_class1, my_class2, my_class3):
def do_something_important(self):
return my_class1.common_method(self) + my_class2.common_method(self)
Note, hoever, that if any of the common_methods would call super().common_method in a common ancestor base, that super-method would be run once for each explicit invocation of a sub-class' .common_method.
If you would want to specialize that it would be though to do.
In other words, if you want, a "super" counterpart that would allow you to specify which super-classes to visit when calling the method, and ensure any super-method called by those would run only once - that i feasible, but complicated and error prone. If you can use explicit classes like in this example, it is 100 times simpler.
I just can't see why do we need to use #staticmethod. Let's start with an exmaple.
class test1:
def __init__(self,value):
self.value=value
#staticmethod
def static_add_one(value):
return value+1
#property
def new_val(self):
self.value=self.static_add_one(self.value)
return self.value
a=test1(3)
print(a.new_val) ## >>> 4
class test2:
def __init__(self,value):
self.value=value
def static_add_one(self,value):
return value+1
#property
def new_val(self):
self.value=self.static_add_one(self.value)
return self.value
b=test2(3)
print(b.new_val) ## >>> 4
In the example above, the method, static_add_one , in the two classes do not require the instance of the class(self) in calculation.
The method static_add_one in the class test1 is decorated by #staticmethod and work properly.
But at the same time, the method static_add_one in the class test2 which has no #staticmethod decoration also works properly by using a trick that provides a self in the argument but doesn't use it at all.
So what is the benefit of using #staticmethod? Does it improve the performance? Or is it just due to the zen of python which states that "Explicit is better than implicit"?
The reason to use staticmethod is if you have something that could be written as a standalone function (not part of any class), but you want to keep it within the class because it's somehow semantically related to the class. (For instance, it could be a function that doesn't require any information from the class, but whose behavior is specific to the class, so that subclasses might want to override it.) In many cases, it could make just as much sense to write something as a standalone function instead of a staticmethod.
Your example isn't really the same. A key difference is that, even though you don't use self, you still need an instance to call static_add_one --- you can't call it directly on the class with test2.static_add_one(1). So there is a genuine difference in behavior there. The most serious "rival" to a staticmethod isn't a regular method that ignores self, but a standalone function.
Today I suddenly find a benefit of using #staticmethod.
If you created a staticmethod within a class, you don't need to create an instance of the class before using the staticmethod.
For example,
class File1:
def __init__(self, path):
out=self.parse(path)
def parse(self, path):
..parsing works..
return x
class File2:
def __init__(self, path):
out=self.parse(path)
#staticmethod
def parse(path):
..parsing works..
return x
if __name__=='__main__':
path='abc.txt'
File1.parse(path) #TypeError: unbound method parse() ....
File2.parse(path) #Goal!!!!!!!!!!!!!!!!!!!!
Since the method parse is strongly related to the classes File1 and File2, it is more natural to put it inside the class. However, sometimes this parse method may also be used in other classes under some circumstances. If you want to do so using File1, you must create an instance of File1 before calling the method parse. While using staticmethod in the class File2, you may directly call the method by using the syntax File2.parse.
This makes your works more convenient and natural.
I will add something other answers didn't mention. It's not only a matter of modularity, of putting something next to other logically related parts. It's also that the method could be non-static at other point of the hierarchy (i.e. in a subclass or superclass) and thus participate in polymorphism (type based dispatching). So if you put that function outside the class you will be precluding subclasses from effectively overriding it. Now, say you realize you don't need self in function C.f of class C, you have three two options:
Put it outside the class. But we just decided against this.
Do nothing new: while unused, still keep the self parameter.
Declare you are not using the self parameter, while still letting other C methods to call f as self.f, which is required if you wish to keep open the possibility of further overrides of f that do depend on some instance state.
Option 2 demands less conceptual baggage (you already have to know about self and methods-as-bound-functions, because it's the more general case). But you still may prefer to be explicit about self not being using (and the interpreter could even reward you with some optimization, not having to partially apply a function to self). In that case, you pick option 3 and add #staticmethod on top of your function.
Use #staticmethod for methods that don't need to operate on a specific object, but that you still want located in the scope of the class (as opposed to module scope).
Your example in test2.static_add_one wastes its time passing an unused self parameter, but otherwise works the same as test1.static_add_one. Note that this extraneous parameter can't be optimized away.
One example I can think of is in a Django project I have, where a model class represents a database table, and an object of that class represents a record. There are some functions used by the class that are stand-alone and do not need an object to operate on, for example a function that converts a title into a "slug", which is a representation of the title that follows the character set limits imposed by URL syntax. The function that converts a title to a slug is declared as a staticmethod precisely to strongly associate it with the class that uses it.
I am writing a python API/server to allow an external device (microcontroller) to remotely call methods of an object by sending a string with the name of the method. These methods would be stored in a dictionary. e.g. :
class Server:
...
functions = {}
def register(self, func):
self.functions[func.__name__] = func
def call(self, func_name, args):
self.functions[func_name](*args)
...
I know that I could define functions externally to the class definition and register them manually, but I would really like that the registering step would be done automatically. Consider the following class:
class MyServer(Server):
...
def add(self,a,b):
print a+b
def sub(self,a,b):
print a-b
...
It would work by subclassing a server class and by defining methods to be called. How could I get the methods to be automatically registered in the functions dictionary?
One way that I thought it could be done is with a metaclass that look at a pattern in the methods name add if a match is found, add that methods to the functions dictionary. It seems overkill...
Would it be possible to decorate the methods to be registered? Can someone give me a hint to the simplest solution to this problem?
There is no need to construct a dictionary, just use the getattr() built-in function:
def call(self, func_name, args):
getattr(self, func_name)(*args)
Python actually uses a dictionary to access attributes on objects anyway (it's called __dict__, - but using getattr() is better than accessing it directly).
If you really want to construct that dict for some reason, then look at the inspect module:
def __init__(self, ...):
self.functions = dict(inspect.getmembers(self, inspect.ismethod))
If you want to pick specific methods, you could use a decorator to do that, but as BrenBarn points out, the instance doesn't exist at the time the methods are decorated, so you need to use the mark and recapture technique to do what you want.
This question already has answers here:
Difference between #staticmethod and #classmethod
(35 answers)
Why do we use #staticmethod?
(4 answers)
Closed last month.
I ran into unbound method error in python with this code:
import random
class Sample(object):
def drawSample(samplesize, List):
sample = random.sample(List, samplesize)
return sample
Choices=range(100)
print(Sample.drawSample(5, Choices))
I was able to fix the problem by adding #staticmethod to the method. However, I don't really understand the situation.
What is the point of using "static" methods? Why does it solve the problem in this code, and why are they ever necessary? Conversely, why would I ever not want to do it (i.e., why is extra code needed to make the method static)?
See this article for detailed explanation.
TL;DR
1.It eliminates the use of self argument.
2.It reduces memory usage because Python doesn't have to instantiate a bound-method for each object instiantiated:
>>>RandomClass().regular_method is RandomClass().regular_method
False
>>>RandomClass().static_method is RandomClass().static_method
True
>>>RandomClass.static_method is RandomClass().static_method
True
3.It improves code readability, signifying that the method does not depend on state of the object itself.
4.It allows for method overriding in that if the method were defined at the module-level (i.e. outside the class) a subclass would not be able to override that method.
Static methods have limited use, because they don't have access to the attributes of an instance of a class (like a regular method does), and they don't have access to the attributes of the class itself (like a class method does).
So they aren't useful for day-to-day methods.
However, they can be useful to group some utility function together with a class - e.g. a simple conversion from one type to another - that doesn't need access to any information apart from the parameters provided (and perhaps some attributes global to the module.)
They could be put outside the class, but grouping them inside the class may make sense where they are only applicable there.
You can also reference the method via an instance or the class, rather than the module name, which may help the reader understand to what instance the method is related.
This is not quite to the point of your actual question, but since you've said you are a python newbie perhaps it will be helpful, and no one else has quite come out and said it explicitly.
I would never have fixed the above code by making the method a static method. I would either have ditched the class and just written a function:
def drawSample(samplesize,List):
sample=random.sample(List,samplesize)
return sample
Choices=range(100)
print drawSample(5,Choices)
If you have many related functions, you can group them in a module - i.e, put them all in the same file, named sample.py for example; then
import sample
Choices=range(100)
print sample.drawSample(5,Choices)
Or I would have added an __init__ method to the class and created an instance that had useful methods:
class Sample(object):
'''This class defines various methods related to the sample'''
def __init__(self, thelist):
self.list = thelist
def draw_sample(self, samplesize):
sample=random.sample(self.list,samplesize)
return sample
choices=Sample(range(100))
print choices.draw_sample(5)
(I also changed the case conventions in the above example to match the style recommended by PEP 8.)
One of the advantages of Python is that it doesn't force you to use classes for everything. You can use them only when there is data or state that should be associated with the methods, which is what classes are for. Otherwise you can use functions, which is what functions are for.
Why one would want to define static methods?
Suppose we have a class called Math then
nobody will want to create object of class Math
and then invoke methods like ceil and floor and fabs on it.
So we make them static.
For example doing
>> Math.floor(3.14)
is much better than
>> mymath = Math()
>> mymath.floor(3.14)
So they are useful in some way. You need not create an instance of a class to use them.
Why are not all methods defined as static methods?
They don't have access to instance variables.
class Foo(object):
def __init__(self):
self.bar = 'bar'
def too(self):
print self.bar
#staticmethod
def foo():
print self.bar
Foo().too() # works
Foo.foo() # doesn't work
That is why we don't make all the methods static.
The alternatives to a staticmethod are: classmethod, instancemethod, and function. If you don't know what these are, scroll down to the last section. If a staticmethod is better than any of these alternatives, depends on for what purpose it is written.
advantages of the Python static method
If you don't need access to the attributes or methods of the class or instance, a staticmethod is better than a classmethod or instancemethod. That way it is clear (from the #staticmethod decorator) that the class' and instance's state is not read or modified. However, using a function makes that distinction even clearer (see disadvantages).
The call signature of a staticmethod is the same as that of a classmethod or instancemethod, namely <instance>.<method>(<arguments>). Hence it can easily be replaced by one of the three if that is needed later on or in a derived class. You can't do that with a simple function.
A staticmethod can be used instead of a function to make clear that it subjectively belongs to a class and to prevent namespace conflicts.
disadvantages of the Python static method
It cannot access attributes or methods of the instance or class.
The call signature of a staticmethod is the same as that of a classmethod or instancemethod. This masks the fact that the staticmethod does not actually read or modify any object information. This makes code harder to read. Why not just use a function?
A staticmethod is difficult to re-use if you ever need to call it from outside the class/instance where it was defined. If there is any potential for re-use, a function is the better choice.
The staticmethod is seldom used, so people reading code that includes one may take a little longer to read it.
alternatives to a static method in Python
To address discuss the advantages of the staticmethod, we need to know what the alternatives are and how they differ from each other.
The staticmethod belongs to a class but cannot access or modify any instance or class information.
There are three alternatives to it:
The classmethod has access to the caller's class.
The instancemethod has access to the caller's instance and its class.
The function has nothing to do with classes. It is the closest in capability to the staticmethod.
Here's what this looks like in code:
# function
# has nothing to do with a class
def make_cat_noise(asker_name):
print('Hi %s, mieets mieets!' % asker_name)
# Yey, we can make cat noises before we've even defined what a cat is!
make_cat_noise('JOey') # just a function
class Cat:
number_of_legs = 4
# special instance method __init__
def __init__(self, name):
self.name = name
# instancemethod
# the instance (e.g. Cat('Kitty')) is passed as the first method argument
def tell_me_about_this_animal(self, asker_name):
print('Hi %s, This cat has %d legs and is called %s'
% (asker_name, self.number_of_legs, self.name))
# classmethod
# the class (e.g. Cat) is passed as the first method argument
# by convention we call that argument cls
#classmethod
def tell_me_about_cats(cls, asker_name):
print("Hi %s, cats have %d legs."
% (asker_name, cls.number_of_legs))
# cls.name # AttributeError because only the instance has .name
# self.name # NameError because self isn't defined in this namespace
# staticmethod
# no information about the class or the instance is passed to the method
#staticmethod
def make_noise(asker_name):
print('Hi %s, meooow!' % asker_name)
# class and instance are not accessible from here
# one more time for fun!
make_cat_noise('JOey') # just a function
# We just need the class to call a classmethod or staticmethod:
Cat.make_noise('JOey') # staticmethod
Cat.tell_me_about_cats('JOey') # classmethod
# Cat.tell_me_about_this_animal('JOey') # instancemethod -> TypeError
# With an instance we can use instancemethod, classmethod or staticmethod
mycat = Cat('Kitty') # mycat is an instance of the class Cat
mycat.make_noise('JOey') # staticmethod
mycat.tell_me_about_cats('JOey') # classmethod
mycat.tell_me_about_this_animal('JOey') # instancemethod
When you call a function object from an object instance, it becomes a 'bound method' and gets the instance object itself is passed in as a first argument.
When you call a classmethod object (which wraps a function object) on an object instance, the class of the instance object gets passed in as a first argument.
When you call a staticmethod object (which wraps a function object), no implicit first argument is used.
class Foo(object):
def bar(*args):
print args
#classmethod
def baaz(*args):
print args
#staticmethod
def quux(*args):
print args
>>> foo = Foo()
>>> Foo.bar(1,2,3)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unbound method bar() must be called with Foo instance as first argument (got int instance instead)
>>> Foo.baaz(1,2,3)
(<class 'Foo'>, 1, 2, 3)
>>> Foo.quux(1,2,3)
(1, 2, 3)
>>> foo.bar(1,2,3)
(<Foo object at 0x1004a4510>, 1, 2, 3)
>>> foo.baaz(1,2,3)
(<class 'Foo'>, 1, 2, 3)
>>> foo.quux(1,2,3)
(1, 2, 3)
static methods are great because you don't have to declare an instance of the object to which the method belongs.
python's site has some great documentation on static methods here:
http://docs.python.org/library/functions.html#staticmethod
In my estimation, there is no single performance benefit of using #staticmethods compared to just defining the function outside of and separate from the class it would otherwise be a #staticmethod of.
The only thing I would say justifies their existence is convenience. Static methods are common in other popular programming languages, so why not python? If you want to create a function with behavior that is very closely associated with the class you are creating it for but it doesn't actually access/modify the internal data of an instance of the class in a way that justifies conceptualizing it as a typical method of that class then slap a #staticmethod above it and anyone reading your code will immediately learn a lot about the nature of the method and its relationship to the class.
One thing I occasionally like to do is place functionality that my class uses internally a lot into private #staticmethods. That way I do not clutter the API exposed by my module with methods that no one using my module would ever need to see let alone use.
Static methods have almost no reason-to-be in Python. You use either instance methods or class methods.
def method(self, args):
self.member = something
#classmethod
def method(cls, args):
cls.member = something
#staticmethod
def method(args):
MyClass.member = something
# The above isn't really working
# if you have a subclass
Because namespacing functions is nice (as was previously pointed out):
When I want to be explicit about methods that don't change the state of the object, I use static methods. This discourages people on my team to start changing the object's attributes in those methods.
When i refactor really rotten code, I start by trying to make as many methods #staticmethod as possible. This allows me then to extract these methods into a class - though I agree, this is rarely something I use, it did came in helpful a few times.
I have a python fuse project based on the Xmp example in the fuse documentation. I have included a small piece of the code to show how this works. For some reason get_file does get called and the class gets created, but instead of fuse calling .read() on the class from get_file (file_class) fuse keeps calling Dstorage.read() which defeats the purpose in moving the read function out of that class.
class Dstorage(Fuse, Distributor):
def get_file(self, server, path, flags, *mode):
pass
# This does some work and passes back an instance of
# a class very similar to XmpFile
def main(self, *a, **kw):
self.file_class = self.get_file
return Fuse.main(self, *a, **kw)
I have my code hosted on launchpad, you can download it with this command.
bzr co https://code.launchpad.net/~asa-ayers/+junk/dstorage
bzr branch lp:~asa-ayers/dstorage/trunk
solution:
I used a proxy class that subclasses the one I needed and in the constructor I get the instance of the class I need and overwrite all of the proxy's methods to simply call the instance methods.
Looking at the code of the Fuse class (which is a maze of twisty little passages creating method proxies), I see this bit (which is a closure used to create a setter inside Fuse.MethodProxy._add_class_type, line 865):
def setter(self, xcls):
setattr(self, type + '_class', xcls)
for m in inits:
self.mdic[m] = xcls
for m in proxied:
if hasattr(xcls, m):
self.mdic[m] = self.proxyclass(m)
When you do self.file_class = self.get_file, this gets called with self.get_file, which is a bound method. The loop over proxied attributes is expecting to be able to get the attributes off the class you set, to put them into its mdic proxy dictionary after wrapping them, but they aren't there, because it's a bound method, rather than a class. Since it can't find them, it reverts to calling them on Dstorage.
So, long story short, you can't use a callable that returns an instance (kind of a pseudo-class) instead of a class here, because Fuse is introspecting the object that you set to find the methods it should call.
You need to assign a class to file_class - if you need to refer back to the parent instance, you can use the nested class trick they show in the docs.