Related
I am new to OOP and am writing a small tool in Python that checks Bitcoin prices using a JSON load from the web Bitcoin() class, it monitors the prices Monitor(), notifies the user when thresholds are met Notify() and uses a console-interface Interface() for now to do so.
I have created a Bitcoin() class that can read the prices and volumes from the JSON load. The __init__ definition connects to the web using socket. Since every instance of this class would result in a new socket, I would only need/want one instance of this class running.
Is a class still the best way to approach this?
What is the best way to get other classes and instances to interact with my Bitcoin() instance?
Should I global a Bitcoin() instance? Pass the instance as an argument to every class that needs it?
The first thing which concerns me is the SRP violation, your Bitcoin class probably shouldn't be responsible for:
opening socket,
parsing results,
rendering output.
I don't know the details but from my point of view you should split that functionality to smaller classes/functions (in case of using only modules), and one of them will be responsible for retrieving data from web. Please also keep in mind that global state is evil (singletons in some contexts could be described as global state).
Another thing which is a smell from my point of view is opening a socket inside the constructor. This isn't testable, of course you could mock/stub socket, but from my point of view it's better when class requires all it's dependencies as a constructor parameter. By doing it that way you could also notice some classes with to wide responsibility (if your constructor requires more that 3,4 parameters it definitely could be simplified).
http://www.youtube.com/watch?v=o9pEzgHorH0
I'm not sure how relevant this video is for your project (no code to actually read). But maybe you'll pick up the answer to your question. At least you'll learn something new and that's what were here for.
If I were you my code would be something like:
( a class for every set of jobs, which is not what you are doing )
class Interface:
''' Handle UI '''
...
class Connect:
''' Handle web interface '''
...
class Bitcoin:
''' Handle the calculations '''
...
class Notify:
''' Notifier '''
...
In short, split your classes into smaller simpler classes.
Now for your question:
Yes, because you have a "complex-ish" problem at hand and you're using Python, so it's definitely easier to create a OOP version than a non-OOP one. So, unless you have a good reason not to, Stick to OOP.
In your case, it might as well be passing the instance as an argument.
This is a good idea. This eliminates the problems caused by scopes if you don't have a very good understanding of them.
But remember you pass the reference, not the value, so manipulating the instance, can and will affect other classes the instance is passed to.
Note: Opening a socket in the constructor of the class is not a good idea. It might be better if you have it in a method.
The answer is maybe. Depends upon you whole architecture,
You should look at the singleton pattern, because you description yells Singleton all over.
http://de.wikipedia.org/wiki/Singleton_%28Entwurfsmuster%29
If you don't find any good reason against creating a class in your given architecture, then just go for it.
OOP is a tool, not a goal, you can make a decision whether to use it or not. If you use a Python module, you can achieve encapsulation without ever writing "class".
Sure, you can use python classes for this purpose. You can use module-level instances as well(no global keyword or explicit passing as arguments needed). It is a matter of taste IMHO.
Basically you're asking about Singleton pattern python-specific implementation, it has been answered here:
Python and the Singleton Pattern
Description of pattern itself can be found here: http://en.wikipedia.org/wiki/Singleton_pattern
I have been programming mainly in PHP, and I am trying to make a switch to python. I am skilled with PHP, and I have never needed to use introspection / introspection like capabilities. What good is code introspection, and in what situations would I find it indispensable?
Here is the only way I find it useful:
From the examples I saw in 'Dive into Python', introspection basically means that you can list all of the functions and attributes of an object. To me it seems that introspection is just there as a "user's manual" to an object. It lets you look at the object and its functionality from the python shell.
I just do not see why or in what situation you would take an arbitrary object, introspect upon it, and do something useful.
Suppose you are given a custom object and you want to know if the object has certain attributes or has as a certain method, then the introspection function such as hasattr can be used to find that out.
Also like the DiveintoPython book already illustrates, suppose you are building a GUI Editor with Auto-Completion feature, you want to get the public methods of the object which are callable at the run-time, then you can use the introspection methods like getattr for each for the methods got via dir and check if it is callable and then display it in your auto-completion list.
One example where I have used introspection on a real project:
We had a service that was managing background tasks called TaskService. Each task was actually implemented as a class that was implementing the Start() Stop() methods of a given interface. We had a config file, in which we were matching each task with its class. So when running TaskService, it just browsed the config file, and for each task it took the name of the class and instanciated it (during runtime) through reflection (introspection is a subpart of reflection).
Another example of where introspection can be useful is in the use of annotations in your programming language. Annotations are used to give metainformation about your classes to other third party programs (like ORMs), for instance you can use annotations to tell whether a class is an entity class (it is the case in Java, I don't know about Python sorry), or about the type of association of certain attributs etc.
Code Completion is another example of the usefulness of introspection.
And by the way, as you mentionned, introspection helps a lot to program documentation tools.
I wrote a documentation validator that runs tests on PDF files to check for various problems with them. The tests are methods of special classes that represent Subversion branches, products, manuals, and arbitrary groupings of various types. The validator engine uses introspection to find these special classes, instantiate them, and run their methods.
I could have written the validator so that you have to write boilerplate code to instantiate each class, call each method, etc. But that is repeating yourself and it is prone to maintenance problems (failure to update both places when adding/removing tests, in this case). By taking advantage of the fact that you want to apply the same operation to all the special classes, the computer can essentially do the boilerplate stuff for you, and it won't make mistakes. That way, you have to declare the structure of the documentation in only one place.
A little bit late on this, but another example of introspection in use is with Active Record (a Ruby library that maps objects to database tables). Active Record uses introspection to look at the name of the class, determine the associated table, and defines methods that access object attributes after inferring their names from the database schema. It reads the schema at runtime (metaprogramming & introspection in play here). So for example, if you have a class Person, you don't have to write accessor methods e.g nameoremail. As long as columns by the same name (in this case nameandemail) exist in the associated table (in this case people`), Active Record defines accessor methods for these attributes of the same name at runtime.
My first "serious" language was Java, so I have comprehended object-oriented programming in sense that elemental brick of program is a class.
Now I write on VBA and Python. There are module languages and I am feeling persistent discomfort: I don't know how should I decompose program in a modules/classes.
I understand that one module corresponds to one knowledge domain, one module should ba able to test separately...
Should I apprehend module as namespace(c++) only?
I don't do VBA but in python, modules are fundamental. As you say, the can be viewed as namespaces but they are also objects in their own right. They are not classes however, so you cannot inherit from them (at least not directly).
I find that it's a good rule to keep a module concerned with one domain area. The rule that I use for deciding if something is a module level function or a class method is to ask myself if it could meaningfully be used on any objects that satisfy the 'interface' that it's arguments take. If so, then I free it from a class hierarchy and make it a module level function. If its usefulness truly is restricted to a particular class hierarchy, then I make it a method.
If you need it work on all instances of a class hierarchy and you make it a module level function, just remember that all the the subclasses still need to implement the given interface with the given semantics. This is one of the tradeoffs of stepping away from methods: you can no longer make a slight modification and call super. On the other hand, if subclasses are likely to redefine the interface and its semantics, then maybe that particular class hierarchy isn't a very good abstraction and should be rethought.
It is matter of taste. If you use modules your 'program' will be more procedural oriented. If you choose classes it will be more or less object oriented. I'm working with Excel for couple of months and personally I choose classes whenever I can because it is more comfortable to me. If you stop thinking about objects and think of them as Components you can use them with elegance. The main reason why I prefer classes is that you can have it more that one. You can't have two instances of module. It allows me use encapsulation and better code reuse.
For example let's assume that you like to have some kind of logger, to log actions that were done by your program during execution. You can write a module for that. It can have for example a global variable indicating on which particular sheet logging will be done. But consider the following hypothetical situation: your client wants you to include some fancy report generation functionality in your program. You are smart so you figure out that you can use your logging code to prepare them. But you can't do log and report simultaneously by one module. And you can with two instances of logging Component without any changes in their code.
Idioms of languages are different and thats the reason a problem solved in different languages take different approaches.
"C" is all about procedural decomposition.
Main idiom in Java is about "class or Object" decomposition. Functions are not absent, but they become a part of exhibited behavior of these classes.
"Python" provides support for both Class based problem decomposition as well as procedural based.
All of these uses files, packages or modules as concept for organizing large code pieces together. There is nothing that restricts you to have one module for one knowledge domain.
These are decomposition and organizing techniques and can be applied based on the problem at hand.
If you are comfortable with OO, you should be able to use it very well in Python.
VBA also allows the use of classes. Unfortunately, those classes don't support all the features of a full-fleged object oriented language. Especially inheritance is not supported.
But you can work with interfaces, at least up to a certain degree.
I only used modules like "one module = one singleton". My modules contain "static" or even stateless methods. So in my opinion a VBa module is not namespace. More often a bunch of classes and modules would form a "namespace". I often create a new project (DLL, DVB or something similar) for such a "namespace".
I have started using Zope interfaces in my code, and as of now, they are really only documentation. I use them to specify what attributes the class should possess, explicitly implement them in the appropriate classes and explicitly check for them where I expect one. This is fine, but I would like them to do more if possible, such as actually verify that the class has implemented the interface, instead of just verifying that I have said that the class implements the interface. I have read the zope wiki a couple of times, but still cannot see much more use for interfaces than what I am currently doing. So, my question is what else can you use these interfaces for, and how do you use them for more.
Where I work, we use Interfaces so that we can use ZCA, or the Zope Component Architecture, which is a whole framework for making components that are swappable and pluggable using Interfaces. We use ZCA so that we can cope with all manner of per-client customisations without necessarily having to fork our software or have all of the many per-client bits messing up the main tree. The Zope wiki is often quite incomplete, unfortunately. There's a good-but-terse explanation of most of ZCA's features on its ZCA's pypi page.
I don't use Interfaces for anything like checking that a class implements all the methods for a given Interface. In theory, that might be useful when you add another method to an interface, to check that you've remembered to add the new method to all of the classes that implement the interface. Personally I strongly prefer to create a new Interface over modifying an old one. Modifying old Interfaces is usually a very bad idea once they're in eggs that have been released to pypi or to the rest of your organisation.
A quick note on terminology: classes implement Interfaces, and objects (instances of classes) provide Interfaces. If you want to check for an Interface, you would either write ISomething.implementedBy(SomeClass) or ISomething.providedBy(some_object).
So, down to examples of where ZCA is useful. Let's pretend that we're writing a blog, using the ZCA to make it modular. We'll have a BlogPost object for each post, which will provide an IBlogPost interface, all defined in our handy-dandy my.blog egg. We'll also store the blog's configuration in BlogConfiguration objects which provide IBlogConfiguration. Using this as a starting point, we can implement new features without necessarily having to touch my.blog at all.
The following is a list of examples of things that we can do by using ZCA, without having to alter the base my.blog egg. I or my co-workers have done all of these things (and found them useful) on real for-client projects, though we weren't implementing blogs at the time. :) Some of the use cases here could be better solved by other means, such as a print CSS file.
Adding extra views (BrowserViews, usually registered in ZCML with the browser:page directive) to all objects which provide IBlogPost. I could make a my.blog.printable egg. That egg would register a BrowserView called print for IBlogPost, which renders the blog post through a Zope Page Template designed to produce HTML that prints nicely. That BrowserView would then appear at the URL /path/to/blogpost/##print.
The event subscription mechanism in Zope. Say I want to publish RSS feeds, and I want to generate them in advance rather than on request. I could create a my.blog.rss egg. In that egg, I'd register a subscriber for events that provide IObjectModified (zope.lifecycleevent.interfaces.IObjectModified), on objects that provide IBlogPost. That subscriber would get get called every time an attribute changed on anything providing IBlogPost, and I could use it to update all the RSS feeds that the blog post should appear in.
In this case, it might be better to have an IBlogPostModified event that is sent at the end of each of the BrowserViews that modify blog posts, since IObjectModified gets sent once on every single attribute change - which might be too often for performance's sake.
Adapters. Adapters are effectively "casts" from one Interface to another. For programming language geeks: Zope adapters implement "open" multiple-dispatch in Python (by "open" I mean "you can add more cases from any egg"), with more-specific interface matches taking priority over less-specific matches (Interface classes can be subclasses of one another, and this does exactly what you'd hope it would do.)
Adapters from one Interface can be called with a very nice syntax, ISomething(object_to_adapt), or can be looked up via the function zope.component.getAdapter. Adapters from multiple Interfaces have to be looked up via the function zope.component.getMultiAdapter, which is slightly less pretty.
You can have more than one adapter for a given set of Interfaces, differentiated by a string name that you provide when registering the adapter. The name defaults to "". For example, BrowserViews are actually adapters that adapt from the interface that they're registered on and an interface that the HTTPRequest class implements. You can also look up all of the adapters that are registered from one sequence of Interfaces to another Interface, using zope.component.getAdapters( (IAdaptFrom,), IAdaptTo ), which returns a sequence of (name, adapter) pairs. This can be used as a very nice way to provide hooks for plugins to attach themselves to.
Say I wanted to save all my blog's posts and configuration as one big XML file. I create a my.blog.xmldump egg which defines an IXMLSegment, and registers an adapter from IBlogPost to IXMLSegment and an adapter from IBlogConfiguration to IXMLSegment. I can now call whichever adapter is appropriate for some object I want to serialize by writing IXMLSegment(object_to_serialize).
I could even add more adapters from various other things to IXMLSegment from eggs other than my.blog.xmldump. ZCML has a feature where it can run a particular directive if and only if some egg is installed. I could use this to have my.blog.rss register an adapter from IRSSFeed to IXMLSegment iff my.blog.xmldump happens to be installed, without making my.blog.rss depend on my.blog.xmldump.
Viewlets are like little BrowserViews that you can have 'subscribe' to a particular spot inside a page. I can't remember all the details right now but these are very good for things like plugins that you want to appear in a sidebar.
I can't remember offhand whether they're part of base Zope or Plone. I would recommend against using Plone unless the problem that you are trying to solve actually needs a real CMS, since it's a big and complicated piece of software and it tends to be kinda slow.
You don't necessarily actually need Viewlets anyway, since BrowserViews can call one another, either by using 'object/##some_browser_view' in a TAL expression, or by using queryMultiAdapter( (ISomething, IHttpRequest), name='some_browser_view' ), but they're pretty nice regardless.
Marker Interfaces. A marker Interface is an Interface that provides no methods and no attributes. You can add a marker Interface any object at runtime using ISomething.alsoProvidedBy. This allows you to, for example, alter which adapters will get used on a particular object and which BrowserViews will be defined on it.
I apologise that I haven't gone into enough detail to be able to implement each of these examples straight away, but they'd take approximately a blog post each.
You can actually test if your object or class implements your interface.
For that you can use verify module (you would normally use it in your tests):
>>> from zope.interface import Interface, Attribute, implements
>>> class IFoo(Interface):
... x = Attribute("The X attribute")
... y = Attribute("The Y attribute")
>>> class Foo(object):
... implements(IFoo)
... x = 1
... def __init__(self):
... self.y = 2
>>> from zope.interface.verify import verifyObject
>>> verifyObject(IFoo, Foo())
True
>>> from zope.interface.verify import verifyClass
>>> verifyClass(IFoo, Foo)
True
Interfaces can also be used for setting and testing invariants.
You can find more information here:
http://www.muthukadan.net/docs/zca.html#interfaces
Zope interfaces can provide a useful way to decouple two pieces of code that shouldn't depend on each other.
Say we have a component that knows how to print a greeting in module a.py:
>>> class Greeter(object):
... def greet(self):
... print 'Hello'
And some code that needs to print a greeting in module b.py:
>>> Greeter().greet()
'Hello'
This arrangement makes it hard to swap out the code that handles the greeting without touching b.py (which might be distributed in a separate package). Instead, we could introduce a third module c.py which defines an IGreeter interface:
>>> from zope.interface import Interface
>>> class IGreeter(Interface):
... def greet():
... """ Gives a greeting. """
Now we can use this to decouple a.py and b.py. Instead of instantiating a Greeter class, b.py will now ask for a utility providing the IGreeter interface. And a.py will declare that the Greeter class implements that interface:
(a.py)
>>> from zope.interface import implementer
>>> from zope.component import provideUtility
>>> from c import IGreeter
>>> #implementer(IGreeter)
... class Greeter(object):
... def greet(self):
... print 'Hello'
>>> provideUtility(Greeter(), IGreeter)
(b.py)
>>> from zope.component import getUtility
>>> from c import IGreeter
>>> greeter = getUtility(IGreeter)
>>> greeter.greet()
'Hello'
I've never used Zope interfaces, but you might consider writing a metaclass, which on initialization checks the members of the class against the interface, and raises a runtime exception if a method isn't implemented.
With Python you don't have other options. Either have a "compile" step that inspects your code, or dynamically inspect it at runtime.
In Java IoC / DI is a very common practice which is extensively used in web applications, nearly all available frameworks and Java EE. On the other hand, there are also lots of big Python web applications, but beside of Zope (which I've heard should be really horrible to code) IoC doesn't seem to be very common in the Python world. (Please name some examples if you think that I'm wrong).
There are of course several clones of popular Java IoC frameworks available for Python, springpython for example. But none of them seems to get used practically. At least, I've never stumpled upon a Django or sqlalchemy+<insert your favorite wsgi toolkit here> based web application which uses something like that.
In my opinion IoC has reasonable advantages and would make it easy to replace the django-default-user-model for example, but extensive usage of interface classes and IoC in Python looks a bit odd and not »pythonic«. But maybe someone has a better explanation, why IoC isn't widely used in Python.
I don't actually think that DI/IoC are that uncommon in Python. What is uncommon, however, are DI/IoC frameworks/containers.
Think about it: what does a DI container do? It allows you to
wire together independent components into a complete application ...
... at runtime.
We have names for "wiring together" and "at runtime":
scripting
dynamic
So, a DI container is nothing but an interpreter for a dynamic scripting language. Actually, let me rephrase that: a typical Java/.NET DI container is nothing but a crappy interpreter for a really bad dynamic scripting language with butt-ugly, sometimes XML-based, syntax.
When you program in Python, why would you want to use an ugly, bad scripting language when you have a beautiful, brilliant scripting language at your disposal? Actually, that's a more general question: when you program in pretty much any language, why would you want to use an ugly, bad scripting language when you have Jython and IronPython at your disposal?
So, to recap: the practice of DI/IoC is just as important in Python as it is in Java, for exactly the same reasons. The implementation of DI/IoC however, is built into the language and often so lightweight that it completely vanishes.
(Here's a brief aside for an analogy: in assembly, a subroutine call is a pretty major deal - you have to save your local variables and registers to memory, save your return address somewhere, change the instruction pointer to the subroutine you are calling, arrange for it to somehow jump back into your subroutine when it is finished, put the arguments somewhere where the callee can find them, and so on. IOW: in assembly, "subroutine call" is a Design Pattern, and before there were languages like Fortran which had subroutine calls built in, people were building their own "subroutine frameworks". Would you say that subroutine calls are "uncommon" in Python, just because you don't use subroutine frameworks?)
BTW: for an example of what it looks like to take DI to its logical conclusion, take a look at Gilad Bracha's Newspeak Programming Language and his writings on the subject:
Constructors Considered Harmful
Lethal Injection
A Ban on Imports (continued)
IoC and DI are super common in mature Python code. You just don't need a framework to implement DI thanks to duck typing.
The best example is how you set up a Django application using settings.py:
# settings.py
CACHES = {
'default': {
'BACKEND': 'django_redis.cache.RedisCache',
'LOCATION': REDIS_URL + '/1',
},
'local': {
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
'LOCATION': 'snowflake',
}
}
Django Rest Framework utilizes DI heavily:
class FooView(APIView):
# The "injected" dependencies:
permission_classes = (IsAuthenticated, )
throttle_classes = (ScopedRateThrottle, )
parser_classes = (parsers.FormParser, parsers.JSONParser, parsers.MultiPartParser)
renderer_classes = (renderers.JSONRenderer,)
def get(self, request, *args, **kwargs):
pass
def post(self, request, *args, **kwargs):
pass
Let me remind (source):
"Dependency Injection" is a 25-dollar term for a 5-cent concept. [...] Dependency injection means giving an object its instance variables. [...].
Part of it is the way the module system works in Python. You can get a sort of "singleton" for free, just by importing it from a module. Define an actual instance of an object in a module, and then any client code can import it and actually get a working, fully constructed / populated object.
This is in contrast to Java, where you don't import actual instances of objects. This means you are always having to instantiate them yourself, (or use some sort of IoC/DI style approach). You can mitigate the hassle of having to instantiate everything yourself by having static factory methods (or actual factory classes), but then you still incur the resource overhead of actually creating new ones each time.
Django makes great use of inversion of control. For instance, the database server is selected by the configuration file, then the framework provides appropriate database wrapper instances to database clients.
The difference is that Python has first-class types. Data types, including classes, are themselves objects. If you want something to use a particular class, simply name the class. For example:
if config_dbms_name == 'postgresql':
import psycopg
self.database_interface = psycopg
elif config_dbms_name == 'mysql':
...
Later code can then create a database interface by writing:
my_db_connection = self.database_interface()
# Do stuff with database.
Instead of the boilerplate factory functions that Java and C++ need, Python does it with one or two lines of ordinary code. This is the strength of functional versus imperative programming.
It seems that people really don't get what Dependency injection and inversion of control mean anymore.
The practice of using inversion of control is to have classes or functions that depend on other classes or functions, but instead of creating the instances whithin the class or function code it is better to receive them as parameters, so loose coupling can be achieved. That has many benefits as more testability and to achieve the liskov substitution principle.
You see, by working with interfaces and injections, your code gets more maintainable, since you can change the behavior easily, because you won't have to rewrite a single line of code (maybe a line or two on the DI configuration) of your class to change its behavior, since the classes that implement the interface your class is waiting for can vary independently as long as they follow the interface. One of the best strategies to keep code decoupled and easy to maintain is to follow at least the single responsibility, substitution and dependency inversion principles.
What's a DI library good for if you can instantiate an object yourself inside a package and import it to inject it yourself? The chosen answer is right, since java has no procedural sections (code outside of classes), all that goes into boring configuration xml's, hence the need of a class to instantiate and inject dependencies on a lazy load fashion so you don't blow away your performance, while on python you just code the injections in the "procedural" (code outside classes) sections of your code.
Haven't used Python in several years, but I would say that it has more to do with it being a dynamically typed language than anything else. For a simple example, in Java, if I wanted to test that something wrote to standard out appropriately I could use DI and pass in any PrintStream to capture the text being written and verify it. When I'm working in Ruby, however, I can dynamically replace the 'puts' method on STDOUT to do the verify, leaving DI completely out of the picture. If the only reason I'm creating an abstraction is to test the class that's using it (think File system operations or the clock in Java) then DI/IoC creates unnecessary complexity in the solution.
Actually, it is quite easy to write sufficiently clean and compact code with DI (I wonder, will it be/stay pythonic then, but anyway :) ), for example I actually perefer this way of coding:
def polite(name_str):
return "dear " + name_str
def rude(name_str):
return name_str + ", you, moron"
def greet(name_str, call=polite):
print "Hello, " + call(name_str) + "!"
_
>>greet("Peter")
Hello, dear Peter!
>>greet("Jack", rude)
Hello, Jack, you, moron!
Yes, this can be viewed as just a simple form of parameterizing functions/classes, but it does its work. So, maybe Python's default-included batteries are enough here too.
P.S. I have also posted a larger example of this naive approach at Dynamically evaluating simple boolean logic in Python.
IoC/DI is a design concept, but unfortunately it's often taken as a concept that applies to certain languages (or typing systems). I'd love to see dependency injection containers become far more popular in Python. There's Spring, but that's a super-framework and seems to be a direct port of the Java concepts without much consideration for "The Python Way."
Given Annotations in Python 3, I decided to have a crack at a full featured, but simple, dependency injection container: https://github.com/zsims/dic . It's based on some concepts from a .NET dependency injection container (which IMO is fantastic if you're ever playing in that space), but mutated with Python concepts.
I think due to the dynamic nature of python people don't often see the need for another dynamic framework. When a class inherits from the new-style 'object' you can create a new variable dynamically (https://wiki.python.org/moin/NewClassVsClassicClass).
i.e.
In plain python:
#application.py
class Application(object):
def __init__(self):
pass
#main.py
Application.postgres_connection = PostgresConnection()
#other.py
postgres_connection = Application.postgres_connection
db_data = postgres_connection.fetchone()
However have a look at https://github.com/noodleflake/pyioc this might be what you are looking for.
i.e. In pyioc
from libs.service_locator import ServiceLocator
#main.py
ServiceLocator.register(PostgresConnection)
#other.py
postgres_connection = ServiceLocator.resolve(PostgresConnection)
db_data = postgres_connection.fetchone()
pytest fixtures all based on DI (source)
Check out FastAPI, it has dependency injection built-in. For example:
from fastapi import Depends, FastAPI
async def get_db():
db = DBSession()
try:
yield db
except Exception:
db.rollback()
raise
finally:
db.close()
app = FastAPI()
#app.get("/items")
def get_items(db=Depends(get_db)):
return db.get_items()
I back "Jörg W Mittag" answer: "The Python implementation of DI/IoC is so lightweight that it completely vanishes".
To back up this statement, take a look at the famous Martin Fowler's example ported from Java to Python: Python:Design_Patterns:Inversion_of_Control
As you can see from the above link, a "Container" in Python can be written in 8 lines of code:
class Container:
def __init__(self, system_data):
for component_name, component_class, component_args in system_data:
if type(component_class) == types.ClassType:
args = [self.__dict__[arg] for arg in component_args]
self.__dict__[component_name] = component_class(*args)
else:
self.__dict__[component_name] = component_class
My 2cents is that in most Python applications you don't need it and, even if you needed it, chances are that many Java haters (and incompetent fiddlers who believe to be developers) consider it as something bad, just because it's popular in Java.
An IoC system is actually useful when you have complex networks of objects, where each object may be a dependency for several others and, in turn, be itself a dependant on other objects. In such a case you'll want to define all these objects once and have a mechanism to put them together automatically, based on as many implicit rules as possible. If you also have configuration to be defined in a simple way by the application user/administrator, that's an additional reason to desire an IoC system that can read its components from something like a simple XML file (which would be the configuration).
The typical Python application is much simpler, just a bunch of scripts, without such a complex architecture. Personally I'm aware of what an IoC actually is (contrary to those who wrote certain answers here) and I've never felt the need for it in my limited Python experience (also I don't use Spring everywhere, not when the advantages it gives don't justify its development overhead).
That said, there are Python situations where the IoC approach is actually useful and, in fact, I read here that Django uses it.
The same reasoning above could be applied to Aspect Oriented Programming in the Java world, with the difference that the number of cases where AOP is really worthwhile is even more limited.
You can do dependency injection with Python manually, but manual approach has its downsides:
lots of boilerplate code to do the wiring. You can use dynamic features of Python to do the injection, but then you're loosing IDE support (e.g. Ctrl+Space in PyCharm), and you're making code harder to understand and debug
no standards: every programmer has its own way for solving same problems, this leads to reinventing the wheel, understanding each other's code can quickly become a pain. Dependency injection library provides easy framework to plug-in
To have it all we NEED a dependency injection framework, for example this one https://python-dependency-injector.ets-labs.org/index.html seems to be the most mature DI framework for Python.
For smaller apps DI container is not necessary, for anything that has few hundred lines of code or more, DI container is a must have to keep your code maintaineable.
I agree with #Jorg in the point that DI/IoC is possible, easier and even more beautiful in Python. What's missing is the frameworks supporting it, but there are a few exceptions. To point a couple of examples that come to my mind:
Django comments let you wire your own Comment class with your custom logic and forms. [More Info]
Django let you use a custom Profile object to attach to your User model. This is not completely IoC but is a good approach. Personally I'd like to replace the hole User model as the comments framework does. [More Info]
IoC containers are "mimicked" mostly using **kwargs
class A:
def __init__(self, **kwargs):
print(kwargs)
Class B:
pass
Class C:
pass
Ainstance = A(b=B, c=C)
In my opinion, things like dependency injection are symptoms of a rigid and over-complex framework. When the main body of code becomes much too weighty to change easily, you find yourself having to pick small parts of it, define interfaces for them, and then allowing people to change behaviour via the objects that plug into those interfaces. That's all well and good, but it's better to avoid that sort of complexity in the first place.
It's also the symptom of a statically-typed language. When the only tool you have to express abstraction is inheritance, then that's pretty much what you use everywhere. Having said that, C++ is pretty similar but never picked up the fascination with Builders and Interfaces everywhere that Java developers did. It is easy to get over-exuberant with the dream of being flexible and extensible at the cost of writing far too much generic code with little real benefit. I think it's a cultural thing.
Typically I think Python people are used to picking the right tool for the job, which is a coherent and simple whole, rather than the One True Tool (With A Thousand Possible Plugins) that can do anything but offers a bewildering array of possible configuration permutations. There are still interchangeable parts where necessary, but with no need for the big formalism of defining fixed interfaces, due to the flexibility of duck-typing and the relative simplicity of the language.
Unlike the strong typed nature in Java. Python's duck typing behavior makes it so easy to pass objects around.
Java developers are focusing on the constructing the class strcuture and relation between objects, while keeping things flexible. IoC is extremely important for achieving this.
Python developers are focusing on getting the work done. They just wire up classes when they need it. They don't even have to worry about the type of the class. As long as it can quack, it's a duck! This nature leaves no room for IoC.