<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>python &amp;mdash; StealthyCoder</title>
    <link>https://stealthycoder.writeas.com/tag:python</link>
    <description>Making code ninjas out of everyone</description>
    <pubDate>Wed, 29 Apr 2026 01:44:18 +0000</pubDate>
    <item>
      <title>Supply and demand</title>
      <link>https://stealthycoder.writeas.com/supply-and-demand?pk_campaign=rss-feed</link>
      <description>&lt;![CDATA[This post will touch on two subjects that I already talked about, Amara&#39;s Law and creativity thrives in structure. I will reiterate Amara&#39;s Law here though:&#xA;&#xA;  We tend to overestimate the effect of a technology in the short run and underestimate the effect in the long run.&#xA;!--more--&#xA;In the past few weeks I worked on refactoring three Python projects in the field of data processing and OSINT (Open-Source Intelligence) and all those projects turned exactly into the same structure so I thought I would write a piece on how I ( and a friend of mine ) reworked the code into a structure that works for three separate projects. In three different domains but all do data processing and analysis. &#xA;&#xA;The structure we made followed the concepts of Suppliers and Consumers. This is not new by any means, but there a lot of patterns and sometimes people forget them. This pattern has the concept of a class being a Supplier and therefore it supplies data. What that data is, that is arbitrary, numbers, string or other classes. Then there are classes who are Consumers, they consume whatever the data is given by the Supplier and do something with it, or not. The Supplier might get some input to where to get the data, then the input for the Consumer is the output of the Supplier and maybe the output of the Consumer is the input for a new Supplier or Consumer.&#xA;&#xA;There might be special types of Consumers that all do a similar action, like transforming the data in a particular way. These Consumers might collectively be called Transformers. Cue 80s cartoon music... Suppliers that get the data from a specific place might also be named as such, like a Database Supplier getting the data from a database. &#xA;&#xA;I will present the whole code and then in sections refactor it into a nice structure. You can easily find who wrote the original code but it is not a gibe towards that person. &#xA;&#xA;def main():&#xA;    planet = &#34;mars&#34;&#xA;    myearthweightkg = 75  # 165lbs / 11.8st&#xA;    weights = calculateweights(planet, myearthweightkg)&#xA;    print(f&#34;A person weighing {myearthweightkg}kg on Earth would weigh:\n&#34;)&#xA;    print(f&#34;  {weights[&#39;pounds&#39;]:  3.2f}lbs&#34;)&#xA;    print(f&#34;  {weights[&#39;stones&#39;]:  2.2f}st&#34;)&#xA;    print(f&#34;  {weights[&#39;kilograms&#39;]:  3.2f}kg&#34;)&#xA;    print(f&#34;\non {planet.capitalize()}.&#34;)&#xA;&#xA;def calculateweights(planet, myearthweightkg):&#xA;    planetdetails = getplanetdetails()&#xA;    G = 6.67408  10-11&#xA;    Fg = G  ((planetdetailsplanet  myearthweightkg)&#xA;              / (planetdetailsplanet  2))&#xA;    weights = newtonstoweights(Fg)&#xA;    return weights&#xA;&#xA;def getplanetdetails():&#xA;    planetdetails = {}&#xA;    planetdetails[&#34;mercury&#34;] = {&#34;masskg&#34;: 3.3011  10*23,&#xA;                                 &#34;meanradiusmetres&#34;: 2439.7  1000}&#xA;    planetdetails[&#34;venus&#34;] = {&#34;masskg&#34;: 4.8675  1024,&#xA;                               &#34;meanradiusmetres&#34;: 6051.8  1000}&#xA;    planetdetails[&#34;earth&#34;] = {&#34;masskg&#34;: 5.97237  1024,&#xA;                               &#34;meanradiusmetres&#34;: 6371  1000}&#xA;    planetdetails[&#34;mars&#34;] = {&#34;masskg&#34;: 6.4171  1023,&#xA;                              &#34;meanradiusmetres&#34;: 3389.5  1000}&#xA;    planetdetails[&#34;jupiter&#34;] = {&#34;masskg&#34;: 1.8982  1027,&#xA;                                 &#34;meanradiusmetres&#34;: 69911  1000}&#xA;    planetdetails[&#34;saturn&#34;] = {&#34;masskg&#34;: 5.6834  1026,&#xA;                                &#34;meanradiusmetres&#34;: 58232  1000}&#xA;    planetdetails[&#34;uranus&#34;] = {&#34;masskg&#34;: 8.681  1025,&#xA;                                &#34;meanradiusmetres&#34;: 25362  1000}&#xA;    planetdetails[&#34;neptune&#34;] = {&#34;masskg&#34;: 1.02413  1026,&#xA;                                 &#34;meanradiusmetres&#34;: 24622  1000}&#xA;    return planetdetails&#xA;&#xA;def newtonstoweights(N):&#xA;    weights = {}&#xA;    weights[&#34;newtons&#34;] = N&#xA;    weights[&#34;pounds&#34;] = N / 4.4482216&#xA;    weights[&#34;stones&#34;] = weights[&#34;pounds&#34;] / 14&#xA;    weights[&#34;kilograms&#34;] = N / 9.80665&#xA;    return weights&#xA;&#xA;main()&#xA;&#xA;Supplier&#xA;The method called get\planet\details() looks like a Supplier type to me. It supplies in this case a dictionary of planets with some properties. So first let us create a Planet class that holds data about planets that we need. If you follow along and created an empty dir with nothing in it yet then create a directory now called models . Within that models directory place two files: \\init\\.py and planet.py . &#xA;Inside \\init\\.py place the following code:&#xA;class Model(object):&#xA;    pass&#xA;&#xA;Inside planet.py place the following code:&#xA;from typing import Union&#xA;from models import Model&#xA;&#xA;class Planet(Model):&#xA;    def init(self, &#xA;                    name: str, &#xA;                    mass: Union[float, str], &#xA;                    radius: Union[float, str],&#xA;                    orderofmass: Union[int, str],&#xA;                    orderofradius: Union[int, str]):&#xA;        self.name = name&#xA;        self.mass = float(mass)&#xA;        self.radius = float(radius)&#xA;        self.orderofmass = int(orderofmass)&#xA;        self.orderofradius = int(orderofradius)&#xA;&#xA;    @property&#xA;    def mass(self):&#xA;        return self.mass  10  self.orderofmass&#xA;&#xA;    @property&#xA;    def radius(self):&#xA;        return self.radius  10 * self.orderofradius&#xA;I put the order\of\mass and order\of\radius attributes there so we can give the unit like 3.3011 \ 10\\23 as two separate values the mass base unit 3.3011 and the order of magnitude &#xA;23. The @property tells Python the function can actually be accessed like a property and therefore we can give back the calculated properties for mass and radius. The Model is now only there so we can do nice type hinting&#xA;&#xA;Next we need a Supplier to give back all these Planet objects. &#xA;Make the following directories from the root suppliers/planet/planets . So you have two directories in the root, suppliers and models. Inside suppliers/planet create the file PlanetSupplier.py with the following contents:&#xA;import os&#xA;from config import Config&#xA;from models.planet import Planet&#xA;from suppliers.BaseSupplier import BaseSupplier&#xA;from typing import Generator&#xA;&#xA;class PlanetSupplier(BaseSupplier):&#xA;    def init(self, config: Config):&#xA;        self.config = config&#xA;        self.planets = []&#xA;        location = self.config.supplier[&#39;location&#39;]&#xA;        for ini in sorted(os.listdir(location)):&#xA;            planetini = self.config.parse(open(location + &#34;/&#34; + ini))&#xA;            self.planets.append(Planet(planetini.defaults()))&#xA;    &#xA;    def supply(self) -  Generator[Planet, None, None]:&#xA;        for planet in self.planets:&#xA;            yield planet&#xA;&#xA;    def validate(config):&#xA;        assert &#34;location&#34; in config.supplier, &#34;location property is needed&#34;     &#xA;Before we get into the new mentioned classes a quick word about the ideas. The BaseSupplier object is there for type hinting and the static method validate (not annotated here because it comes from BaseSupplier) is there to make sure the configuration is valid. &#xA;&#xA;So we will use .ini* files to handle the data representation on all the planets, they are in a location ( I wonder if you can already guess where) and the location comes from a Config object. It will then parse each ini file in that location. Optional improvement here is to use glob to only read in files that have a .ini suffix. Then it creates a Planet instance and appends it to the list. &#xA;&#xA;The \\planet.inidefaults() gives back an OrderedDict so if we make the ini file have the same keys as the Planet constructor ones for the key value pairs it will automatically unpack it for us into the constructor. Regardless of order in the ini file. That is pretty handy. So next first let us take a look a the .ini file. &#xA;[DEFAULT]&#xA;name=Earth&#xA;mass=5.97237&#xA;orderofmass=24&#xA;radius=6371&#xA;orderofradius=3&#xA;The DEFAULT is a special keyword making the values go into the call for inidefaults later. You might have wondered at the extra call to float  in the Planet \\init\\ method. This is because ini files handle everything as strings, so therefore we have to convert them once. Naturally all these files will be placed in the suppliers/planet/planets/ folder. This example is called earth.ini. &#xA;&#xA;Next let us take a look at the BaseSupplier. It lives in the file BaseSupplier.py inside the suppliers directory. &#xA;import abc&#xA;from models import Model&#xA;from typing import Union, Generator&#xA;from config import Config&#xA;&#xA;class BaseSupplier(object):&#xA;    &#xA;    @staticmethod&#xA;    @abc.abstractmethod&#xA;    def validate(config: Config) -  None:&#xA;        pass&#xA;&#xA;    @abc.abstractmethod&#xA;    def supply(self) -  Generator[Model, None, None]:&#xA;        pass&#xA;The BaseSupplier sets two methods and there you can see the Model for type hinting. The supply method should be a generator always because that allows for lazy loading and evaluation when dealing with large data sets this means the program will not be limited so much by storage and memory limits. &#xA;&#xA;Next let us take a look at the Config. It lives in the root of the project in the file config.py.&#xA;import configparser&#xA;&#xA;class Config(object):&#xA;    def init(self):&#xA;        parser = configparser.ConfigParser()&#xA;        assert len(parser.read(&#34;config.ini&#34;)) != 0, &#34;Could not read config file&#34;&#xA;        Config.validate(parser)&#xA;        self.supplier = parser[&#39;supplier&#39;]&#xA;&#xA;    &#xA;    @staticmethod&#xA;    def validate(parser: configparser.ConfigParser) -  None:&#xA;        assert &#34;supplier&#34; in parser, &#34;Supplier section must be there&#34;&#xA;        assert &#34;type&#34; in parser[&#39;supplier&#39;], &#34;Supplier section must have a type&#34;&#xA;    &#xA;    @staticmethod&#xA;    def parse(fp) -  configparser.ConfigParser:&#xA;        parser = configparser.ConfigParser()&#xA;        parser.readfile(fp)&#xA;        return parser&#xA;As you can see here the Config gets instantiated with a call to a hard coded filename called config.ini. This could be improved by specifying the name in the constructor. Next we do a simple validation check and then also give a static parse method so other classes can parse .ini files without having to import and deal with parsing. &#xA;&#xA;There is one more class I want to add and that is an AgnosticSupplier. I will first show the class here and this class lives in the \\init\\.py class inside the suppliers directory. &#xA;from config import Config&#xA;from suppliers.planet.PlanetSupplier import PlanetSupplier&#xA;from suppliers.BaseSupplier import BaseSupplier&#xA;from typing import Dict&#xA;&#xA;class AgnosticSupplier(object):&#xA;    def init(self, config: Config):&#xA;        self.config = config&#xA;        self.providermap: Dict[BaseSupplier] = {&#xA;            &#34;planet&#34;: PlanetSupplier&#xA;        }&#xA;&#xA;    def getsupplier(self) -  BaseSupplier:&#xA;        supplier: BaseSupplier = self.providermap.get(self.config.supplier[&#39;type&#39;])&#xA;        supplier.validate(self.config)&#xA;        return supplier(self.config)&#xA;So the AgnosticSupplier is here for your ease of use. You give it a Config object and on the basis of that it will give you the correct Supplier back based on the type and a simple map, which is just a dictionary of type name and class . As you can see here there is a call to supplier.validate to make sure the config is valid. Next the config.ini file itself, which is placed in the root directory:&#xA;[supplier]&#xA;type=planet&#xA;location=suppliers/planet/planets&#xA;There you see all that is needed to make sure the PlanetSupplier has all the information. &#xA;&#xA;Consumer&#xA;&#xA;def calculateweights(planet, myearthweightkg):&#xA;    planetdetails = getplanetdetails()&#xA;    G = 6.67408  10*-11&#xA;    Fg = G  ((planetdetailsplanet  myearthweightkg)&#xA;              / (planetdetailsplanet  2))&#xA;    weights = newtonstoweights(Fg)&#xA;    return weights&#xA;&#xA;def newtonstoweights(N):&#xA;    weights = {}&#xA;    weights[&#34;newtons&#34;] = N&#xA;    weights[&#34;pounds&#34;] = N / 4.4482216&#xA;    weights[&#34;stones&#34;] = weights[&#34;pounds&#34;] / 14&#xA;    weights[&#34;kilograms&#34;] = N / 9.80665&#xA;    return weights&#xA;Now then. We have a Supplier, a Model so now all we need is the actual operation of getting the weight and it will be inside a Consumer. A special one, a Transformer. So go ahead and make a directory called  transformers/planet in the root of the project. Inside transformers/planet create the file WeightTransformer.py and put the following code in:&#xA;from models.planet import Planet&#xA;from suppliers.planet.PlanetSupplier import PlanetSupplier&#xA;from typing import Generator&#xA;&#xA;class WeightTransformer(object):&#xA;    class Result(object):&#xA;        def init(self, newtons: float, planet: Planet):&#xA;            self.newtons = newtons&#xA;            self.planet = planet&#xA;    &#xA;        @property&#xA;        def pounds(self):&#xA;           return self.newtons / 4.4482216&#xA;&#xA;        @property&#xA;        def stones(self):&#xA;            return self.pounds / 14&#xA;&#xA;        @property&#xA;        def kilograms(self):&#xA;            return self.newtons / 9.80665&#xA;&#xA;    def init(self, supplier: PlanetSupplier, weight: float):&#xA;        self.supplier = supplier&#xA;        self.weight = weight&#xA;        self.G = 6.67408  10*-11&#xA;&#xA;    def transform(self) -  Generator[Result, None, None]:&#xA;        for planet in self.supplier.supply():&#xA;            Fg = self.G  ((planet.mass  self.weight) / (planet.radius * 2))&#xA;            &#xA;            yield self.Result(Fg, planet)&#xA;So this will take over the piece of calculating the weights and also give an inner class of Result responsible for calculating the different forms of weight. As you can see another generator is used for the case of large data sets. It loops over all the ones from the Supplier not just one.&#xA;Now all we need is to run the program again. The only thing I did not completely take over again was the formatted printing, I am just going to fully print everything. This next code can be placed inside main.py in your root directory.&#xA;from config import Config&#xA;from suppliers import AgnosticSupplier&#xA;from transformers.planet.WeightTransformer import WeightTransformer&#xA;&#xA;c = Config()&#xA;supplier = AgnosticSupplier(c).get_supplier()&#xA;wt = WeightTransformer(supplier, 75)&#xA;for result in wt.transform():&#xA;    print(result.planet.name, result.kilograms)&#xA;It will print out for every planet in this case. If you just want Mars then you add an if statement. &#xA;&#xA;That is it. We transformed a simple code into a nice structure.&#xA;&#xA;Closing thoughts&#xA;Why this structure? Is this not overkill? This seems complicated for such a simple task. Maybe you are having these questions and thoughts right now. Remember the law you read at the beginning. The value in this structure is that I can add properties to every planet ini file and change the Planet constructor and the rest of the code will still work. &#xA;&#xA;We have single point of entry in the AgnosticSupplier, so again if we change something in the PlanetSupplier overall if it will keep the supply method then no worries. If we want to add more calculations for example we add the property to the planets for distance from Earth then a simple CommunicationTimings class can take the PlanetSupplier and give you back how long it will take for a single message to reach that planet using radio, light or something else to communicate. Your WeightTransformer will still work too. &#xA;&#xA;In the future we discover a new planet and it is only one .ini file away from being included in the code. You know exactly where to put it and it will get picked up. Maybe in the future there won&#39;t be a need for the ini files. Someone gives you a SQLite database file with all the data. You make a DatabaseSupplier and rewrite the PlanetSupplier a bit to get the data from the DatabaseSupplier and make it into Planets. &#xA;&#xA;#code #python]]&gt;</description>
      <content:encoded><![CDATA[<p>This post will touch on two subjects that I already talked about, <a href="https://stealthycoder.writeas.com/how-to-pierce-through-illusions" rel="nofollow">Amara&#39;s Law</a> and <a href="https://stealthycoder.writeas.com/structure-allows-for-creativity" rel="nofollow">creativity thrives in structure</a>. I will reiterate Amara&#39;s Law here though:</p>

<blockquote><p>We tend to overestimate the effect of a technology in the short run and underestimate the effect in the long run.

In the past few weeks I worked on refactoring three Python projects in the field of data processing and OSINT (Open-Source Intelligence) and all those projects turned exactly into the same structure so I thought I would write a piece on how I ( and a friend of mine ) reworked the code into a structure that works for three separate projects. In three different domains but all do data processing and analysis.</p></blockquote>

<p>The structure we made followed the concepts of Suppliers and Consumers. This is not new by any means, but there a lot of patterns and sometimes people forget them. This pattern has the concept of a class being a Supplier and therefore it supplies data. What that data is, that is arbitrary, numbers, string or other classes. Then there are classes who are Consumers, they consume whatever the data is given by the Supplier and do something with it, or not. The Supplier might get some input to where to get the data, then the input for the Consumer is the output of the Supplier and maybe the output of the Consumer is the input for a new Supplier or Consumer.</p>

<p>There might be special types of Consumers that all do a similar action, like transforming the data in a particular way. These Consumers might collectively be called Transformers. Cue 80s cartoon music... Suppliers that get the data from a specific place might also be named as such, like a Database Supplier getting the data from a database.</p>

<p>I will present the whole code and then in sections refactor it into a nice structure. You can easily find who wrote the original code but it is not a gibe towards that person.</p>

<pre><code class="language-python">def main():
    planet = &#34;mars&#34;
    my_earth_weight_kg = 75  # 165lbs / 11.8st
    weights = calculate_weights(planet, my_earth_weight_kg)
    print(f&#34;A person weighing {my_earth_weight_kg}kg on Earth would weigh:\n&#34;)
    print(f&#34;  {weights[&#39;pounds&#39;]:&gt;3.2f}lbs&#34;)
    print(f&#34;  {weights[&#39;stones&#39;]:&gt;2.2f}st&#34;)
    print(f&#34;  {weights[&#39;kilograms&#39;]:&gt;3.2f}kg&#34;)
    print(f&#34;\non {planet.capitalize()}.&#34;)

def calculate_weights(planet, my_earth_weight_kg):
    planet_details = get_planet_details()
    G = 6.67408 * 10**-11
    Fg = G * ((planet_details[planet][&#34;mass_kg&#34;] * my_earth_weight_kg)
              / (planet_details[planet][&#34;mean_radius_metres&#34;] ** 2))
    weights = newtons_to_weights(Fg)
    return weights

def get_planet_details():
    planet_details = {}
    planet_details[&#34;mercury&#34;] = {&#34;mass_kg&#34;: 3.3011 * 10**23,
                                 &#34;mean_radius_metres&#34;: 2439.7 * 1000}
    planet_details[&#34;venus&#34;] = {&#34;mass_kg&#34;: 4.8675 * 10**24,
                               &#34;mean_radius_metres&#34;: 6051.8 * 1000}
    planet_details[&#34;earth&#34;] = {&#34;mass_kg&#34;: 5.97237 * 10**24,
                               &#34;mean_radius_metres&#34;: 6371 * 1000}
    planet_details[&#34;mars&#34;] = {&#34;mass_kg&#34;: 6.4171 * 10**23,
                              &#34;mean_radius_metres&#34;: 3389.5 * 1000}
    planet_details[&#34;jupiter&#34;] = {&#34;mass_kg&#34;: 1.8982 * 10**27,
                                 &#34;mean_radius_metres&#34;: 69911 * 1000}
    planet_details[&#34;saturn&#34;] = {&#34;mass_kg&#34;: 5.6834 * 10**26,
                                &#34;mean_radius_metres&#34;: 58232 * 1000}
    planet_details[&#34;uranus&#34;] = {&#34;mass_kg&#34;: 8.681 * 10**25,
                                &#34;mean_radius_metres&#34;: 25362 * 1000}
    planet_details[&#34;neptune&#34;] = {&#34;mass_kg&#34;: 1.02413 * 10**26,
                                 &#34;mean_radius_metres&#34;: 24622 * 1000}
    return planet_details

def newtons_to_weights(N):
    weights = {}
    weights[&#34;newtons&#34;] = N
    weights[&#34;pounds&#34;] = N / 4.4482216
    weights[&#34;stones&#34;] = weights[&#34;pounds&#34;] / 14
    weights[&#34;kilograms&#34;] = N / 9.80665
    return weights

main()
</code></pre>

<h2 id="supplier" id="supplier">Supplier</h2>

<p>The method called <em>get_planet_details()</em> looks like a Supplier type to me. It supplies in this case a dictionary of planets with some properties. So first let us create a Planet class that holds data about planets that we need. If you follow along and created an empty dir with nothing in it yet then create a directory now called <strong>models</strong> . Within that <strong>models</strong> directory place two files: <strong>__init__.py</strong> and <strong>planet.py</strong> .
Inside <strong>__init__.py</strong> place the following code:</p>

<pre><code class="language-python">class Model(object):
    pass
</code></pre>

<p>Inside <strong>planet.py</strong> place the following code:</p>

<pre><code class="language-python">from typing import Union
from models import Model

class Planet(Model):
    def __init__(self, 
                    name: str, 
                    mass: Union[float, str], 
                    radius: Union[float, str],
                    order_of_mass: Union[int, str],
                    order_of_radius: Union[int, str]):
        self.name = name
        self._mass = float(mass)
        self._radius = float(radius)
        self.order_of_mass = int(order_of_mass)
        self.order_of_radius = int(order_of_radius)

    @property
    def mass(self):
        return self._mass * 10 ** self.order_of_mass

    @property
    def radius(self):
        return self._radius * 10 ** self.order_of_radius
</code></pre>

<p>I put the <em>order_of_mass</em> and <em>order_of_radius</em> attributes there so we can give the unit like <em>3.3011 * 10**23</em> as two separate values the mass base unit <em>3.3011</em> and the order of magnitude
<em>23</em>. The <em>@property</em> tells Python the function can actually be accessed like a property and therefore we can give back the calculated properties for mass and radius. The Model is now only there so we can do nice type hinting</p>

<p>Next we need a Supplier to give back all these Planet objects.
Make the following directories from the root <em>suppliers/planet/planets</em> . So you have two directories in the root, suppliers and models. Inside <em>suppliers/planet</em> create the file <em>PlanetSupplier.py</em> with the following contents:</p>

<pre><code class="language-python">import os
from config import Config
from models.planet import Planet
from suppliers.BaseSupplier import BaseSupplier
from typing import Generator

class PlanetSupplier(BaseSupplier):
    def __init__(self, config: Config):
        self.config = config
        self.planets = []
        location = self.config.supplier[&#39;location&#39;]
        for ini in sorted(os.listdir(location)):
            planet_ini = self.config.parse(open(location + &#34;/&#34; + ini))
            self.planets.append(Planet(**planet_ini.defaults()))
    
    def supply(self) -&gt; Generator[Planet, None, None]:
        for planet in self.planets:
            yield planet

    def validate(config):
        assert &#34;location&#34; in config.supplier, &#34;location property is needed&#34;     
</code></pre>

<p>Before we get into the new mentioned classes a quick word about the ideas. The BaseSupplier object is there for type hinting and the static method validate (not annotated here because it comes from BaseSupplier) is there to make sure the configuration is valid.</p>

<p>So we will use <strong>.ini</strong> files to handle the data representation on all the planets, they are in a location ( I wonder if you can already guess where) and the location comes from a Config object. It will then parse each ini file in that location. Optional improvement here is to use glob to only read in files that have a <em>.ini</em> suffix. Then it creates a Planet instance and appends it to the list.</p>

<p>The **planet.ini_defaults() gives back an OrderedDict so if we make the ini file have the same keys as the Planet constructor ones for the key value pairs it will automatically unpack it for us into the constructor. Regardless of order in the ini file. That is pretty handy. So next first let us take a look a the .ini file.</p>

<pre><code class="language-ini">[DEFAULT]
name=Earth
mass=5.97237
order_of_mass=24
radius=6371
order_of_radius=3
</code></pre>

<p>The DEFAULT is a special keyword making the values go into the call for ini_defaults later. You might have wondered at the extra call to float  in the Planet __init__ method. This is because ini files handle everything as strings, so therefore we have to convert them once. Naturally all these files will be placed in the <em>suppliers/planet/planets/</em> folder. This example is called earth.ini.</p>

<p>Next let us take a look at the BaseSupplier. It lives in the file <em>BaseSupplier.py</em> inside the <em>suppliers</em> directory.</p>

<pre><code class="language-python">import abc
from models import Model
from typing import Union, Generator
from config import Config

class BaseSupplier(object):
    
    @staticmethod
    @abc.abstractmethod
    def validate(config: Config) -&gt; None:
        pass

    @abc.abstractmethod
    def supply(self) -&gt; Generator[Model, None, None]:
        pass
</code></pre>

<p>The BaseSupplier sets two methods and there you can see the Model for type hinting. The supply method should be a generator always because that allows for lazy loading and evaluation when dealing with large data sets this means the program will not be limited so much by storage and memory limits.</p>

<p>Next let us take a look at the Config. It lives in the root of the project in the file <em>config.py</em>.</p>

<pre><code class="language-python">import configparser


class Config(object):
    def __init__(self):
        parser = configparser.ConfigParser()
        assert len(parser.read(&#34;config.ini&#34;)) != 0, &#34;Could not read config file&#34;
        Config._validate(parser)
        self.supplier = parser[&#39;supplier&#39;]

    
    @staticmethod
    def _validate(parser: configparser.ConfigParser) -&gt; None:
        assert &#34;supplier&#34; in parser, &#34;Supplier section must be there&#34;
        assert &#34;type&#34; in parser[&#39;supplier&#39;], &#34;Supplier section must have a type&#34;
    
    @staticmethod
    def parse(fp) -&gt; configparser.ConfigParser:
        parser = configparser.ConfigParser()
        parser.read_file(fp)
        return parser
</code></pre>

<p>As you can see here the Config gets instantiated with a call to a hard coded filename called <em>config.ini</em>. This could be improved by specifying the name in the constructor. Next we do a simple validation check and then also give a static parse method so other classes can parse <em>.ini</em> files without having to import and deal with parsing.</p>

<p>There is one more class I want to add and that is an AgnosticSupplier. I will first show the class here and this class lives in the <strong>__init__.py</strong> class inside the <em>suppliers</em> directory.</p>

<pre><code class="language-python">from config import Config
from suppliers.planet.PlanetSupplier import PlanetSupplier
from suppliers.BaseSupplier import BaseSupplier
from typing import Dict

class AgnosticSupplier(object):
    def __init__(self, config: Config):
        self.config = config
        self.provider_map: Dict[BaseSupplier] = {
            &#34;planet&#34;: PlanetSupplier
        }

    def get_supplier(self) -&gt; BaseSupplier:
        supplier: BaseSupplier = self.provider_map.get(self.config.supplier[&#39;type&#39;])
        supplier.validate(self.config)
        return supplier(self.config)
</code></pre>

<p>So the AgnosticSupplier is here for your ease of use. You give it a Config object and on the basis of that it will give you the correct Supplier back based on the type and a simple map, which is just a dictionary of type name and class . As you can see here there is a call to supplier.validate to make sure the config is valid. Next the config.ini file itself, which is placed in the root directory:</p>

<pre><code class="language-ini">[supplier]
type=planet
location=suppliers/planet/planets
</code></pre>

<p>There you see all that is needed to make sure the PlanetSupplier has all the information.</p>

<h2 id="consumer" id="consumer">Consumer</h2>

<pre><code class="language-python">def calculate_weights(planet, my_earth_weight_kg):
    planet_details = get_planet_details()
    G = 6.67408 * 10**-11
    Fg = G * ((planet_details[planet][&#34;mass_kg&#34;] * my_earth_weight_kg)
              / (planet_details[planet][&#34;mean_radius_metres&#34;] ** 2))
    weights = newtons_to_weights(Fg)
    return weights

def newtons_to_weights(N):
    weights = {}
    weights[&#34;newtons&#34;] = N
    weights[&#34;pounds&#34;] = N / 4.4482216
    weights[&#34;stones&#34;] = weights[&#34;pounds&#34;] / 14
    weights[&#34;kilograms&#34;] = N / 9.80665
    return weights
</code></pre>

<p>Now then. We have a Supplier, a Model so now all we need is the actual operation of getting the weight and it will be inside a Consumer. A special one, a Transformer. So go ahead and make a directory called  <em>transformers/planet</em> in the root of the project. Inside <em>transformers/planet</em> create the file <em>WeightTransformer.py</em> and put the following code in:</p>

<pre><code class="language-python">from models.planet import Planet
from suppliers.planet.PlanetSupplier import PlanetSupplier
from typing import Generator

class WeightTransformer(object):
    class Result(object):
        def __init__(self, newtons: float, planet: Planet):
            self.newtons = newtons
            self.planet = planet
    
        @property
        def pounds(self):
           return self.newtons / 4.4482216

        @property
        def stones(self):
            return self.pounds / 14

        @property
        def kilograms(self):
            return self.newtons / 9.80665

    def __init__(self, supplier: PlanetSupplier, weight: float):
        self.supplier = supplier
        self.weight = weight
        self.G = 6.67408 * 10**-11

    def transform(self) -&gt; Generator[Result, None, None]:
        for planet in self.supplier.supply():
            Fg = self.G * ((planet.mass * self.weight) / (planet.radius ** 2))
            
            yield self.Result(Fg, planet)
</code></pre>

<p>So this will take over the piece of calculating the weights and also give an inner class of Result responsible for calculating the different forms of weight. As you can see another generator is used for the case of large data sets. It loops over all the ones from the Supplier not just one.
Now all we need is to run the program again. The only thing I did not completely take over again was the formatted printing, I am just going to fully print everything. This next code can be placed inside <em>main.py</em> in your root directory.</p>

<pre><code class="language-python">from config import Config
from suppliers import AgnosticSupplier
from transformers.planet.WeightTransformer import WeightTransformer

c = Config()
supplier = AgnosticSupplier(c).get_supplier()
wt = WeightTransformer(supplier, 75)
for result in wt.transform():
    print(result.planet.name, result.kilograms)
</code></pre>

<p>It will print out for every planet in this case. If you just want Mars then you add an if statement.</p>

<p>That is it. We transformed a simple code into a nice structure.</p>

<h2 id="closing-thoughts" id="closing-thoughts">Closing thoughts</h2>

<p>Why this structure? Is this not overkill? This seems complicated for such a simple task. Maybe you are having these questions and thoughts right now. Remember the law you read at the beginning. The value in this structure is that I can add properties to every planet ini file and change the Planet constructor and the rest of the code will still work.</p>

<p>We have single point of entry in the AgnosticSupplier, so again if we change something in the PlanetSupplier overall if it will keep the supply method then no worries. If we want to add more calculations for example we add the property to the planets for distance from Earth then a simple CommunicationTimings class can take the PlanetSupplier and give you back how long it will take for a single message to reach that planet using radio, light or something else to communicate. Your WeightTransformer will still work too.</p>

<p>In the future we discover a new planet and it is only one .ini file away from being included in the code. You know exactly where to put it and it will get picked up. Maybe in the future there won&#39;t be a need for the ini files. Someone gives you a SQLite database file with all the data. You make a DatabaseSupplier and rewrite the PlanetSupplier a bit to get the data from the DatabaseSupplier and make it into Planets.</p>

<p><a href="https://stealthycoder.writeas.com/tag:code" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">code</span></a> <a href="https://stealthycoder.writeas.com/tag:python" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">python</span></a></p>
]]></content:encoded>
      <guid>https://stealthycoder.writeas.com/supply-and-demand</guid>
      <pubDate>Sun, 25 Aug 2019 21:05:35 +0000</pubDate>
    </item>
    <item>
      <title>Supply chains</title>
      <link>https://stealthycoder.writeas.com/supply-chains?pk_campaign=rss-feed</link>
      <description>&lt;![CDATA[So in the previous post I showed how to use the pattern of Suppliers and Consumers to structure any kind of input and output of data and structuring the processing. Well for bonus points we are going to make something fancy, a Chain. A Chain is nothing more than the series of steps that starts with one action and the result of that action will be the input for the next action and so on all the way till the end. Let us make one. !--more--&#xA;&#xA;Chain&#xA;First off let us create a directory to house everything in chains/planet. Inside the chains directory place a \\init\\.py file with the following contents:&#xA;import abc&#xA;from typing import List, Dict, Callable&#xA;&#xA;class SimpleChain(object):&#xA;    class Step(object):&#xA;        def init(self, func: Callable, posargs: List, kwargs: Dict = None):&#xA;            self.func = func&#xA;            self.posargs = posargs&#xA;            self.kwargs = kwargs&#xA;        &#xA;        def execute(self):&#xA;            if len(self.posargs)   0 and self.kwargs is not None:&#xA;                return self.func(self.posargs, self.kwargs)&#xA;            elif len(self.posargs)   0:&#xA;                return self.func(self.posargs)&#xA;            elif self.kwargs is not None:&#xA;                return self.func(self.kwargs)&#xA;            else:&#xA;                return self.func()&#xA;&#xA;    def init(self):&#xA;        self.steps: List[self.Step] = []&#xA;&#xA;    def then(self, func: Callable, posargs: List = [], kwargs: Dict = None):&#xA;        self.steps.append(self.Step(func, posargs, kwargs))&#xA;&#xA;    def execute(self):&#xA;        counter = 0&#xA;        for step in self.steps:&#xA;            if counter == 0:&#xA;                r = step.execute()&#xA;            else:&#xA;                step.posargs = [r] + step.posargs&#xA;                r = step.execute()&#xA;            counter += 1&#xA;            &#xA;        return r&#xA;The SimpleChain class has a method to add steps called then and an execute method that will execute them all. You can return the counter as well to verify all steps have been run. The inner class of Step is there to better manage everything and keep things nice and easy to comprehend. So the logic is that for each step beyond the first one we will add the results of the previous step as the first positional argument. I chose to prepend it rather than append it because we now can use unnamed functions called lambdas where it will always be the first positional argument. &#xA;&#xA;Next up our PlanetWeightChain to see it in action. Create the PlanetWeightChain.py file inside the chains/planet directory with the following contents:&#xA;from chains import SimpleChain&#xA;from config import Config&#xA;from suppliers import AgnosticSupplier&#xA;from transformers.planet.WeightTransformer import WeightTransformer&#xA;&#xA;class PlanetWeightChain(object):&#xA;    def init(self, config: Config, weight: float):&#xA;        self.chain = SimpleChain()&#xA;        self.chain.then(AgnosticSupplier, [config])&#xA;        self.chain.then(lambda x: x.getsupplier())&#xA;        self.chain.then(lambda x, y: WeightTransformer(x, y), [weight])&#xA;        self.chain.then(lambda x: x.transform())&#xA;        self.chain.then(lambda x: PlanetWeightChain.print(x))        &#xA;&#xA;    def execute(self):&#xA;        self.chain.execute()&#xA;&#xA;    @staticmethod&#xA;    def print(results):&#xA;        for result in results:&#xA;            print(result.kilograms, result.planet.name)&#xA;This Chain will first instantiate a SimpleChain and add the steps to it that seem awfully familiar to the main.py of the previous post. We want to pass in functions, but we don&#39;t necessarily want to make named functions for all these steps, therefore we make lambdas. The first positional argument will always be the result of the previous one. So the first step is to create an instance of AgnosticSupplier and that will be given to the second lambda and therefore x is the AgnosticSupplier instance and getsupplier will give us the supplier we need for the next step which is to create a WeightTransformer. &#xA;&#xA;Remember the print at the end does not return anything so a None will be passed along if there were more steps. &#xA;&#xA;Now to make our main.py** slightly different:&#xA;from config import Config&#xA;from chains.planet.PlanetWeightChain import PlanetWeightChain&#xA;&#xA;chain = PlanetWeightChain(Config(), 75)&#xA;chain.execute()&#xA;That is it. We have the full chain. It will automatically print the results at the end, naturally if you don&#39;t want it to print the results you could stop at the transform function and get the results back.&#xA;&#xA;Closing thoughts&#xA;&#xA;I really like this extra system. It seems like an overkill but this makes everything so flexible. You can insert extra steps, take an existing Chain and add or prepend steps to it wherever necessary. This system can make it so we can join the CommunicationTiming and WeightTransformer of previous post as examples into one chain and get the total data back. &#xA;&#xA;#code #python]]&gt;</description>
      <content:encoded><![CDATA[<p>So in the <a href="https://stealthycoder.writeas.com/supply-and-demand" rel="nofollow">previous post</a> I showed how to use the pattern of Suppliers and Consumers to structure any kind of input and output of data and structuring the processing. Well for bonus points we are going to make something fancy, a Chain. A Chain is nothing more than the series of steps that starts with one action and the result of that action will be the input for the next action and so on all the way till the end. Let us make one. </p>

<h2 id="chain" id="chain">Chain</h2>

<p>First off let us create a directory to house everything in <em>chains/planet</em>. Inside the <em>chains</em> directory place a <strong>__init__.py</strong> file with the following contents:</p>

<pre><code class="language-python">import abc
from typing import List, Dict, Callable

class SimpleChain(object):
    class Step(object):
        def __init__(self, func: Callable, pos_args: List, kw_args: Dict = None):
            self.func = func
            self.pos_args = pos_args
            self.kw_args = kw_args
        
        def execute(self):
            if len(self.pos_args) &gt; 0 and self.kw_args is not None:
                return self.func(*self.pos_args, **self.kw_args)
            elif len(self.pos_args) &gt; 0:
                return self.func(*self.pos_args)
            elif self.kw_args is not None:
                return self.func(**self.kw_args)
            else:
                return self.func()


    def __init__(self):
        self.steps: List[self.Step] = []

    def then(self, func: Callable, pos_args: List = [], kw_args: Dict = None):
        self.steps.append(self.Step(func, pos_args, kw_args))

    def execute(self):
        counter = 0
        for step in self.steps:
            if counter == 0:
                r = step.execute()
            else:
                step.pos_args = [r] + step.pos_args
                r = step.execute()
            counter += 1
            
        return r
</code></pre>

<p>The SimpleChain class has a method to add steps called then and an execute method that will execute them all. You can return the counter as well to verify all steps have been run. The inner class of Step is there to better manage everything and keep things nice and easy to comprehend. So the logic is that for each step beyond the first one we will add the results of the previous step as the first positional argument. I chose to prepend it rather than append it because we now can use unnamed functions called lambdas where it will always be the first positional argument.</p>

<p>Next up our PlanetWeightChain to see it in action. Create the <em>PlanetWeightChain.py</em> file inside the <em>chains/planet</em> directory with the following contents:</p>

<pre><code class="language-python">from chains import SimpleChain
from config import Config
from suppliers import AgnosticSupplier
from transformers.planet.WeightTransformer import WeightTransformer

class PlanetWeightChain(object):
    def __init__(self, config: Config, weight: float):
        self.chain = SimpleChain()
        self.chain.then(AgnosticSupplier, [config])
        self.chain.then(lambda x: x.get_supplier())
        self.chain.then(lambda x, y: WeightTransformer(x, y), [weight])
        self.chain.then(lambda x: x.transform())
        self.chain.then(lambda x: PlanetWeightChain.print(x))        

    def execute(self):
        self.chain.execute()

    @staticmethod
    def print(results):
        for result in results:
            print(result.kilograms, result.planet.name)
</code></pre>

<p>This Chain will first instantiate a SimpleChain and add the steps to it that seem awfully familiar to the <strong>main.py</strong> of the previous post. We want to pass in functions, but we don&#39;t necessarily want to make named functions for all these steps, therefore we make lambdas. The first positional argument will always be the result of the previous one. So the first step is to create an instance of AgnosticSupplier and that will be given to the second lambda and therefore x is the AgnosticSupplier instance and get_supplier will give us the supplier we need for the next step which is to create a WeightTransformer.</p>

<p>Remember the print at the end does not return anything so a None will be passed along if there were more steps.</p>

<p>Now to make our <strong>main.py</strong> slightly different:</p>

<pre><code class="language-python">from config import Config
from chains.planet.PlanetWeightChain import PlanetWeightChain

chain = PlanetWeightChain(Config(), 75)
chain.execute()
</code></pre>

<p>That is it. We have the full chain. It will automatically print the results at the end, naturally if you don&#39;t want it to print the results you could stop at the transform function and get the results back.</p>

<h2 id="closing-thoughts" id="closing-thoughts">Closing thoughts</h2>

<p>I really like this extra system. It seems like an overkill but this makes everything so flexible. You can insert extra steps, take an existing Chain and add or prepend steps to it wherever necessary. This system can make it so we can join the CommunicationTiming and WeightTransformer of previous post as examples into one chain and get the total data back.</p>

<p><a href="https://stealthycoder.writeas.com/tag:code" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">code</span></a> <a href="https://stealthycoder.writeas.com/tag:python" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">python</span></a></p>
]]></content:encoded>
      <guid>https://stealthycoder.writeas.com/supply-chains</guid>
      <pubDate>Sun, 25 Aug 2019 22:40:30 +0000</pubDate>
    </item>
    <item>
      <title>Optimizing code - Part 0</title>
      <link>https://stealthycoder.writeas.com/optimizing-code-part-0?pk_campaign=rss-feed</link>
      <description>&lt;![CDATA[This first part will deal with setting up the problem and the first initial code. &#xA;&#xA;Problem&#xA;The problem to solve is to find the first x amount of Narcissistic Numbers . What they are is easy to explain. The process by which to identify if a number is narcissistic is by following these steps: !--more--&#xA;&#xA;Separate number into individual numerals&#xA;Raise each numeral to the power that is equal to the total amount of numerals (length of the number)&#xA;Sum those results together&#xA;If that sum is equal to the original number then it is narcissistic&#xA;&#xA;A quick example is 153 .&#xA;&#xA;Separate numerals are 1, 5 and 3.&#xA;1 \\ 3 = 1, 5 \\ 3 = 125 and 3 \\ 3 = 27&#xA;1 + 125 + 27 = 153&#xA;153 == 153 is true&#xA;&#xA;Therefore 153 is narcissistic. By looking at this algorithm we can see that all numbers with length 1 are narcissistic. Since something to the power of 1 is itself. &#xA;&#xA;Naive code&#xA;The naive implementation is the following: &#xA;import sys&#xA;from datetime import datetime&#xA;&#xA;def isnarcissistic(x: int) -  bool:&#xA;    strx = str(x)&#xA;    s = sum([int(i)  len(strx) for i in strx])&#xA;    return s == x&#xA;&#xA;def findnarcissisticnumbers(desired: int) -  None:&#xA;    for x in range(sys.maxsize):&#xA;        if isnarcissistic(x):&#xA;            desired -= 1&#xA;        if desired == 0:&#xA;            return&#xA;&#xA;start = datetime.utcnow()&#xA;findnarcissisticnumbers(28)&#xA;print(datetime.utcnow() - start)&#xA;&#xA;This code will make the number we are checking into a string and by utilizing Python iterators it will iterate over each character in the string and therefore we have step 1 down. Then in the list comprehension we also raise to the power that is the length of the string (amount of numerals) and we sum it . This is step 2 and 3. Then we check the original with that sum and get step 4. &#xA;&#xA;The total run time for this code on my laptop is : 0:08:09.315972**&#xA;&#xA;Let us look in future parts how we can optimize this code. &#xA;&#xA;#code #python]]&gt;</description>
      <content:encoded><![CDATA[<p>This first part will deal with setting up the problem and the first initial code.</p>

<h2 id="problem" id="problem">Problem</h2>

<p>The problem to solve is to find the first <em>x</em> amount of <a href="https://en.wikipedia.org/wiki/Narcissistic_numbers" rel="nofollow">Narcissistic Numbers</a> . What they are is easy to explain. The process by which to identify if a number is narcissistic is by following these steps: </p>
<ul><li>Separate number into individual numerals</li>
<li>Raise each numeral to the power that is equal to the total amount of numerals (length of the number)</li>
<li>Sum those results together</li>
<li>If that sum is equal to the original number then it is narcissistic</li></ul>

<p>A quick example is <strong>153</strong> .</p>
<ol><li>Separate numerals are <strong>1</strong>, <strong>5</strong> and <strong>3</strong>.</li>
<li>1 ** 3 = 1, 5 ** 3 = 125 and 3 ** 3 = 27</li>
<li>1 + 125 + 27 = 153</li>
<li>153 == 153 is true</li></ol>

<p>Therefore <strong>153</strong> is narcissistic. By looking at this <em>algorithm</em> we can see that all numbers with length <em>1</em> are narcissistic. Since something to the power of 1 is itself.</p>

<h2 id="naive-code" id="naive-code">Naive code</h2>

<p>The naive implementation is the following:</p>

<pre><code class="language-python">import sys
from datetime import datetime

def is_narcissistic(x: int) -&gt; bool:
    str_x = str(x)
    s = sum([int(i) ** len(str_x) for i in str_x])
    return s == x

def find_narcissistic_numbers(desired: int) -&gt; None:
    for x in range(sys.maxsize):
        if is_narcissistic(x):
            desired -= 1
        if desired == 0:
            return

start = datetime.utcnow()
find_narcissistic_numbers(28)
print(datetime.utcnow() - start)
</code></pre>

<p>This code will make the number we are checking into a string and by utilizing Python iterators it will iterate over each character in the string and therefore we have step 1 down. Then in the list comprehension we also raise to the power that is the length of the string (amount of numerals) and we sum it . This is step 2 and 3. Then we check the original with that sum and get step 4.</p>

<p>The total run time for this code on my laptop is : <strong>0:08:09.315972</strong></p>

<p>Let us look in future parts how we can optimize this code.</p>

<p><a href="https://stealthycoder.writeas.com/tag:code" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">code</span></a> <a href="https://stealthycoder.writeas.com/tag:python" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">python</span></a></p>
]]></content:encoded>
      <guid>https://stealthycoder.writeas.com/optimizing-code-part-0</guid>
      <pubDate>Sun, 06 Oct 2019 13:43:43 +0000</pubDate>
    </item>
    <item>
      <title>Optimizing code – Part 1</title>
      <link>https://stealthycoder.writeas.com/optimizing-code-part-1?pk_campaign=rss-feed</link>
      <description>&lt;![CDATA[The first improvement we will make is to move away from int to string to int conversion in the previous code and implement integer only operations. We can do this by using the modulo and floor integer division. !--more--&#xA;&#xA;Modulo&#xA;&#xA;The modulo % operator gives you when dealing with whole base 10 (decimal) numbers, in other words the Natural numbers ( non-negative integers), the digit on the most right. The operation a mod b or a % b means divide a with b and whatever remains return that value. &#xA;&#xA;Examples:&#xA;15 % 10 = 5&#xA;124 % 10 = 4&#xA;40 % 10 = 0&#xA;&#xA;Floor integer&#xA;&#xA;Floor integer division given a and b is divide a with b and round that result off down to the nearest whole number or integer. &#xA;&#xA;Examples:&#xA;15 // 10 = 1&#xA;143 // 10 = 14&#xA;456 // 10 = 45&#xA;&#xA;As might see, by using modulo we get the last digit and with floor integer we chop that number off so we can move through the numbers from right to left. &#xA;&#xA;import sys&#xA;from datetime import datetime&#xA;&#xA;def isnarcissistic(x: int) -  bool:&#xA;    org = x&#xA;    digits = []&#xA;    while x   0:&#xA;        , x = digits.append(x % 10), x // 10&#xA;&#xA;    s = sum([i  len(digits) for i in digits])&#xA;    return s == org&#xA;&#xA;def findnarcissisticnumbers(desired: int) -  None:&#xA;    for x in range(sys.maxsize):&#xA;        if isnarcissistic(x):&#xA;            desired -= 1&#xA;        if desired == 0:&#xA;            return&#xA;&#xA;start = datetime.utcnow()&#xA;findnarcissistic_numbers(28)&#xA;print(datetime.utcnow() - start)&#xA;&#xA;The time for this code on my laptop is: 0:07:53.349431**&#xA;&#xA;#code #python]]&gt;</description>
      <content:encoded><![CDATA[<p>The first improvement we will make is to move away from int to string to int conversion in the previous code and implement integer only operations. We can do this by using the <em>modulo</em> and <em>floor integer</em> division. </p>

<h2 id="modulo" id="modulo">Modulo</h2>

<p>The modulo <strong>%</strong> operator gives you when dealing with whole base 10 (decimal) numbers, in other words the Natural numbers ( non-negative integers), the digit on the most right. The operation <em>a mod b</em> or <em>a % b</em> means divide <strong>a</strong> with <strong>b</strong> and whatever remains return that value.</p>

<p>Examples:
– 15 % 10 = 5
– 124 % 10 = 4
– 40 % 10 = 0</p>

<h2 id="floor-integer" id="floor-integer">Floor integer</h2>

<p>Floor integer division given <em>a</em> and <em>b</em> is divide <em>a</em> with <em>b</em> and round that result off down to the nearest whole number or integer.</p>

<p>Examples:
– 15 // 10 = 1
– 143 // 10 = 14
– 456 // 10 = 45</p>

<p>As might see, by using modulo we get the last digit and with floor integer we chop that number off so we can move through the numbers from right to left.</p>

<pre><code class="language-python">import sys
from datetime import datetime

def is_narcissistic(x: int) -&gt; bool:
    org = x
    digits = []
    while x &gt; 0:
        _, x = digits.append(x % 10), x // 10

    s = sum([i ** len(digits) for i in digits])
    return s == org

def find_narcissistic_numbers(desired: int) -&gt; None:
    for x in range(sys.maxsize):
        if is_narcissistic(x):
            desired -= 1
        if desired == 0:
            return

start = datetime.utcnow()
find_narcissistic_numbers(28)
print(datetime.utcnow() - start)
</code></pre>

<p>The time for this code on my laptop is: <strong>0:07:53.349431</strong></p>

<p><a href="https://stealthycoder.writeas.com/tag:code" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">code</span></a> <a href="https://stealthycoder.writeas.com/tag:python" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">python</span></a></p>
]]></content:encoded>
      <guid>https://stealthycoder.writeas.com/optimizing-code-part-1</guid>
      <pubDate>Sun, 06 Oct 2019 13:57:36 +0000</pubDate>
    </item>
    <item>
      <title>Optimizing code - Part 2</title>
      <link>https://stealthycoder.writeas.com/optimizing-code-part-2?pk_campaign=rss-feed</link>
      <description>&lt;![CDATA[A small mini optimization is to move the call to len out as the length of the number does not change.  !--more--&#xA;&#xA;import sys&#xA;from datetime import datetime&#xA;&#xA;def isnarcissistic(x: int) -  bool:&#xA;    org = x&#xA;    digits = []&#xA;    while x   0:&#xA;        , x = digits.append(x % 10), x // 10&#xA;    power = len(digits)&#xA;    s = sum([i  power for i in digits])&#xA;    return s == org&#xA;&#xA;def findnarcissisticnumbers(desired: int) -  None:&#xA;    for x in range(sys.maxsize):&#xA;        if isnarcissistic(x):&#xA;            desired -= 1&#xA;        if desired == 0:&#xA;            return&#xA;&#xA;start = datetime.utcnow()&#xA;findnarcissistic_numbers(28)&#xA;print(datetime.utcnow() - start)&#xA;The time for this code to run on my laptop is: 0:07:14.172538**&#xA;&#xA;#code #python]]&gt;</description>
      <content:encoded><![CDATA[<p>A small mini optimization is to move the call to <em>len</em> out as the length of the number does not change.  </p>

<pre><code class="language-python">import sys
from datetime import datetime

def is_narcissistic(x: int) -&gt; bool:
    org = x
    digits = []
    while x &gt; 0:
        _, x = digits.append(x % 10), x // 10
    power = len(digits)
    s = sum([i ** power for i in digits])
    return s == org

def find_narcissistic_numbers(desired: int) -&gt; None:
    for x in range(sys.maxsize):
        if is_narcissistic(x):
            desired -= 1
        if desired == 0:
            return

start = datetime.utcnow()
find_narcissistic_numbers(28)
print(datetime.utcnow() - start)
</code></pre>

<p>The time for this code to run on my laptop is: <strong>0:07:14.172538</strong></p>

<p><a href="https://stealthycoder.writeas.com/tag:code" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">code</span></a> <a href="https://stealthycoder.writeas.com/tag:python" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">python</span></a></p>
]]></content:encoded>
      <guid>https://stealthycoder.writeas.com/optimizing-code-part-2</guid>
      <pubDate>Sun, 06 Oct 2019 14:00:22 +0000</pubDate>
    </item>
    <item>
      <title>Optimizing code – Part 3</title>
      <link>https://stealthycoder.writeas.com/optimizing-code-part-3?pk_campaign=rss-feed</link>
      <description>&lt;![CDATA[The next thing we can optimize is the fact that the result of the powers calculation does not change during the same length of the numbers. In order words, *3 \\  3 does not change for the numbers 123, 345, 543 and any other number containing a 3 in the range of 100 - 999.  !--more--&#xA;&#xA;So we make a lookup table and put all the powers in there in a nice way. If the position is the same as the value contained within then it is really easy to calculate the next power. It is just multiply the value by the index it is located at. This process is called memoization. It is when you store or cache the results of expensive calculations and just look them up the next time you need them.&#xA;&#xA;import sys&#xA;from datetime import datetime&#xA;&#xA;POWERS = [0,1,2,3,4,5,6,7,8,9]&#xA;LENGTH = 1&#xA;&#xA;def recalculatepowers() -  None:&#xA;    global POWERS&#xA;    for i,v in enumerate(POWERS):&#xA;        POWERS[i] = i  v&#xA;&#xA;def isnarcissistic(x: int) -  bool:&#xA;    global LENGTH, POWERS&#xA;    org = x&#xA;    digits = []&#xA;    total = 0&#xA;    while x   0:&#xA;        , x = digits.append(x % 10), x // 10&#xA;    curlength = len(digits)&#xA;    if curlength != LENGTH:&#xA;        LENGTH = curlength&#xA;        recalculatepowers()&#xA;    for i in digits:&#xA;        total += POWERS[i]&#xA;    return total == org&#xA;&#xA;def findnarcissisticnumbers(desired: int) -  None:&#xA;    for x in range(1,sys.maxsize):&#xA;        if isnarcissistic(x):&#xA;            desired -= 1&#xA;        if desired == 0:&#xA;            return&#xA;&#xA;start = datetime.utcnow()&#xA;findnarcissisticnumbers(28)&#xA;print(datetime.utcnow() - start)&#xA;&#xA;The time for this code to run on my laptop: 0:06:23.868587&#xA;&#xA;#code #python]]&gt;</description>
      <content:encoded><![CDATA[<p>The next thing we can optimize is the fact that the result of the powers calculation does not change during the same length of the numbers. In order words, <strong>3 **  3</strong> does not change for the numbers <em>123</em>, <em>345</em>, <em>543</em> and any other number containing a <strong>3</strong> in the range of <em>100 – 999</em>.  </p>

<p>So we make a lookup table and put all the powers in there in a nice way. If the position is the same as the value contained within then it is really easy to calculate the next power. It is just multiply the value by the index it is located at. This process is called <em>memoization</em>. It is when you store or <em>cache</em> the results of expensive calculations and just look them up the next time you need them.</p>

<pre><code class="language-python">import sys
from datetime import datetime

POWERS = [0,1,2,3,4,5,6,7,8,9]
LENGTH = 1

def recalculate_powers() -&gt; None:
    global POWERS
    for i,v in enumerate(POWERS):
        POWERS[i] = i * v

def is_narcissistic(x: int) -&gt; bool:
    global LENGTH, POWERS
    org = x
    digits = []
    total = 0
    while x &gt; 0:
        _, x = digits.append(x % 10), x // 10
    cur_length = len(digits)
    if cur_length != LENGTH:
        LENGTH = cur_length
        recalculate_powers()
    for i in digits:
        total += POWERS[i]
    return total == org

def find_narcissistic_numbers(desired: int) -&gt; None:
    for x in range(1,sys.maxsize):
        if is_narcissistic(x):
            desired -= 1
        if desired == 0:
            return

start = datetime.utcnow()
find_narcissistic_numbers(28)
print(datetime.utcnow() - start)
</code></pre>

<p>The time for this code to run on my laptop: <strong>0:06:23.868587</strong></p>

<p><a href="https://stealthycoder.writeas.com/tag:code" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">code</span></a> <a href="https://stealthycoder.writeas.com/tag:python" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">python</span></a></p>
]]></content:encoded>
      <guid>https://stealthycoder.writeas.com/optimizing-code-part-3</guid>
      <pubDate>Sun, 06 Oct 2019 14:02:18 +0000</pubDate>
    </item>
    <item>
      <title>Optimizing code – Part 4</title>
      <link>https://stealthycoder.writeas.com/optimizing-code-part-4?pk_campaign=rss-feed</link>
      <description>&lt;![CDATA[The next mini optimization we can do is to bail out earlier because when summing the number and we overshoot the original then we can stop immediately. For example *9 \\ 6 is a big number and so with bigger numbers it makes sense to bail out earlier. !--more--&#xA;&#xA;import sys&#xA;from datetime import datetime&#xA;&#xA;POWERS = [0,1,2,3,4,5,6,7,8,9]&#xA;LENGTH = 1&#xA;&#xA;def recalculatepowers() -  None:&#xA;    global POWERS&#xA;    for i,v in enumerate(POWERS):&#xA;        POWERS[i] = i  v&#xA;&#xA;def isnarcissistic(x: int) -  bool:&#xA;    global LENGTH, POWERS&#xA;    org = x&#xA;    digits = []&#xA;    total = 0&#xA;    while x   0:&#xA;        , x = digits.append(x % 10), x // 10&#xA;    curlength = len(digits)&#xA;    if curlength != LENGTH:&#xA;        LENGTH = curlength&#xA;        recalculatepowers()&#xA;    for i in digits:&#xA;        total += POWERS[i]&#xA;        if total   org:&#xA;            return False&#xA;    return total == org&#xA;&#xA;def findnarcissisticnumbers(desired: int) -  None:&#xA;    for x in range(1,sys.maxsize):&#xA;        if isnarcissistic(x):&#xA;            desired -= 1&#xA;        if desired == 0:&#xA;            return&#xA;&#xA;start = datetime.utcnow()&#xA;findnarcissisticnumbers(28)&#xA;print(datetime.utcnow() - start)&#xA;The time for this code to run on my laptop is: 0:06:21.202479&#xA;&#xA;To compare this to the original run of the naive implementation is, which was 0:08:09.315972. Even on my slow hardware, it still resulted in a speed up of about 25%. &#xA;&#xA;#code #python]]&gt;</description>
      <content:encoded><![CDATA[<p>The next mini optimization we can do is to bail out earlier because when summing the number and we overshoot the original then we can stop immediately. For example <strong>9 ** 6</strong> is a big number and so with bigger numbers it makes sense to bail out earlier. </p>

<pre><code class="language-python">import sys
from datetime import datetime

POWERS = [0,1,2,3,4,5,6,7,8,9]
LENGTH = 1

def recalculate_powers() -&gt; None:
    global POWERS
    for i,v in enumerate(POWERS):
        POWERS[i] = i * v

def is_narcissistic(x: int) -&gt; bool:
    global LENGTH, POWERS
    org = x
    digits = []
    total = 0
    while x &gt; 0:
        _, x = digits.append(x % 10), x // 10
    cur_length = len(digits)
    if cur_length != LENGTH:
        LENGTH = cur_length
        recalculate_powers()
    for i in digits:
        total += POWERS[i]
        if total &gt; org:
            return False
    return total == org

def find_narcissistic_numbers(desired: int) -&gt; None:
    for x in range(1,sys.maxsize):
        if is_narcissistic(x):
            desired -= 1
        if desired == 0:
            return

start = datetime.utcnow()
find_narcissistic_numbers(28)
print(datetime.utcnow() - start)
</code></pre>

<p>The time for this code to run on my laptop is: <strong>0:06:21.202479</strong></p>

<p>To compare this to the original run of the naive implementation is, which was <strong>0:08:09.315972</strong>. Even on my slow hardware, it still resulted in a speed up of about <strong>25%</strong>.</p>

<p><a href="https://stealthycoder.writeas.com/tag:code" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">code</span></a> <a href="https://stealthycoder.writeas.com/tag:python" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">python</span></a></p>
]]></content:encoded>
      <guid>https://stealthycoder.writeas.com/optimizing-code-part-4</guid>
      <pubDate>Sun, 06 Oct 2019 14:10:18 +0000</pubDate>
    </item>
    <item>
      <title>Optimizing code - Part 5</title>
      <link>https://stealthycoder.writeas.com/optimizing-code-part-5?pk_campaign=rss-feed</link>
      <description>&lt;![CDATA[So for the smart people out there they might have already figured out that the result for 153 is the same as for 135,315,351,513 and 531. This means that we can calculate the result for all of those once and just check if the result of that calculation is in that list. Which is the case for the number 153.  !--more--&#xA;&#xA;Online Encyclopedia Integer Sequences&#xA;&#xA;There exists an online database of integer sequences. It has a lot of cool sequences and one of them is the one with all Narcissistic Numbers. It has number A005188 and you can find it here.&#xA;&#xA;This next code is inspired and based on the code in the OEIS. &#xA;&#xA;Code&#xA;&#xA;from itertools import combinationswithreplacement&#xA;from datetime import datetime&#xA;import sys&#xA;&#xA;POWERS = [0,1,2,3,4,5,6,7,8,9]&#xA;NARCISSISTICNUMBERS = []&#xA;&#xA;def recalculatepowers():&#xA;    for i,v in enumerate(POWERS):&#xA;        POWERS[i] = i * v&#xA;&#xA;def equals(number: int, target: tuple) -  bool:&#xA;    digits = []&#xA;    while number   0:&#xA;        , number = digits.append(number % 10), number // 10&#xA;    return tuple(sorted(digits)) == target&#xA;&#xA;def findnarcissisticnumbers(desired: int) -  None:&#xA;    global POWERS, NARCISSISTICNUMBERS&#xA;    for k in range(1, sys.maxsize):&#xA;&#xA;        for b in combinationswithreplacement(range(10), k):&#xA;&#xA;            x = sum(map(lambda y:POWERS[y], b))&#xA;            if x   0 and equals(x, b):&#xA;                NARCISSISTICNUMBERS.append(x)&#xA;                if len(NARCISSISTICNUMBERS) == desired:&#xA;                    return&#xA;        recalculatepowers()&#xA;&#xA;start = datetime.utcnow()&#xA;findnarcissisticnumbers(28)&#xA;print(datetime.utcnow() - start)&#xA;&#xA;The combinations\with\_replacement gets numbers 0-9 and how many times to do it. So for example when k = 2 you get:&#xA;&#xA;[0,0]&#xA;[0,1]&#xA;...&#xA;[1,1]&#xA;...&#xA;[2,2]&#xA;...&#xA;[9,9]&#xA;&#xA;And as you can see you lose one number every time you go up in tens. As 0,1 is equal to 1,0 and 1,2 is equal to 2,1. There are considerable amount of fewer computations to check. &#xA;&#xA;So this code takes this much time to run on my laptop: 0:00:00.204806&#xA;&#xA;That is an insane speedup in time compared to the naive implementation and the optimized implementation. &#xA;&#xA;Caveat&#xA;&#xA;Small thing I found out whilst running this code. I thought it was enough to do sorted((2,1)) but this returns a list!!. So then I needed to wrap that with another tuple or the other one with list and I did not want to do that. So therefore I went with the initial list and turn that into a tuple. &#xA;&#xA;#code #python]]&gt;</description>
      <content:encoded><![CDATA[<p>So for the smart people out there they might have already figured out that the result for <strong>153</strong> is the same as for <strong>135,315,351,513 and 531</strong>. This means that we can calculate the result for all of those once and just check if the result of that calculation is in that list. Which is the case for the number <strong>153</strong>.  </p>

<h2 id="online-encyclopedia-integer-sequences" id="online-encyclopedia-integer-sequences">Online Encyclopedia Integer Sequences</h2>

<p>There exists an online database of integer sequences. It has a lot of cool sequences and one of them is the one with all Narcissistic Numbers. It has number A005188 and you can find it <a href="https://oeis.org/A005188" rel="nofollow">here</a>.</p>

<p>This next code is inspired and based on the code in the OEIS.</p>

<h2 id="code" id="code">Code</h2>

<pre><code class="language-python">from itertools import combinations_with_replacement
from datetime import datetime
import sys

POWERS = [0,1,2,3,4,5,6,7,8,9]
NARCISSISTIC_NUMBERS = []

def recalculate_powers():
    for i,v in enumerate(POWERS):
        POWERS[i] = i * v

def equals(number: int, target: tuple) -&gt; bool:
    digits = []
    while number &gt; 0:
        _, number = digits.append(number % 10), number // 10
    return tuple(sorted(digits)) == target



def find_narcissistic_numbers(desired: int) -&gt; None:
    global POWERS, NARCISSISTIC_NUMBERS
    for k in range(1, sys.maxsize):

        for b in combinations_with_replacement(range(10), k):

            x = sum(map(lambda y:POWERS[y], b))
            if x &gt; 0 and equals(x, b):
                NARCISSISTIC_NUMBERS.append(x)
                if len(NARCISSISTIC_NUMBERS) == desired:
                    return
        recalculate_powers()

start = datetime.utcnow()
find_narcissistic_numbers(28)
print(datetime.utcnow() - start)
</code></pre>

<p>The combinations_with_replacement gets numbers 0-9 and how many times to do it. So for example when k = 2 you get:</p>

<p>[0,0]
[0,1]
...
[1,1]
...
[2,2]
...
[9,9]</p>

<p>And as you can see you lose one number every time you go up in tens. As 0,1 is equal to 1,0 and 1,2 is equal to 2,1. There are considerable amount of fewer computations to check.</p>

<p>So this code takes this much time to run on my laptop: <strong>0:00:00.204806</strong></p>

<p>That is an insane speedup in time compared to the naive implementation and the optimized implementation.</p>

<h4 id="caveat" id="caveat">Caveat</h4>

<p>Small thing I found out whilst running this code. I thought it was enough to do <strong>sorted((2,1))</strong> but this returns a <strong>list!!</strong>. So then I needed to wrap that with another <strong>tuple</strong> or the other one with <strong>list</strong> and I did not want to do that. So therefore I went with the initial list and turn that into a tuple.</p>

<p><a href="https://stealthycoder.writeas.com/tag:code" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">code</span></a> <a href="https://stealthycoder.writeas.com/tag:python" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">python</span></a></p>
]]></content:encoded>
      <guid>https://stealthycoder.writeas.com/optimizing-code-part-5</guid>
      <pubDate>Sun, 06 Oct 2019 14:21:21 +0000</pubDate>
    </item>
    <item>
      <title>How to transport a snake?</title>
      <link>https://stealthycoder.writeas.com/how-to-transport-a-snake?pk_campaign=rss-feed</link>
      <description>&lt;![CDATA[So we all know planes are not a good idea. Before you know it you have Samuel L. Jackson shouting in your ear.&#xA;&#xA;So maybe we need a few new ideas. !--more--&#xA;&#xA;Point of view&#xA;&#xA;As most quasi intellectuals who want to sound philosophical like to say; It all depends on your point of view. However, in this case I want to make for how to ship Python applications, I want to make sure you embody the different individuals who partake in the process of shipping it or deploying it if you want to be technical. One is the developer who writes the source code, the other is the DevOps engineer tasked with deploying it wherever it is needed. &#xA;&#xA;Ecosystem&#xA;&#xA;The ecosystem for Python applications is great if you are the developer that just has to write the source code to make it work. You activate a virtual environment using any tool that has  your preference. You install the necessary libraries outside of the standard library that you need. You write the code until it all works. Job done.&#xA;&#xA;The ecosystem for deploying it sucks. Either you use the same flow as the developer but that is not the context and  environment of the DevOps engineer. You really wanted to use the packages from the package managers of the Operating System you deploying it to. You cannot however because the same versions do not sync up. So you have to choose.&#xA;&#xA;Either Or&#xA;&#xA;Either you use the developer tools and flows for the duration of deploying and your Continuous Integration process. Or you use the system packages to pre-built docker images where you run your code and development process. It is either or. There is a big discrepancy between the developer context and the deployment context, or if you will the end user. &#xA;&#xA;Let us assume you made something and you want other people to run it too. How do you get your Python application to the end user? You might get away with making a self running archive. Though one thing needs to be there and that is the C libraries on the host machine. So you cannot get away with prepping the host machine environment. &#xA;&#xA;The one solution is to statically compile everything and not dynamically link it. This means a lot of management done by developers or DevOps engineers themselves. It would solve the problem though that you can ship your archive and anyone else can just run it. Not a feasible thing to accomplish as it introduces a lot of unneeded complexity. &#xA;&#xA;Two layers &#xA;&#xA;There also exists the possibility of having the self running archive and then also putting it inside a docker image. These two layers can have two independent running pipelines. One to produce the archive and one that produces the image. Now you can update the runtime without changing the source code and run the risk of introducing anomalies. You take the archive out and you update the Python runtime and reinstate the archive and run it. &#xA;&#xA;It gives you more fine grained control if that is needed. &#xA;&#xA;#devops #python]]&gt;</description>
      <content:encoded><![CDATA[<p>So we all know <a href="https://www.imdb.com/title/tt0417148/" rel="nofollow">planes</a> are not a good idea. Before you know it you have Samuel L. Jackson shouting in your ear.</p>

<p>So maybe we need a few new ideas. </p>

<h2 id="point-of-view" id="point-of-view">Point of view</h2>

<p>As most quasi intellectuals who want to sound philosophical like to say; It all depends on your point of view. However, in this case I want to make for how to ship Python applications, I want to make sure you embody the different individuals who partake in the process of shipping it or deploying it if you want to be technical. One is the developer who writes the source code, the other is the DevOps engineer tasked with deploying it wherever it is needed.</p>

<h2 id="ecosystem" id="ecosystem">Ecosystem</h2>

<p>The ecosystem for Python applications is great if you are the developer that just has to write the source code to make it work. You activate a virtual environment using any tool that has  your preference. You install the necessary libraries outside of the standard library that you need. You write the code until it all works. Job done.</p>

<p>The ecosystem for deploying it sucks. Either you use the same flow as the developer but that is not the context and  environment of the DevOps engineer. You really wanted to use the packages from the package managers of the Operating System you deploying it to. You cannot however because the same versions do not sync up. So you have to choose.</p>

<h2 id="either-or" id="either-or">Either Or</h2>

<p>Either you use the developer tools and flows for the duration of deploying and your Continuous Integration process. Or you use the system packages to pre-built docker images where you run your code and development process. It is either or. There is a big discrepancy between the developer context and the deployment context, or if you will the end user.</p>

<p>Let us assume you made something and you want other people to run it too. How do you get your Python application to the end user? You might get away with making a <a href="https://www.python.org/dev/peps/pep-0441/" rel="nofollow">self running archive</a>. Though one thing needs to be there and that is the C libraries on the host machine. So you cannot get away with prepping the host machine environment.</p>

<p>The one solution is to statically compile everything and not dynamically link it. This means a lot of management done by developers or DevOps engineers themselves. It would solve the problem though that you can ship your archive and anyone else can just run it. Not a feasible thing to accomplish as it introduces a lot of unneeded complexity.</p>

<h2 id="two-layers" id="two-layers">Two layers</h2>

<p>There also exists the possibility of having the self running archive and then also putting it inside a docker image. These two layers can have two independent running pipelines. One to produce the archive and one that produces the image. Now you can update the runtime without changing the source code and run the risk of introducing anomalies. You take the archive out and you update the Python runtime and reinstate the archive and run it.</p>

<p>It gives you more fine grained control if that is needed.</p>

<p><a href="https://stealthycoder.writeas.com/tag:devops" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">devops</span></a> <a href="https://stealthycoder.writeas.com/tag:python" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">python</span></a></p>
]]></content:encoded>
      <guid>https://stealthycoder.writeas.com/how-to-transport-a-snake</guid>
      <pubDate>Mon, 24 Feb 2020 10:28:33 +0000</pubDate>
    </item>
    <item>
      <title>Decoration patterns</title>
      <link>https://stealthycoder.writeas.com/decoration-patterns?pk_campaign=rss-feed</link>
      <description>&lt;![CDATA[So this post touches on some Python concepts in async/await territory. I will not cover event loops nor how to interact with them, but something I uncovered/unearthed in a quest to make something work that was synchronous only. I will use the word async which itself is a shortening of the word asynchronous. !--more--&#xA;&#xA;First things first, the async structure in essence means a form of cooperative multi-threading. This is in contrast with preemptive multi-threading. The latter means there will be scheduled allotted CPU cycles where for example a function needs 3 cycles, but gets 2 at a time over the course of all work that needs to be done can actually take 6 cycles. &#xA;&#xA;In cooperative model the function gets to take as many cycles with regards to the CPU scheduler though and then hand back control after 3 and hopefully that means in this case the cycles are used in a more direct and efficient way making the program smoother and more efficient.&#xA;&#xA;  As a side note, async should only be used as you expect to be I/O bound and also it should be used completely throughout the application and third party libraries. &#xA;&#xA;So this also means it will be running in the background whatever this function is you wanted to make async, and therefore the keyword await was introduced stating you should await the function for when it is done. &#xA;&#xA;Getting started&#xA;&#xA;First something simple.&#xA;&#xA;def f():&#xA;    pass&#xA;A simple function definition. If we wanted an async function we would do the following:&#xA;&#xA;async def a():&#xA;    pass&#xA;So far only the only difference, other than the name, is the keyword async. So what happens when you print these defined symbols.&#xA;&#xA;print(f) # function f at 0x7fa7b50af1f0&#xA;print(a) # function a at 0x7fa7b4fb9ca0&#xA;So nothing apparently. They are both just function definitions. What happens when you print the result of executing the functions?&#xA;&#xA;print(f()) # None&#xA;print(a()) # coroutine object a at 0x7fa7b5037940&#xA;You will also get a RuntimeWarning of a coroutine not being awaited. We leave that for what it is right now. So interestingly we see they are both functions before and after the execution the one has a result, the other a coroutine object. So we want to see if there is a way to determine if the function is a coroutine aforehand. &#xA;&#xA;Let us write something that does that:&#xA;import inspect&#xA;&#xA;print(inspect.iscoroutine(a)) # False&#xA;print(inspect.isawaitable(a)) # False&#xA;&#xA;print(inspect.iscoroutine(a())) # True&#xA;print(inspect.isawaitable(a())) # True&#xA;Hang on, they both state False when operating on the definition. However our RuntimeWarning said we needed to await. When we execute the function we do get the information, but that is still after the fact. &#xA;&#xA;We first have to execute a function in order to find out we need to await.  There might be some people out there right now that go well you used a wrong method. There will be two solutions at the end. &#xA;&#xA;Decorators&#xA;&#xA;In Python there exists the following syntactic sugar:&#xA;&#xA;def decorator(func):&#xA;    def wrapper():&#xA;       func()&#xA;    return wrapper&#xA;&#xA;@decorator&#xA;async def a():&#xA;     pass&#xA;&#xA;a()&#xA;&#xA;This is the same as doing a = decorator(a) and then calling a() will actually execute the wrapper, as a will be now equal to wrapper. &#xA;&#xA;First problem we run into in this example is we gave an async function to a non-async function. You can only await in async functions. That is easily solved:&#xA;&#xA;def decorator(func):&#xA;    async def wrapper():&#xA;       await func()&#xA;    return wrapper&#xA;&#xA;Now the wrapper is also async and we await the function inside. However this decorator might be used for async and non-async functions alike. We still need to determine accurately whether or not a function is async aforehand. &#xA;&#xA;Internals&#xA;&#xA;Looking at the internals of Python there exists the code property on functions. Inside that property there is a coflags property. That will actually hold a bitmap value of what flags the function itself holds. You can get at this information in the following way:&#xA;&#xA;from dis import prettyflags&#xA;&#xA;def f():&#xA;    pass&#xA;&#xA;async def a():&#xA;    pass&#xA;&#xA;print(prettyflags(f.code.coflags)) # OPTIMIZED, NEWLOCALS, NOFREE&#xA;print(prettyflags(a.code.coflags)) # OPTIMIZED, NEWLOCALS, NOFREE, COROUTINE&#xA;&#xA;Aha, we see now that we can determine if a function is a coroutine or not.  This means we can make our decorator correctly now:&#xA;&#xA;from dis import prettyflags&#xA;&#xA;def decorator(func):&#xA;    def wrapper():&#xA;        func()&#xA;    async def asyncwrapper():&#xA;        await func()&#xA;    &#xA;    if &#34;COROUTINE&#34; in prettyflags(func.code.coflags):&#xA;        return asyncwrapper&#xA;    &#xA;    return wrapper&#xA;&#xA;Final Solution&#xA;&#xA;I already mentioned there are two solution. I first wanted to get this internal solution out the way as that is the one I used first. Then I ran into something that made more sense. So the before mentioned decorator can also be written thusly:&#xA;&#xA;import inspect&#xA;&#xA;def decorator(func):&#xA;    def wrapper():&#xA;        func()&#xA;    async def asyncwrapper():&#xA;        await func()&#xA;    &#xA;    if inspect.iscoroutinefunction(func):&#xA;        return asyncwrapper&#xA;    &#xA;    return wrapper&#xA;&#xA;The importance of using the correct method is abundantly clear in this case. Our definition is a coroutine function, not yet a coroutine and therefor you also cannot await a definition. Only an instance of the executed async function.&#xA;&#xA;Hope this helps out a bit in the future of your async python adventure.&#xA;&#xA;As a final final example the decorator should probably look like this:&#xA;&#xA;import inspect&#xA;&#xA;def decorator(func):&#xA;    def wrapper(args, kwargs):&#xA;        func(args, *kwargs)&#xA;    async def asyncwrapper(args, *kwargs):&#xA;        await func(args, **kwargs)&#xA;    &#xA;    if inspect.iscoroutinefunction(func):&#xA;        return async_wrapper&#xA;    &#xA;    return wrapper&#xA;&#xA;In order to propagate any and all arguments given to the function you are decorating. &#xA;&#xA;#code #python]]&gt;</description>
      <content:encoded><![CDATA[<p>So this post touches on some Python concepts in async/await territory. I will not cover event loops nor how to interact with them, but something I uncovered/unearthed in a quest to make something work that was synchronous only. I will use the word <code>async</code> which itself is a shortening of the word asynchronous. </p>

<p>First things first, the async structure in essence means a form of cooperative multi-threading. This is in contrast with preemptive multi-threading. The latter means there will be scheduled allotted CPU cycles where for example a function needs 3 cycles, but gets 2 at a time over the course of all work that needs to be done can actually take 6 cycles.</p>

<p>In cooperative model the function gets to take as many cycles with regards to the CPU scheduler though and then hand back control after 3 and hopefully that means in this case the cycles are used in a more direct and efficient way making the program smoother and more efficient.</p>

<blockquote><p>As a side note, async should only be used as you expect to be I/O bound and also it should be used completely throughout the application and third party libraries.</p></blockquote>

<p>So this also means it will be running in the background whatever this function is you wanted to make async, and therefore the keyword <code>await</code> was introduced stating you should await the function for when it is done.</p>

<h1 id="getting-started" id="getting-started">Getting started</h1>

<p>First something simple.</p>

<pre><code class="language-python">
def f():
    pass
</code></pre>

<p>A simple function definition. If we wanted an async function we would do the following:</p>

<pre><code class="language-python">
async def a():
    pass
</code></pre>

<p>So far only the only difference, other than the name, is the keyword async. So what happens when you print these defined symbols.</p>

<pre><code class="language-python">print(f) # &lt;function f at 0x7fa7b50af1f0&gt;
print(a) # &lt;function a at 0x7fa7b4fb9ca0&gt;
</code></pre>

<p>So nothing apparently. They are both just function definitions. What happens when you print the result of executing the functions?</p>

<pre><code class="language-python">print(f()) # None
print(a()) # &lt;coroutine object a at 0x7fa7b5037940&gt;
</code></pre>

<p>You will also get a RuntimeWarning of a coroutine not being awaited. We leave that for what it is right now. So interestingly we see they are both functions before and after the execution the one has a result, the other a coroutine object. So we want to see if there is a way to determine if the function is a coroutine aforehand.</p>

<p>Let us write something that does that:</p>

<pre><code class="language-python">import inspect

print(inspect.iscoroutine(a)) # False
print(inspect.isawaitable(a)) # False

print(inspect.iscoroutine(a())) # True
print(inspect.isawaitable(a())) # True
</code></pre>

<p>Hang on, they both state <code>False</code> when operating on the definition. However our RuntimeWarning said we needed to <code>await</code>. When we execute the function we do get the information, but that is still after the fact.</p>

<p>We first have to execute a function in order to find out we need to <code>await</code>.  There might be some people out there right now that go well you used a wrong method. There will be two solutions at the end.</p>

<h1 id="decorators" id="decorators">Decorators</h1>

<p>In Python there exists the following syntactic sugar:</p>

<pre><code class="language-python">
def decorator(func):
    def wrapper():
       func()
    return wrapper

@decorator
async def a():
     pass

a()
</code></pre>

<p>This is the same as doing <code>a = decorator(a)</code> and then calling <code>a()</code> will actually execute the wrapper, as <code>a</code> will be now equal to <code>wrapper</code>.</p>

<p>First problem we run into in this example is we gave an async function to a non-async function. You can only <code>await</code> in async functions. That is easily solved:</p>

<pre><code class="language-python">
def decorator(func):
    async def wrapper():
       await func()
    return wrapper
</code></pre>

<p>Now the wrapper is also async and we await the function inside. However this decorator might be used for async and non-async functions alike. We still need to determine accurately whether or not a function is async aforehand.</p>

<h2 id="internals" id="internals">Internals</h2>

<p>Looking at the internals of Python there exists the <code>__code__</code> property on functions. Inside that property there is a <code>co_flags</code> property. That will actually hold a bitmap value of what flags the function itself holds. You can get at this information in the following way:</p>

<pre><code class="language-python">
from dis import pretty_flags

def f():
    pass

async def a():
    pass

print(pretty_flags(f.__code__.co_flags)) # OPTIMIZED, NEWLOCALS, NOFREE
print(pretty_flags(a.__code__.co_flags)) # OPTIMIZED, NEWLOCALS, NOFREE, COROUTINE
</code></pre>

<p>Aha, we see now that we can determine if a function is a coroutine or not.  This means we can make our decorator correctly now:</p>

<pre><code class="language-python">
from dis import pretty_flags


def decorator(func):
    def wrapper():
        func()
    async def async_wrapper():
        await func()
    
    if &#34;COROUTINE&#34; in pretty_flags(func.__code__.co_flags):
        return async_wrapper
    
    return wrapper
</code></pre>

<h1 id="final-solution" id="final-solution">Final Solution</h1>

<p>I already mentioned there are two solution. I first wanted to get this internal solution out the way as that is the one I used first. Then I ran into something that made more sense. So the before mentioned decorator can also be written thusly:</p>

<pre><code class="language-python">
import inspect


def decorator(func):
    def wrapper():
        func()
    async def async_wrapper():
        await func()
    
    if inspect.iscoroutinefunction(func):
        return async_wrapper
    
    return wrapper
</code></pre>

<p>The importance of using the correct method is abundantly clear in this case. Our definition is a coroutine function, not yet a coroutine and therefor you also cannot await a definition. Only an instance of the executed async function.</p>

<p>Hope this helps out a bit in the future of your async python adventure.</p>

<p>As a final final example the decorator should probably look like this:</p>

<pre><code class="language-python">
import inspect


def decorator(func):
    def wrapper(*args, **kwargs):
        func(*args, **kwargs)
    async def async_wrapper(*args, **kwargs):
        await func(*args, **kwargs)
    
    if inspect.iscoroutinefunction(func):
        return async_wrapper
    
    return wrapper
</code></pre>

<p>In order to propagate any and all arguments given to the function you are decorating.</p>

<p><a href="https://stealthycoder.writeas.com/tag:code" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">code</span></a> <a href="https://stealthycoder.writeas.com/tag:python" class="hashtag" rel="nofollow"><span>#</span><span class="p-category">python</span></a></p>
]]></content:encoded>
      <guid>https://stealthycoder.writeas.com/decoration-patterns</guid>
      <pubDate>Tue, 15 Sep 2020 20:48:59 +0000</pubDate>
    </item>
  </channel>
</rss>