Chris Padilla/Blog

My passion project! Posts spanning music, art, software, books, and more
You can follow by Newsletter or RSS! (What's RSS?) Full archive here.

    Jellyfish

    💧

    Must be dreamy being a jellyfish~

    A very, very, very simplified study after Goro Fujita.

    Mathieu on Learning Pace

    From "The Listening Book" by W.A. Mathieu. Full title of the essay says it all: There's Not Much to Learn and It Takes Forever

    The truth is, a musician can spend a lifetime learning five notes and still not know everything in them. The more masterful you become, the deeper becomes the mystery and the more you are a beginner.

    So when a student feels sluggish in learning a certain mode or cross rhythm, I have to say how there is hardly anything there to learn but that it takes more than one life.

    ... there is no ought-to-know-how, there is only the uncovering of ourselves when we sit at the polishing stone.

    It was in my Masters, after 15 years of playing, that I started to think I was getting the hang of things. Only to find out 5 years later that there's much, much more to learn.

    Copy and paste to your discipline of choice.

    Passing State in Python with the Special Dictionary Attribute & the Classmethod decorator

    I found myself in a situation where I had constructed a ProcessState class for storing the results of a cron job that runs on AWS. Passing the instance of ProcessState works just fine when it all happens in a single package. But then I needed to store the state in our database temporarily while the lambda kicks over to another procedure within a step function.

    I needed two things:

    1. A succinct way to export the state.
    2. A way to load the state from the db and re-instantiate my ProcessState class

    Two built-in Python methods did the trick: the __dict__ Special Attribute and the @classmethod decorator.

    Starting File

    Here's ProcessState:

    import logging
    from logging import Logger
    import datetime
    from .types.unit_dict import UnitDict
    
    
    class ProcessState:
        """
        Object for storing and formatting Process State
        """
    
        def __init__(
            self,
            result: list[UnitDict] = [],
            complete: bool = False,
            errors: list[str] = [],
        ):
            self.result = result
            self.complete = complete
            self.errors = errors
            self.logger = logging.getLogger("ProcessLogger")
    
        def __repr__(self):
            return f"ProcessState('{self.result}', {self.complete}, {self.errors}"
            
        # Methods for updating and formatting date here.

    From the type hints, you'll see that we're dealing here with properties of basic types: lists and a boolean. I've also instantiated the class with a logger.

    Exporting with the Dict Attribute

    If I want to get all of those properties, I can simply call the __dict__ attribute directly:

    ps = ProcessState()
    
    # Update the state here.
    
    # Get the dictionary
    dict = ps.__dict__

    If I'm only storing values I want to pass along, this works great!

    The wrinkle comes with the logger. I'm not interested in passing that along outside of my application. But the result will include reference to the logger.

    So I'll have to handle filtering it out with a few helper functions:

    class ProcessState:
        """
        Object for storing and formatting Process State
        """
        
        ...
    
        def get_dict_from_state(self):
            result = {k: v for k, v in self.__dict__.items() if self._is_value_property(v)}
            result["created_at"] = datetime.datetime.now().isoformat()
    
            return result
    
        def _is_value_property(self, v):
            if isinstance(v, Logger):
                return False
            return True

    I've also gone ahead and added a "created_at" property.

    Now, calling ps.get_dict_from_state() would provide only the errors, complete state, and result. Excellent!

    Loading a Dictionary Into Our Class

    Say I pass the result off to my DB. I then query the db for those values again.

    Looking at my __init__ method above, I could almost get away with passing in the dictionary as-is with a spread operator like so:

    ps = ProcessState(**dict)

    However, my dict now includes a created_at property which I haven't included in the __init__ function!

    If it were important to persist that field, I could add it to my init function. Or I could make use of an extra **kwargs at then end of my init signiture to catch any arguements not already defined.

    BUT say that I also need to do some data massaging, such as instantiating another class within ProcessStates own initialization?

    @classmethod is the answer.

    I'll show how I'm using it, then how to construct it:

    ps = ProcessState.from_dict(dict)

    very similar to calling the __init__ method, though we're not tied to one signature. In fact, we could have multiple @classmethods for different scenarios, lending more flexibility to our instance construction.

    The simplest way to implement thiswould be to pass everything in:

    class ProcessState:
        """
        Object for storing and formatting Process State
        """
        
        . . . 
        
        @classmethod
        def from_dict(cls, values: dict) -> "CollectionState":
            return cls(**values)

    However, as I mentioned, we have an unwanted attribute. Here I'll filter it out with list comprehension:

        @classmethod
        def from_dict(cls, values: dict) -> "CollectionState":
            filtered values = [x for x in values if x in ["errors", "results", "complete"]] 
            return cls(**values)

    With that, we're back up and running, ready to use ProcessState in our function!

    Carl Fischer – We'll Be Together Again

    Listen on Youtube

    No tears, no fears. Remember, there's always tomorrow... ~

    Had the pleasure of playing this beautiful piano just outside of the Frisco Discovery Center:

    Front View

    Back View. Beautiful dark design with a colorful, floral pattern.

    Day Dreaming Pup

    Lucy having a good day!

    Love painting this pup. Lucy is becoming my muse! 🐕