December 26th, 2014
In Technology
No Comments
If you enjoy this article, see the other most popular articles
If you enjoy this article, see the other most popular articles
If you enjoy this article, see the other most popular articles
Boring is good in Python’s __init__
(written by lawrence krubner, however indented passages are often quotes). You can contact lawrence at: lawrence@krubner.com, or follow me on Twitter.
You might notice that these three observations I’ve made all sound a bit negative. You might conclude that I think this is an antipattern to be avoided. If so, feel free to give yourself a pat on the back at this point.
But if this is an antipattern, is there a pattern to use instead? I think so. I’ll try to explain it.
The general idea behind the pattern I’m going to suggest comes in two parts. The first part is that your object should primarily be about representing state and your __init__ method should be about accepting that state from the outside world and storing it away on the instance being initialized for later use. It should always represent complete, internally consistent state – not partial state as asynchronous initialization implies. This means your __init__ methods should mostly look like this:
class Microblog(object): def __init__(self, cache_dir, database_connection): self.cache_dir = cache_dir self.database_connection = database_connectionIf you think that looks boring – yes, it does. Boring is a good thing here. Anything exciting your __init__ method does is probably going to be the cause of someone’s bad day sooner or later. If you think it looks tedious – yes, it does. Consider using Hynek Schlawack’s excellent characteristic package (full disclosure – I contributed some ideas to characteristic’s design and Hynek ocassionally says nice things about me (I don’t know if he means them, I just know he says them)).
The second part of the idea an acknowledgement that asynchronous initialization is a reality of programming with asynchronous tools. Fortunately __init__ isn’t the only place to put code. Asynchronous factory functions are a great way to wrap up the asynchronous work sometimes necessary before an object can be fully and consistently initialized. Put another way:
class Microblog(object): # ... __init__ as above ... @classmethod @asyncio.coroutine def from_database(cls, cache_dir, database_path): # ... or make it a free function, not a classmethod, if you prefer loop = asyncio.get_event_loop() database_connection = yield from loop.run_in_executor(None, cls._reading_init) return cls(cache_dir, database_connection)Notice that the setup work for a Microblog instance is still asynchronous but initialization of the Microblog instance is not. There is never a time when a Microblog instance is hanging around partially ready for action. There is setup work and then there is a complete, usable Microblog.
Post external references
- 1
http://as.ynchrono.us/2014/12/asynchronous-object-initialization.html
February 8, 2022 9:33 am
From Michael S on How I recovered from Lyme Disease: I fasted for two weeks, no food, just water
"Did you have Bartonella, too? Seems it uses autogenesis..."