What is static method and how can we explain the below code ?
#staticmethod
def get_model(**kwargs):
try:
return Model.objects.get(**kwargs)
except Model.DoesNotExist:
return
In short and maybe oversimplified: staticmethod doesn't require object of a class to run. This also means that you don't need self argument.
About the code:
This method is attempting to return single (.get()) instance of a Model that match with parameters specified in kwargs.
example:
kwargs = {"id":5, "is_alive": True}
Model.objects.get(**kwargs)
#is the same as
Model.objects.get(id=5, is_alive=True)
This can raise Model.DoesNotExists error if there is no instances of Model matching with paramaters so try/except is used.
If Model.DoesNotExists error is raised then method return None.
A staticmethod is a function not bound to an object, but is encapsulated within it ( typically to reduce outer namespace clutter, or eliminate any need to import it). It doesn't have the first self argument that a normal object method does.
Related
I am working with google classroom api and one of the params of a function takes a callback.
def callback(request_id, response, exception):
if exception is not None:
print 'Error adding user "{0}" to the course course: {1}'.format(
request_id, exception)
else:
print 'User "{0}" added as a student to the course.'.format(
response.get('profile').get('name').get('fullName'))
In my case the method is inside a class and as I know every python method should take a self object but in this case this function will have specific params and I am not sure how to pass the self object or should I ignore self? the issue is I plan to use self inside of the function.
Any ideas?
I think that I understand your dilema. Go ahead and include self as the first argument, since it will be passed implicitly by Python every time callback() gets called. All the other positional arguments (request_id, response and exception) will not be affected by the inclusion of self in the definition of the method's argument. i.e:
def callback(self, request_id, response, exception):
# ...
If you weren't going to use the self object inside the callback method (now a function), then you could use the #staticmethod decorator upon the function's definition, but if I'm following you straight, that's not the case here.
Edit: If you need to pass a specific parameter without compromising the nature of the callback, you can use partial, from the functools module. I would do something as follows (In this example I'm using the parameter request_id, but it could be any other(s)):
from functools import partial
partial_callback = partial(callback, request_id='12345')
Now you can pass partial_callback instead of callback wherever you need that specific argument (request_id in my example) to be passed.
Please note: If you want to pass a parameter that was not defined in the original callback function, that will raise a TypeError. If that was the case, then redefine callback, using the special syntax **kwargs, so that callback now accept a keyworded, variable-length arguments, which will be stored as key-value pairs in a dictionary called kwargs.
Just note that in order to use the arguments inside the function definition, you must refer to them as kwargs['whatever_argument_name'] (as you would do with any dictionary)
So, for example, if you want to pass an argument called extraparam, then you would need to have something as follows:
def callback(self, request_id, response, exception, **kwargs):
# ...
extraparam = kwargs.get('extraparam')
if extraparam is not None:
# ...
partial_callback = partial(callback, extraparam='whatever')
I have encountered an interesting scenario, while creating decorator in python. Following is my code :-
class RelationShipSearchMgr(object):
#staticmethod
def user_arg_required(obj_func):
def _inner_func(**kwargs):
if "obj_user" not in kwargs:
raise Exception("required argument obj_user missing")
return obj_func(*tupargs, **kwargs)
return _inner_func
#staticmethod
#user_arg_required
def find_father(**search_params):
return RelationShipSearchMgr.search(Relation.RELATION_FATHER, **search_params)
As shown in above code, I have created a decorator(which is static method in class), which checks, if "obj_user" is passed as argument to decorated function. I have decorated function find_father, but I am getting following error message :- 'staticmethod' object is not callable.
How to use static utility method as shown above, as decorator in python ?
Thanks in advance.
staticmethod is a descriptor. #staticmethod return a descriptor object instead of a function. That why it raises staticmethod' object is not callable.
My answer is simply avoid doing this. I don't think it's necessary to make user_arg_required a static method.
After some play around, I found there is hack if you still want to use static method as decorator.
#staticmethod
#user_arg_required.__get__(0)
def find_father(**search_params):
return RelationShipSearchMgr.search(Relation.RELATION_FATHER, **search_params)
This doc will tell you what is descriptor.
https://docs.python.org/2/howto/descriptor.html
After digging a bit, I found that, staticmethod object has __func__ internal variable __func__, which stores the raw function to be executed.
So, following solution worked for me :-
#staticmethod
#user_arg_required.__func__
def find_father(**search_params):
return RelationShipSearchMgr.search(Relation.RELATION_FATHER, **search_params)
I wanted to write a class function which takes Signal object as a parameter and returns its copy. Then I wanted to overload this function with an instance function that returns copy of self argument. I have a following code:
#classmethod
def copy(cls, arg):
if not isinstance(arg, Signal):
raise ValueError("Argument must be of type Signal")
result = Signal()
result.framerate = arg.framerate
return result
def copy(self):
return FragmentsSignal.copy(self)
and
Signal1 = Signal(100)
Signal2 = signal1.copy()
But after calling the function copy my code goes into infinite recursive loop and throws name of this site as an exception. My questions are:
Do I properly use python function overloading mechanism?
How can I pass *this argument to a class function within my class?
Do I properly use python function overloading mechanism?
You can't have two functions with the same name; Python does not support overloading based on the types of the arguments. The definition of the second function will override that of the first.
In essence you're calling the non classmethod function copy over and over again. You'll need to rename one of these in order to get it to work effectively.
How can I pass *this argument to a class function within my class?
I'm guessing you mean self here; passing self to another function is done as with any other arg (as you did FragmentsSignal.copy(self)). Your issue is that you're getting stumped by the recursion caused by the similar names.
I am trying to figure out how the property decorator works in Python.
So,
class Foo:
def method(self,param):
self._method(param)
#property
def _method(self): # works fine.. why... I havent defined this to accept any argument
#some logic
#even though it passes.. how do i retrieve "param" parameter passed above?
vs.:
class Foo:
def method(self,param):
self._method(param)
# no property decorator here (throws error)
def _method(self):
#some logic
If the decorator property is removed, Python throws an error, which is fine, as I am passing an argument which is not accepted in the method. I understand that, but why doesn't _method(self) need any more params with property defined?
And how do I retrieve the param value inside method using decorator approach?
You're misinterpreting what self._method(param) actually does when _method is a property. Since you are dealing with a property, the value currently stored in the property is retrieved.
tmp = self._method
And then that value is called as a function.
tmp(param)
Therefore there is no way to retrieve the value of param in the getter for _method since the interpreter hasn't even gotten to the point where param even matters.
I have a model class with getter and setter methods, and the occasional static methods. I would like to enforce the usage of unicode strings as arguments for specific methods and using decorators was the first idea I had. Now I have something like this:
import types
class require_unicode(object):
def __init__(self, function):
self.f = function
def __call__(self, string):
if not isinstance(string, types.UnicodeType):
raise ValueError('String is not unicode')
return self.f(string)
class Foo(object):
something = 'bar'
#staticmethod
#require_unicode
def do_another(self, string):
return ' '.join(['baz', string])
#require_unicode
def set_something(self, string):
self.something = string
foo = Foo()
foo.set_something('ValueError is raised')
foo.set_something(u'argument count error')
foo.do_another('ValueError is raised')
foo.do_another(u'argument count error')
In the above code the method call inside decorator's __call__ fails due to wrong argument count (because the 'foo' object ref is missing?). Before doing something stupid I wanted to ask you guys. How this should be done?
I think, your problem is with the #staticmethod decorator, not with your require_unicode decorator. Staticmethods, unlike classmethods don't receive the reference to the class as the first argument, so your argument signature is wrong.
You must either change do_another to be a #classmethod, or remove self from the arguments.
EDIT: and, mind you, - #classmethod-decorated methods receive the class as the first argument, while instance methods receive the reference to the instance of the class (self). So it is a good idea to name the first argument to a classmethod "cls" or something, not "self" so it doesn't confuse anyone.
I would think that this was unpythonic - you should never check the type of your arguments, but instead check that they have the necessary methods and attributes. The simplest way to do this is by assuming they are there and getting an exception otherwise, but I guess you could do getattr too. Just don't check the type of things.
Another option is to use assertions. It depends on whether passing a non-unicode type into your methods should be considered a programming error that should be evident during development.
import types
class Foo:
def set_something(self, string):
assert isinstance(string, types.UnicodeType), 'String is not unicode'
self.something = string
This will raise an AssertionError exception whenever string is not of type unicode, but only when the Python interpretter is run in "deubg" mode. If you run Python with the -O option, the assert is efficiently ignored by the interpretter.