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.
Related
I have a class
class A:
def sample_method():
I would like to decorate class A sample_method() and override the contents of sample_method()
class DecoratedA(A):
def sample_method():
The setup above resembles inheritance, but I need to keep the preexisting instance of class A when the decorated function is used.
a # preexisting instance of class A
decorated_a = DecoratedA(a)
decorated_a.functionInClassA() #functions in Class A called as usual with preexisting instance
decorated_a.sample_method() #should call the overwritten sample_method() defined in DecoratedA
What is the proper way to go about this?
There isn't a straightforward way to do what you're asking. Generally, after an instance has been created, it's too late to mess with the methods its class defines.
There are two options you have, as far as I see it. Either you create a wrapper or proxy object for your pre-existing instance, or you modify the instance to change its behavior.
A proxy defers most behavior to the object itself, while only adding (or overriding) some limited behavior of its own:
class Proxy:
def __init__(self, obj):
self.obj = obj
def overridden_method(self): # add your own limited behavior for a few things
do_stuff()
def __getattr__(self, name): # and hand everything else off to the other object
return getattr(self.obj, name)
__getattr__ isn't perfect here, it can only work for regular methods, not special __dunder__ methods that are often looked up directly in the class itself. If you want your proxy to match all possible behavior, you probably need to add things like __add__ and __getitem__, but that might not be necessary in your specific situation (it depends on what A does).
As for changing the behavior of the existing object, one approach is to write your subclass, and then change the existing object's class to be the subclass. This is a little sketchy, since you won't have ever initialized the object as the new class, but it might work if you're only modifying method behavior.
class ModifiedA(A):
def overridden_method(self): # do the override in a normal subclass
do_stuff()
def modify_obj(obj): # then change an existing object's type in place!
obj.__class__ = ModifiedA # this is not terribly safe, but it can work
You could also consider adding an instance variable that would shadow the method you want to override, rather than modifying __class__. Writing the function could be a little tricky, since it won't get bound to the object automatically when called (that only happens for functions that are attributes of a class, not attributes of an instance), but you could probably do the binding yourself (with partial or lambda if you need to access self.
First, why not just define it from the beginning, how you want it, instead of decorating it?
Second, why not decorate the method itself?
To answer the question:
You can reassign it
class A:
def sample_method(): ...
pass
A.sample_method = DecoratedA.sample_method;
but that affects every instance.
Another solution is to reassign the method for just one object.
import functools;
a.sample_method = functools.partial(DecoratedA.sample_method, a);
Another solution is to (temporarily) change the type of an existing object.
a = A();
a.__class__ = DecoratedA;
a.sample_method();
a.__class__ = A;
I am new to opp programming.I wanted to know what to do with a function that is inside the class but does not use self value
For example
class example:
def __init__(self,n):
self.number=n
def get_t(self,t):
return t*t
def main(self):
b=1
k=self.get_t(b)
From the example the function get_t has nothing to do with self value.
So I wanted to know where to place the function get_t or may be how to restructure the class.
Thank you for your consideration
What you're looking for are static methods. To declare a method static do it like this
#staticmethod
def foo():
pass
Nothing. Just let it be, Python won't complain about it and there's nothing fundamentally wrong about methods that doesn't use its instance. If your linter complains about it, you can shut up that warning. These kind of helper functions are often intended to be private methods that aren't intended to be used externally, you may want to prefix the name with underscore to indicate that.
Convert it into a free function. Python is an OOP language, but it's also a mixed paradigm language, unlike Java, for example, you can actually create a function outside of a class declaration. Pythonic code does not necessarily means putting everything into classes, and often a free function is perfectly suitable place for functions that doesn't involve a particular object instance.
def get_t(t):
return t*t
class example:
def main(self):
b=1
k=self.get_t(b)
If you want to be able to call it from the class by doing Example.get_t(blah) without having to have an instance, then you can either use the staticmethod or classmethod decorator. I suggest using classmethod which can do everything that staticmethod can do while the reverse isn't true and it's easier to make classmethod work correctly when you need to override it in a multi inheritance situation. staticmethod has a very tiny performance advantage, but you're microoptimizing if that's your concern.
class example:
#classmethod
def get_t(cls, t):
return t*t
def main(self):
b=1
k=self.get_t(b)
If get_t() is only being called from one method, you can put it as an inner function of that method:
class example:
def main(self):
def get_t(t):
return t * t
b=1
k=self.get_t(b)
With regards to naming, get_xxx is usually a code smell in python. The get_ prefix indicates that the method is likely a getter, and pythonic code usually don't use getters/setters, because the language supports property. What you have on here though, isn't actually a getter but rather a computation method, so it shouldn't be prefixed with get_. A better name might be calculate_t(t) or square(t).
Case 1: If self is there:-
class example:
def get_t(self,t):
return t*t
Then You can not access get_t function directly from class example like example.get_t(t=2) ,it will give you error. But you can access now by creating an object of class like q = example() and then q.get_t(t=2) , it will give you your desired result.
Case 2 : If self is not there:-
class example:
def get_t(t):
return t*t
Now You can directly access get_t function by class example like example.get_t(t=2) ,it will give you your desired result. But now you cannot use get_t function by creating object like q = example() then q.get_t(t=2) it will give you error.
Conclusion :- It all depends on your use case. But when you struck in this type of ambiguity use #staticmethod like given below:-
class example:
#staticmethod
def get_t(t):
return t*t
I hope it may help you.
Let's say I have a class (in python3.6)
class Testing:
def __init__(self, stuff):
self.stuff = stuff
#staticmethod
def method_one(number):
"""My staticmethod"""
return number + 1
def method_two(self):
"""Other method"""
number = 10
# option A
self.method_one(number)
# option B
Testing.method_one(number)
What is more python here?
option A, using the self var
option B, using the class itself
I tend to think A, but I am unsure and couldn't find a solid answer on the topic
In the case of static methods I would always prefer notation B over notation A. The main reason for this is that notation B tells me something about the method that I wouldn't have known if you used notation A.
If you use the class name instead of self it is immediately obvious to the reader that they are dealing with a static method. This way the reader knows that the method doesn't use or change the class or instance state. If you use self you have to check the actual method to see if the class or instance state is used.
In fact using self is not good in static methods. so when you want to call static methods you can use option B , with class object.
So for calling other methods means non static here is the strategy :
If both methods are in same class you can use self like you mentioned in option A.
option B(which means calling a methodinside a class... using class object) , you can use when function that you want to call is in another class
UPDATE :
For calling static methods in the same class you can use two ways,other than self. They are more pythonic.
1. call from class : classname.static_method_name()
2. call from instances
these two ways are more pythonic than self. So in your case option B is more pythonic.
For me Option B has the disadvantage that is explicitly uses the class name Testing again. If the class is renamed (or contents are copy/pasted), this needs to be updated. Using
type(self).method_one(number)
seems a way if one really wants to highlight that this is not an instance method.
Note that this gives you your own class. If your class overwrites a static method of the parent class with and instance method that has the name name, then the call fill fail. Using super().some_static_method() will work, but since super() returns a proxy object type(super()).some_static_method() does not work.
So practically, using self seems ok if all you care about is accessing your (currently set) method. A class instance also "inherits" the class-methods and static methods of parents.
But if you really want to invoke the static method from Testing regardless of what instance you are currently in, then use Testing.method_one(). It's a bit hard to argue about the most "pythonic way" when the whole class/inheritance design can be questioned also...
Sometimes self can denote the instance of the class and sometimes the class itself. So why don't we use inst and klass instead of self? Wouldn't that make things easier?
How things are now
class A:
#classmethod
def do(self): # self refers to class
..
class B:
def do(self): # self refers to instance of class
..
How I think they should be
class A:
#classmethod
def do(klass): # no ambiguity
..
class B:
def do(inst): # no ambiguity
..
So how come we don't program like this when in the zen of Python it is stated that explicit is better than implicit? Is there something that I am missing?
Class method support was added much later to Python, and the convention to use self for instances had already been established. Keeping that convention stable has more value than to switch to a longer name like instance.
The convention for class methods is to use the name cls:
class A:
#classmethod
def do(cls):
In other words, the conventions are already there to distinguish between a class object and the instance; never use self for class methods.
Also see PEP 8 - Function and method arguments:
Always use self for the first argument to instance methods.
Always use cls for the first argument to class methods.
I think it would be better to use "cls":
class A:
#classmethod
def do(cls): # cls refers to class
..
class B:
def do(self): # self refers to instance of class
..
It's requirement of PEP8:
http://legacy.python.org/dev/peps/pep-0008/#function-and-method-arguments
I think the point is that conventially you don't use self for methods wrapped with #classmethod. (You could write kls, cls, etc.)
There is ultimately nothing stopping you from writing inst instead of self if you so desire. So your second example would work fine and is actually the expected way to handle it (in terms of distinguishing an instance vs a class). However, you should definitely use self when dealing with instances. It's a Python convention and breaking it is strongly discouraged.
PEP8
Seeing as others have mentioned it, it's true PEP8 does say to use both self and cls in the case of instance and class methods, respectively. The only thing I'd add to this is that while there isn't any sensible reason to break this rule, changing self is significantly worse (from a semantic POV) because of its strong use inside of 99.999% of Python code. Its use is so universal that many (if not most) beginners assume it's a keyword and are confused by the idea that one can change self to anything.
This strong relationship to code and convention is not so apparent with class methods IMO. Of course I would urge anyone to follow PEP8 as much as possible, but if you felt inclined to use kls instead of cls, I feel that you'd be committing a lesser evil than if you changed self. However, whichever name you go with should remain consistent throughout your program.
I know the question header sounds weird, but since English is not my first language, I find it very hard to formalize. However, I might be able to explain it with bit more text.
The problem is, that I'm trying to create a class called "Foo" for example.
# ../myProject/Foo.py
class Foo:
'''Represents an example class for stackoverflow'''
Now all of Foo class' instances have function attribute, which simply holds a function which can be executed via the instance. Also, there's a parameters attribute, a tuple or a list, which holds parameters which should be used when the function gets called.
def __init__(self, function, parameters):
self.function = function
self.parameters = parameters
def callFunction(self):
if self.function:
self.function(*self.parameters)
This seems to be working fine, however, the problem is, that I want to give it a default value, to change an attribute of the instance. I basically wanna do the following:
def __init__(self, function=setattr, \
parameters=(self, "togglableAttribute", not self.togglableAttribute)):
And doing this will raise NameError: name 'self' is not defined. How should I implement this in order for it to work, or should I come up with a workaround?
self is the typical variable name used to describe the instance. However, default arguments are evaluated when the function is created (at class creation time). Of course self doesn't exist yet because the class doesn't even exist yet -- The class is still in the process of being built.
The typical way to do this is to check for a sentinel;
def __init__(self, function=setattr, parameters=None):
if parameters is None:
parameters = (self, "togglableAttribute", not self.togglableAttribute)
See my answer here (and the comments below it) for a discussion of various objects that you can use as your sentinel and the various pros and cons of each.