Explicit passing of Self when calling super class's __init__ in python - python

This question is in relation to posts at What does 'super' do in Python? , How do I initialize the base (super) class? , and Python: How do I make a subclass from a superclass? which describes two ways to initialize a SuperClass from within a SubClass as
class SuperClass:
def __init__(self):
return
def superMethod(self):
return
## One version of Initiation
class SubClass(SuperClass):
def __init__(self):
SuperClass.__init__(self)
def subMethod(self):
return
or
class SuperClass:
def __init__(self):
return
def superMethod(self):
return
## Another version of Initiation
class SubClass(SuperClass):
def __init__(self):
super(SubClass, self).__init__()
def subMethod(self):
return
So I'm a little confused about needing to explicitly pass self as a parameter in
SuperClass.__init__(self)
and
super(SubClass, self).__init__().
(In fact if I call SuperClass.__init__() I get the error
TypeError: __init__() missing 1 required positional argument: 'self'
). But when calling constructors or any other class method (ie :
## Calling class constructor / initiation
c = SuperClass()
k = SubClass()
## Calling class methods
c.superMethod()
k.superMethod()
k.subMethod()
), The self parameter is passed implicitly .
My understanding of the self keyword is it is not unlike the this pointer in C++, whereas it provides a reference to the class instance. Is this correct?
If there would always be a current instance (in this case SubClass), then why does self need to be explicitly included in the call to SuperClass.__init__(self)?
Thanks

This is simply method binding, and has very little to do with super. When you can x.method(*args), Python checks the type of x for a method named method. If it finds one, it "binds" the function to x, so that when you call it, x will be passed as the first parameter, before the rest of the arguments.
When you call a (normal) method via its class, no such binding occurs. If the method expects its first argument to be an instance (e.g. self), you need to pass it in yourself.
The actual implementation of this binding behavior is pretty neat. Python objects are "descriptors" if they have a __get__ method (and/or __set__ or __delete__ methods, but those don't matter for methods). When you look up an attribute like a.b, Python checks the class of a to see if it has a attribute b that is a descriptor. If it does, it translates a.b into type(a).b.__get__(a, type(a)). If b is a function, it will have a __get__ method that implements the binding behavior I described above. Other kinds of descriptors can have different behaviors. For instance, the classmethod decorator replaces a method with a special descriptor that binds the function the class, rather than the instance.
Python's super creates special objects that handle attribute lookups differently than normal objects, but the details don't matter too much for this issue. The binding behavior of methods called through super is just like what I described in the first paragraph, so self gets passed automatically to the bound method when it is called. The only thing special about super is that it may bind a different function than you'd get lookup up the same method name on self (that's the whole point of using it).

The following example might elucidate things:
class Example:
def method(self):
pass
>>> print(Example.method)
<unbound method Example.method>
>>> print(Example().method)
<bound method Example.method of <__main__.Example instance at 0x01EDCDF0>>
When a method is bound, the instance is passed implicitly. When a method is unbound, the instance needs to be passed explicitly.
The other answers will definitely offer some more detail on the binding process, but I think it's worth showing the above snippet.

The answer is non-trivial and would probably warrant a good article. A very good explanation of how super() works is brilliantly given by Raymond Hettinger in a Pycon 2015 talk, available here and a related article.
I will attempt a short answer and if it is not sufficient I (and hopefully the community) will expand on it.
The answer has two key pieces:
Python's super() needs to have an object on which the method being overridden is called, so it is explicitly passed with self. This is not the only possible implementation and in fact, in Python 3, it is no longer required that you pass the self instance.
Python super() is not like Java, or other compiled languages, super. Python's implementation is designed to support the multiple collaborative inheritance paradigm, as explained in Hettinger's talk.
This has an interesting consequence in Python: the method resolution in super() depends not only on the parent class, but on the children classes as well (consequence of multiple inheritance). Note that Hettinger is using Python 3.
The official Python 2.7 documentation on super is also a good source of information (better understood after watching the talk, in my opinion).

Because in SuperClass.__init__(self), you're calling the method on the class, not the instance, so it cannot be passed implicitly. Similarly you cannot just call SubClass.subMethod(), but you can call SubClass.subMethod(k) and it'll be equivalent to k.subMethod(). Similarly if self refers to a SubClass then self.__init__() means SubClass.__init__(self), so if you want to call SuperClass.__init you have to call it directly.

Related

When do you need to pass arguments to python super()?

A use case of the super() builtin in python is to call an overridden method. Here is a simple example of using super() to call Parent class's echo function:
class Parent():
def echo(self):
print("in Parent")
class Child(Parent):
def echo(self):
super().echo()
print("in Child")
I've seen code that passes 2 parameters to super(). In that case, the signature looks somehing like super(subClass, instance) where subClass is the sub class calling super() from, and instance is the instance the call being made from, ie self. So in the above example, the super() line would become:
super(Child, self).echo()
Looking at python3 docs, these 2 use cases are the same when calling from inside of a class.
Is calling super() with 2 parameters completely deprecated as of python3? If this is only deprecated for calling overridden functions, can you show an example why they're needed for other cases?
I'm also interested to know why python needed those 2 arguments? Are they injected/evaluated when making super() calls in python3, or they're just not needed in that case?
If you don't pass the arguments, Python 3 makes an effort to provide them for you. It's a little kludgy, but it usually works. Essentially, it just assumes the first parameter to your method is self (the second argument to super), and when the class definition completes, it provides a virtual closure scope for any function that refers to super or __class__ that defines __class__ as the class you just defined, so no-arg super() can check the stack frame to find __class__ as the first argument.
This usually works, but there are cases where it doesn't:
In staticmethods (since the first argument isn't actually the class), though staticmethods aren't really supposed to participate in the inheritance hierarchy the same way, so that's not exactly unexpected.
In functions that take *args as the first argument (which was the only safe way to implement any method that accepted arbitrary keyword arguments like dict subclasses prior to 3.8, when they introduced positional-only arguments).
If the super call is in a nested scope, which can be implicit, e.g. a generator expression, or comprehension of any kind (list, set, dict), since the nested scope isn't directly attached to the class, so it doesn't get the __class__ defining magic that methods attached to the class itself get.
There are also rare cases where you might want to explicitly bypass a particular class for resolving the parent method, in which case you'd need to explicitly pass a different class from later in the MRO than the one it would pull by default. This is deep and terrible magic, so I don't recommend it, but I think I've had cause to do it once.
All of those are relatively rare cases, so most of the time, for code purely targeting Python 3, you're fine using no-arg super, and only falling back to explicitly passing arguments when you can't use it for whatever reason. No-arg super is cleaner, faster, and during live development can be more correct (if you replace MyClass, instances of the old version of the class will have the old version cached and no-arg super will continue to work, where looking it up manually in your globals would find the new version of the class and explode), so use it whenever you can.
In Python 3, super() with zero arguments is already the shortcut for super(__class__, self). See PEP3135 for complete explanation.
This is not the case for Python 2, so I guess that most code examples you found were actually written for Python 2 (or Python2+3 compatible)

How are Python static methods useful (except as a namespace)? [duplicate]

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.

how self can be passed while inheritance?

class Trout(Fish):
def __init__(self, water = "freshwater"):
self.water = water
super().__init__(self)
In this line super().__init__(self) how is the self parameter passed to the function?
Say you have the code
f = Trout()
Behind the scenes, this is roughly equivalent to
f = Trout.__new__()
Trout.__init__(f)
Inside Trout.__init__, super() returns a proxy object that represents the appropriate class in the method resolution order of Trout; you don't actually have to pass self as an explicit argument; super().__init__ defaults to a bound method with self already present.
The object calling the method is implicitly (automatically) the first argument to the method. This is an agreement the language makes with itself.
In practical terms, assume you have an object obj of some type that has a method stuff that takes a simple Boolean argument. You invoke the method as
obj.stuff(True)
If this were a "normal" function, you would invoke it as
stuff(obj, True)
... but that's not how the syntax of classes and objects works. In any case, the function/method header looks the same:
def stuff(self, flag):
The difference here is that the each object class can have a method stuff, and we don't have to give them different names. When we use class methods, the compiler knows which one to use by looking at the class of the invoking object.
In the specific case of the __init__ method, the object is created immediately upon entry and assigned to self. This is another automatic agreement the language makes with itself: this specially-named function includes an invisible creation of a default object when you enter.

How to tell python non-class objects from class objects

I am new to python. I think non-class objects do not have bases attribute whereas class objects do have it. But I am not sure. How does python\cpython checks if an object is non-class or class and passes the correct arguments to the object's descriptor attribute accordingly during the attribute access?
============================================
updated:
I was learning how __getattribute__ and descriptor cooperate together to make bounded methods. I was wondering how class object & non-class object invokes the descriptor's __get__ differently. I thought those 2 types of objects shared the same __getattribute__ CPython function and that same function would have to know if the invoking object was a class or non-class. But I was wrong. This article explains it well:
http://docs.python.org/dev/howto/descriptor.html#functions-and-methods
So class object use type.__getattribute__ whereas non-class object use object.__getattribute__. They are different CPython functions. And super has a third __getattribute__ CPython implementation as well.
However, about the super one, the above article states that:
quote and quote
The object returned by super() also has a custom _getattribute_() method for invoking descriptors. The call super(B, obj).m() searches obj._class_._mro_ for the base class A immediately following B and then returns A._dict_['m']._get_(obj, A). If not a descriptor, m is returned unchanged. If not in the dictionary, m reverts to a search using object._getattribute_().
The statement above didn't seem to match my experiment with Python3.1. What I saw is, which is reasonable to me:
super(B, obj).m ---> A.__dict__['m'].__get__(obj, type(obj))
objclass = type(obj)
super(B, objclass).m ---> A.__dict__['m'].__get__(None, objclass)
A was never passed to __get__
It is reasonable to me because I believe objclass (rather than A) 's mro chain is the one needed within m especially for the second case.
Was I doing something wrong? Or I didn't understand it correctly?
As the commenters asked: Why do you care? Usually that's a sign of not using Python the way it was meant to be used.
A very powerful concept of Python is duck typing. You don't care about the type or class of an object as long as it exposes the attributes you need.
how about inspect.isclass(objectname)?
more info here: http://docs.python.org/library/inspect.html

What is the purpose of static methods? How do I know when to use one? [duplicate]

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.

Categories

Resources