What is the right way to use service methods in Django? - python

As an example, let's say I am building an Rest API using Django Rest Framework. Now as part of the application, a few methods are common across all views. My approach is that in the root directory, I have created a services.py file. Inside that module, is a class (CommonUtils) containing all the common utility methods. In that same services.py module I have instantiated an object of CommonUtils.
Now across the application, in the different views.py files I am importing the object from the module and calling the methods on that object. So, essentially I am using a singleton object for the common utility methods.
I feel like this is not a good design approach. So, I want to get an explanation for why this approach is not a good idea and What would the best practice or best approach to achieve the same thing, i.e use a set of common utility methods across all views.py files.
Thanks in advance.

Is this the right design? Why? How to do better?
I feel like this is not a good design approach. So, I want to get an explanation for why this approach is not a good idea and What would the best practice or best approach to achieve the same thing, i.e use a set of common utility methods across all views.py files.
Like #Dmitry Belaventsev wrote above, there is no general rule to solve this problem. This is a typical case of cross-cutting-concerns.
Now across the application, in the different views.py files I am importing the object from the module and calling the methods on that object. So, essentially I am using a singleton object for the common utility methods.
Yes, your implementation is actually a singleton and there is nothing wrong with it. You should ask yourself what do you want to achieve or what do you really need. There are a lot of solutions and you can start with the most basic one:
A simple function in a python module
# file is named utils.py and lives in the root directory
def helper_function_one(param):
return transcendent_all_evil_of(param)
def helper_function_two(prename, lastname):
return 'Hello {} {}'.format(prename, lastname)
In Python it is not uncommon to use just plain functions in a module. You can upgrade it to a method (and a class) if this is really necessary and you need the advantages of classes and objects.
You also can use a class with static methods:
# utils.py
class Utils():
#staticmethod
def helper_one():
print('do something')
But you can see, this is nothing different than the solution with plain functions besides the extra layer of the class. But it has no further value.
You could also write a Singleton Class but in my opinion, this is not very pythonic, because you get the same result with a simple object instance in a module.

Related

Is it a good habit to define a class of function or just put all the funciton in a file?

I'm doing a python project where I got a tons of very different functions. I want to somehow organize them together for the future usage, and, of course, for the easier debugging.
However, is it good habit to arrange lots of functions in a class so that they would be attributes, or just put them all in a file?
A related post could be found here: Differences between `class` and `def` where the author specifically indicated that "class is used to define a class (a template from which you can instantiate objects)", so it seemed like functions, methods to change the objects, might not be used as class.
But the official python documentation stated that "Classes provide a means of bundling data and functionality together." So arranging a bunch of functions in a class seemed to be a suggested habit.
A attempt example was achieved as following
class class1(object):
"""description of class"""
def fun1(x,y):
return x**2+y**2
where
class1.fun1(1,2)
returned the result 5. As shown, the function fun1 was now better organized, and one could easily find where it was and debug it.
However, one could simply import the function fun1 from a file as
def fun1(x,y):
return x**2+y**2
and use it as
fun1(1,2)
which was messier.
Should I arrange all those function in a class as attributes, or just put them all in a file?

Python/Django and services as classes

Are there any conventions on how to implement services in Django? Coming from a Java background, we create services for business logic and we "inject" them wherever we need them.
Not sure if I'm using python/django the wrong way, but I need to connect to a 3rd party API, so I'm using an api_service.py file to do that. The question is, I want to define this service as a class, and in Java, I can inject this class wherever I need it and it acts more or less like a singleton. Is there something like this I can use with Django or should I build the service as a singleton and get the instance somewhere or even have just separate functions and no classes?
TL;DR It's hard to tell without more details but chances are you only need a mere module with a couple plain functions or at most just a couple simple classes.
Longest answer:
Python is not Java. You can of course (technically I mean) use Java-ish designs, but this is usually not the best thing to do.
Your description of the problem to solve is a bit too vague to come with a concrete answer, but we can at least give you a few hints and pointers (no pun intended):
1/ Everything is an object
In python, everything (well, everything you can find on the RHS of an assignment that is) is an object, including modules, classes, functions and methods.
One of the consequences is that you don't need any complex framework for dependency injection - you just pass the desired object (module, class, function, method, whatever) as argument and you're done.
Another consequence is that you don't necessarily need classes for everything - a plain function or module can be just enough.
A typical use case is the strategy pattern, which, in Python, is most often implemented using a mere callback function (or any other callable FWIW).
2/ a python module is a singleton.
As stated above, at runtime a python module is an object (of type module) whose attributes are the names defined at the module's top-level.
Except for some (pathological) corner cases, a python module is only imported once for a given process and is garanteed to be unique. Combined with the fact that python's "global" scope is really only "module-level" global, this make modules proper singletons, so this design pattern is actually already builtin.
3/ a python class is (almost) a singleton
Python classes are objects too (instance of type type, directly or indirectly), and python has classmethods (methods that act on the class itself instead of acting on the current instance) and class-level attributes (attributes that belong to the class object itself, not to it's instances), so if you write a class that only has classmethods and class attributes, you technically have a singleton - and you can use this class either directly or thru instances without any difference since classmethods can be called on instances too.
The main difference here wrt/ "modules as singletons" is that with classes you can use inheritance...
4/ python has callables
Python has the concept of "callable" objects. A "callable" is an object whose class implements the __call__() operator), and each such object can be called as if it was a function.
This means that you can not only use functions as objects but also use objects as functions - IOW, the "functor" pattern is builtin. This makes it very easy to "capture" some context in one part of the code and use this context for computations in another part.
5/ a python class is a factory
Python has no new keyword. Pythonc classes are callables, and instanciation is done by just calling the class.
This means that you can actually use a class or function the same way to get an instance, so the "factory" pattern is also builtin.
6/ python has computed attributes
and beside the most obvious application (replacing a public attribute by a pair of getter/setter without breaking client code), this - combined with other features like callables etc - can prove to be very powerful. As a matter of fact, that's how functions defined in a class become methods
7/ Python is dynamic
Python's objects are (usually) dict-based (there are exceptions but those are few and mostly low-level C-coded classes), which means you can dynamically add / replace (and even remove) attributes and methods (since methods are attributes) on a per-instance or per-class basis.
While this is not a feature you want to use without reasons, it's still a very powerful one as it allows to dynamically customize an object (remember that classes are objects too), allowing for more complex objects and classes creation schemes than what you can do in a static language.
But Python's dynamic nature goes even further - you can use class decorators and/or metaclasses to taylor the creation of a class object (you may want to have a look at Django models source code for a concrete example), or even just dynamically create a new class using it's metaclass and a dict of functions and other class-level attributes.
Here again, this can really make seemingly complex issues a breeze to solve (and avoid a lot of boilerplate code).
Actually, Python exposes and lets you hook into most of it's inners (object model, attribute resolution rules, import mechanism etc), so once you understand the whole design and how everything fits together you really have the hand on most aspects of your code at runtime.
Python is not Java
Now I understand that all of this looks a bit like a vendor's catalog, but the point is highlight how Python differs from Java and why canonical Java solutions - or (at least) canonical Java implementations of those solutions - usually don't port well to the Python world. It's not that they don't work at all, just that Python usually has more straightforward (and much simpler IMHO) ways to implement common (and less common) design patterns.
wrt/ your concrete use case, you will have to post a much more detailed description, but "connecting to a 3rd part API" (I assume a REST api ?) from a Django project is so trivial that it really doesn't warrant much design considerations by itself.
In Python you can write the same as Java program structure. You don't need to be so strongly typed but you can. I'm using types when creating common classes and libraries that are used across multiple scripts.
Here you can read about Python typing
You can do the same here in Python. Define your class in package (folder) called services
Then if you want singleton you can do like that:
class Service(object):
instance = None
def __new__(cls):
if cls.instance is not None:
return cls.instance
else:
inst = cls.instance = super(Service, cls).__new__()
return inst
And now you import it wherever you want in the rest of the code
from services import Service
Service().do_action()
Adding to the answer given by bruno desthuilliers and TreantBG.
There are certain questions that you can ask about the requirements.
For example one question could be, does the api being called change with different type of objects ?
If the api doesn't change, you will probably be okay with keeping it as a method in some file or class.
If it does change, such that you are calling API 1 for some scenario, API 2 for some and so on and so forth, you will likely be better off with moving/abstracting this logic out to some class (from a better code organisation point of view).
PS: Python allows you to be as flexible as you want when it comes to code organisation. It's really upto you to decide on how you want to organise the code.

Why choose module level function over #staticmethod in Python (according to Google Style Guide)?

According to Google Python Style Guide, static methods should (almost) never be used:
Never use #staticmethod unless forced to in order to integrate with an
API defined in an existing library. Write a module level function
instead
What are the reasons behind such recommendation?
Is this particular to Google only or are there any other (more general) downsides with using static methods in Python?
Especially, what is the best practice if I want to implement an utility function inside of a class that will be called by other public member functions of that class?
class Foo:
.......
def member_func(self):
some_utility_function(self.member)
google python style guide
How to understand the Google Python Style Guide that says:
Never use #staticmethod unless forced to in order to integrate with an API defined in an existing library. Write a module level function instead
Well, you should understand it as Google's style guide. If you're writing Python code for Google, or contributing to a project that conforms to that style guide, or have chosen to use it for a project of your own, the answer is pretty simple: Don't use #staticmethod except when forced to by an API.
This means there are no judgment-call cases: A utility function inside of a class is not forced to be a #staticmethod by an API, so it should not be a #staticmethod.
The same is true for some other common1 reasons for #staticmethod. If you want a default value for an instance attribute that's meant to hold a callback function… too bad, find another way to write it (e.g., a local function defined inside __init__). If you want something that looks like a #classmethod but explicitly doesn't covary with subclasses… too bad, it just can't look like a #classmethod.
Of course if you're not following Google's style guide, then you should understand it as just one opinion among many. Plenty of Python developers aren't quite as hard against #staticmethod as that guide is. Of course Google is a pretty prominent developer of lots of Python code. On the other hand, Google's style guide was written while imported Java-isms were more of a problem than today.2 But you probably don't want to think too much about how much weight to give each opinion; instead, when it's important, learn the issues and come up with your own opinion.
As for your specific example, as I said in a comment: the fact that you naturally find yourself writing some_utility_function(self.member) instead of self.some_utility_function(self.member) or Foo.some_utility_function(self.member) means that intuitively, you're already thinking of it as a function, not a #staticmethod. In which case you should definitely write that one as a function, not a #staticmethod.
That may be just the opinion of one guy on the internet, but I think most Python developers would agree in this case. It's the times when you do naturally find yourself prefixing self. before every call when there's a judgment call to make.
1. Well, not exactly common. But they aren't so rare that they never come up. And they were common enough that, when there was discussion about deprecating #staticmethod for Python 3, someone quickly came up with these two cases, with examples from the standard library, and that was enough for Guido to kill the discussion.
2. In Java, there are no module-level functions, and you're forced to write static methods to simulate them. And there were a few years where most university CS programs were focused on Java, and a ton of software was written by Java, so tons of people were writing Python classes with way too many #staticmethods (and getters and setters, and other Java-isms).
The way you've written the call to some_utility_function(), it isn't defined on the class anyway. If it were, you would be using self.some_utility_function() or possibly Foo.some_utility_function() to call it. So you've already done it the way the style guide recommends.
The #classmethod and #staticmethod decorators are used primarily to tell Python what to pass as the first argument to the method in place of the usual self: either the type, or nothing at all. But if you're using #staticmethod, and need neither the instance nor its type, should it really be a member of the class at all? That's what they're asking you to consider here: should utility functions be methods of a class, when they are not actually tied to that class in any way? Google says no.
But this is just Google's style guide. They have decided that they want their programmers to prefer module-level functions. Their word is not law. Obviously the designers of Python saw a use for #staticmethod or they wouldn't have implemented it! If you can make a case for having a utility function attached to a class, feel free to use it.
My 2¢
The point is that when you want to do duck-typing polymorphic things, defining module level functions is overkilled, especially if your definitions are very short. E.g. defining
class StaticClassA:
#staticmethod
def maker(i: int) -> int:
return 2*i
class StaticClassB:
#staticmethod
def maker(i: int) -> float:
return pow(i, 2)
#[...] say, 23 other classes definitions
class StaticClassZ:
#staticmethod
def maker(i: int) -> float:
return 2*pow(i, 2)
Is clearly smarter than having 26 (from A to Z) classes defined within 26 modules.
A practical example of what I imply with the word "polymorphism" ? With the above classes definitions, you can do
for class_ in [StaticClassA, StaticClassB, StaticClassZ]:
print(class_.maker(6))

Static classes in Python

I once read (I think on a page from Microsoft) that it's a good way to use static classes, when you don't NEED two or more instances of a class.
I'm writing a program in Python. Is it a bad style, if I use #classmethod for every method of a class?
Generally, usage like this is better done by just using functions in a module, without a class at all.
It's terrible style, unless you actually need to access the class.
A static method [...] does not translate to a Python classmethod. Oh sure, it results in more or less the same effect, but the goal of a classmethod is actually to do something that's usually not even possible [...] (like inheriting a non-default constructor). The idiomatic translation of a [...] static method is usually a module-level function, not a classmethod or staticmethod.
source
In my experience creating a class is a very good solution for a number of reasons. One is that you wind up using the class as a 'normal' class (esp. making more than just one instance) more often than you might think. It's also a reasonable style choice to stick with classes for everthing; this can make it easier for others who read/maintain your code, esp if they are very OO - they will be comfortable with classes. As noted in other replies, it's also reasonable to just use 'bare' functions for the implementation. You may wish to start with a class and make it a singleton/Borg pattern (lots of examples if you googlefor these); it gives you the flexibility to (re)use the class to meet other needs. I would recommend against the 'static class' approach as being non-conventional and non-Pythonic, which makes it harder to read and maintain.
There are a few approaches you might take for this. As others have mentioned, you could just use module-level functions. In this case, the module itself is the namespace that holds them together. Another option, which can be useful if you need to keep track of state, is to define a class with normal methods (taking self), and then define a single global instance of it, and copy its instance methods to the module namespace. This is the approach taken by the standard library "random" module -- take a look at lib/python2.5/random.py in your python directory. At the bottom, it has something like this:
# Create one instance, seeded from current time, and export its methods
# as module-level functions. [...]
_inst = Random()
seed = _inst.seed
random = _inst.random
uniform = _inst.uniform
...
Or you can take the basic approach you described (though I would recommend using #staticmethod rather than #classmethod in most cases).
You might actually want a singleton class rather than a static class:
Making a singleton class in python

Python: add a parent class to a class after initial evaluation

General Python Question
I'm importing a Python library (call it animals.py) with the following class structure:
class Animal(object): pass
class Rat(Animal): pass
class Bat(Animal): pass
class Cat(Animal): pass
...
I want to add a parent class (Pet) to each of the species classes (Rat, Bat, Cat, ...); however, I cannot change the actual source of the library I'm importing, so it has to be a run time change.
The following seems to work:
import animals
class Pet(object): pass
for klass in (animals.Rat, animals.Bat, animals.Cat, ...):
klass.__bases__ = (Pet,) + klass.__bases__
Is this the best way to inject a parent class into an inheritance tree in Python without making modification to the source definition of the class to be modified?
Motivating Circumstances
I'm trying to graft persistence onto the a large library that controls lab equipment. Messing with it is out of the question. I want to give ZODB's Persistent a try. I don't want to write the mixin/facade wrapper library because I'm dealing with 100+ classes and lots of imports in my application code that would need to be updated. I'm testing options by hacking on my entry point only: setting up the DB, patching as shown above (but pulling the species classes w/ introspection on the animals module instead of explicit listing) then closing out the DB as I exit.
Mea Culpa / Request
This is an intentionally general question. I'm interested in different approaches to injecting a parent and comments on the pros and cons of those approaches. I agree that this sort of runtime chicanery would make for really confusing code. If I settle on ZODB I'll do something explicit. For now, as a regular user of python, I'm curious about the general case.
Your method is pretty much how to do it dynamically. The real question is: What does this new parent class add? If you are trying to insert your own methods in a method chain that exists in the classes already there, and they were not written properly, you won't be able to; if you are adding original methods (e.g. an interface layer), then you could possibly just use functions instead.
I am one who embraces Python's dynamic nature, and would have no problem using the code you have presented. Make sure you have good unit tests in place (dynamic or not ;), and that modifying the inheritance tree actually lets you do what you need, and enjoy Python!
You should try really hard not to do this. It is strange, and will likely end in tears.
As #agf mentions, you can use Pet as a mixin. If you tell us more about why you want to insert a parent class, we can help you find a nicer solution.

Categories

Resources