Is it okay to abuse #classmethod and #staticmethod In python?(Django) - python

I have used spring framework for developing server application, and now I start to learn Django.
I got one question when I use Django.
"Is there no issue about memory when using #classmethod or #staticmethod? in python"
In spring(java), there is issue about abusing static and spring also support controlling object(IoC container).
But when I use Django, there is no decorator or setting about object.
Just I use #classmethod, and use it with class name (ex. AccountService.join() )

#statictmethod can be used if you need a method which you can call with ModelName.method_name() and which don't operate on the object.
You don't really use classmethod in your Models. These operations are done via a Manager class. See this accepted answer on classmethod Django model class methods for predefined values

In "normal use", this is fine. Class methods do not get access to instance data, and static methods don't get access to the parent class. If these are not issues for you, then you can use #classmethod or #staticmethod respectively. In reality though, semantic/readability benefits aside, this is likely premature optimisation, especially in a web application context where the lion's share of latency/resources go to other things.

Related

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))

Advantages of using static methods over instance methods in python

My IDE keeps suggesting I convert my instance methods to static methods. I guess because I haven't referenced any self within these methods.
An example is :
class NotificationViewSet(NSViewSet):
def pre_create_processing(self, request, obj):
log.debug(" creating messages ")
# Ensure data is consistent and belongs to the sending bot.
obj['user_id'] = request.auth.owner.id
obj['bot_id'] = request.auth.id
So my question would be: do I lose anything by just ignoring the IDE suggestions, or is there more to it?
This is a matter of workflow, intentions with your design, and also a somewhat subjective decision.
First of all, you are right, your IDE suggests converting the method to a static method because the method does not use the instance. It is most likely a good idea to follow this suggestion, but you might have a few reasons to ignore it.
Possible reasons to ignore it:
The code is soon to be changed to use the instance (on the other hand, the idea of soon is subjective, so be careful)
The code is legacy and not entirely understood/known
The interface is used in a polymorphic/duck typed way (e.g. you have a collection of objects with this method and you want to call them in a uniform way, but the implementation in this class happens to not need to use the instance - which is a bit of a code smell)
The interface is specified externally and cannot be changed (this is analog to the previous reason)
The AST of the code is read/manipulated either by itself or something that uses it and expects this method to be an instance method (this again is an external dependency on the interface)
I'm sure there can be more, but failing these types of reasons I would follow the suggestion. However, if the method does not belong to the class (e.g. factory method or something similar), I would refactor it to not be part of the class.
I think that you might be mixing up some terminology - the example is not a class method. Class methods receive the class as the first argument, they do not receive the instance. In this case you have a normal instance method that is not using its instance.
If the method does not belong in the class, you can move it out of the class and make it a standard function. Otherwise, if it should be bundled as part of the class, e.g. it's a factory function, then you should probably make it a static method as this (at a minimum) serves as useful documentation to users of your class that the method is coupled to the class, but not dependent on it's state.
Making the method static also has the advantage this it can be overridden in subclasses of the class. If the method was moved outside of the class as a regular function then subclassing is not possible.

Using Django Managers vs. staticmethod on Model class directly

After reading up on Django Managers, I'm still unsure how much benefit I will get by using it. It seems that the best use is to add custom queries (read-only) methods like XYZ.objects.findBy*(). But I can easily do that with static methods off of the Model classes themselves.
I prefer the latter always because:
code locality in terms of readability and easier maintenance
slightly less verbose as I don't need the objects property in my calls
Manager classes have weird rules regarding model inheritance, might as well stay clear of that.
Is there any good reason not to use static methods and instead use Manager classes?
Adding custom queries to managers is the Django convention. From the Django docs on custom managers:
Adding extra Manager methods is the preferred way to add "table-level" functionality to your models.
If it's your own private app, the convention word doesn't matter so much - indeed my company's internal codebase has a few classmethods that perhaps belong in a custom manager.
However, if you're writing an app that you're going to share with other Django users, then they'll expect to see findBy on a custom manager.
I don't think the inheritance issues you mention are too bad. If you read the custom managers and model inheritance docs, I don't think you'll get caught out. The verbosity of writing .objects is bearable, just as it is when we do queries using XYZ.objects.get() and XYZ.objects.all()
Here's a few advantages of using manager methods in my opinion:
Consistency of API. Your method findBy belongs with get, filter, aggregate and the rest. Want to know what lookups you can do on the XYZ.objects manager? It's simple when you can introspect with dir(XYZ.objects).
Static methods "clutter" the instance namespace. XYZ.findBy() is fine but if you define a static method, you can also do xyz.findBy(). Running the findBy lookup on a particular instance doesn't really make sense.
DRYness. Sometimes you can use the same manager on more than one model.
Having said all that, it's up to you. I'm not aware of a killer reason why you should not use a static method. You're an adult, it's your code, and if you don't want to write findBy as a manager method, the sky isn't going to fall in ;)
For further reading, I recommend the blog post Managers versus class methods by James Bennett, the Django release manager.

"Interfaces" in Python: Yea or Nay? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 5 years ago.
Improve this question
So I'm starting a project using Python after spending a significant amount of time in static land. I've seen some projects that make "interfaces" which are really just classes without any implementations. Before, I'd scoff at the idea and ignore that section of those projects. But now, I'm beginning to warm up to the idea.
Just so we're clear, an interface in Python would look something like this:
class ISomething(object):
def some_method():
pass
def some_other_method(some_argument):
pass
Notice that you aren't passing self to any of the methods, thus requiring that the method be overriden to be called. I see this as a nice form of documentation and completeness testing.
So what is everyone here's opinion on the idea? Have I been brainwashed by all the C# programming I've done, or is this a good idea?
I'm not sure what the point of that is. Interfaces (of this form, anyway) are largely to work around the lack of multiple inheritance. But Python has MI, so why not just make an abstract class?
class Something(object):
def some_method(self):
raise NotImplementedError()
def some_other_method(self, some_argument):
raise NotImplementedError()
In Python 2.6 and later, you can use abstract base classes instead. These are useful, because you can then test to see if something implements a given ABC by using "isinstance". As usual in Python, the concept is not as strictly enforced as it would be in a strict language, but it's handy. Moreover there are nice idiomatic ways of declaring abstract methods with decorators - see the link above for examples.
There are some cases where interfaces can be very handy. Twisted makes fairly extensive use of Zope interfaces, and in a project I was working on Zope interfaces worked really well. Enthought's traits packaged recently added interfaces, but I don't have any experience with them.
Beware overuse though -- duck typing and protocols are a fundamental aspect of Python, only use interfaces if they're absolutely necessary.
The pythonic way is to "Ask for forgiveness rather than receive permission". Interfaces are all about receiving permission to perform some operation on an object. Python prefers this:
def quacker(duck):
try:
duck.quack():
except AttributeError:
raise ThisAintADuckException
I don't think interfaces would add anything to the code environment.
Method definition enforcing happens without them. If an object expected to be have like Foo and have method bar(), and it does't, it will throw an AttributeError.
Simply making sure an interface method gets defined doesn't guarantee its correctness; behavioral unit tests need to be in place anyway.
It's just as effective to write a "read this or die" page describing what methods your object needs to have to be compatible with what you're plugging it in as having elaborate docstrings in an interface class, since you're probably going to have tests for it anyway. One of those tests can be standard for all compatible objects that will check the invocation and return type of each base method.
Seems kind of unnecessary to me - when I'm writing classes like that I usually just make the base class (your ISomething) with no methods, and mention in the actual documentation which methods subclasses are supposed to override.
You can create an interface in a dynamically typed language, but there's no enforcement of the interface at compile time. A statically typed language's compiler will warn you if you forget to implement (or mistype!) a method of an interface. Since you receive no such help in a dynamically typed language, your interface declaration serves only as documentation. (Which isn't necessarily bad, it's just that your interface declaration provides no runtime advantage versus writing comments.)
I'm about to do something similar with my Python project, the only things I would add are:
Extra long, in-depth doc strings for each interface and all the abstract methods.
I would add in all the required arguments so there's a definitive list.
Raise an exception instead of 'pass'.
Prefix all methods so they are obviously part of the interface - interface Foo: def foo_method1()
I personally use interfaces a lot in conjunction with the Zope Component Architecture (ZCA). The advantage is not so much to have interfaces but to be able to use them with adapters and utilities (singletons).
E.g. you could create an adapter which can take a class which implements ISomething but adapts it to the some interface ISomethingElse. Basically it's a wrapper.
The original class would be:
class MyClass(object):
implements(ISomething)
def do_something(self):
return "foo"
Then imagine interface ISomethingElse has a method do_something_else(). An adapter could look like this:
class SomethingElseAdapter(object):
implements(ISomethingElse)
adapts(ISomething)
def __init__(self, context):
self.context = context
def do_something_else():
return self.context.do_something()+"bar"
You then would register that adapter with the component registry and you could then use it like this:
>>> obj = MyClass()
>>> print obj.do_something()
"foo"
>>> adapter = ISomethingElse(obj)
>>> print adapter.do_something_else()
"foobar"
What that gives you is the ability to extend the original class with functionality which the class does not provide directly. You can do that without changing that class (it might be in a different product/library) and you could simply exchange that adapter by a different implementation without changing the code which uses it. It's all done by registration of components in initialization time.
This of course is mainly useful for frameworks/libraries.
I think it takes some time to get used to it but I really don't want to live without it anymore. But as said before it's also true that you need to think exactly where it makes sense and where it doesn't. Of course interfaces on it's own can also already be useful as documentation of the API. It's also useful for unit tests where you can test if your class actually implements that interface. And last but not least I like starting by writing the interface and some doctests to get the idea of what I am actually about to code.
For more information you can check out my little introduction to it and there is a quite extensive description of it's API.
Glyph Lefkowitz (of Twisted fame) just recently wrote an article on this topic. Personally I do not feel the need for interfaces, but YMMV.
Have you looked at PyProtocols? it has a nice interface implementation that you should look at.

Categories

Resources