Search code examples
pythonpython-classvariable-variables

How to generate properties of instances of classes in batches?


I have a class named MyClass. I want to generate the attributes k_10sec to k_1d of the instance in batches when generating instances of the class.

How do I modify the code?

bars = ['10sec', '1min', '5min', '30min', '1d']


class MyClass:
    def __init__(self):
        for bar in bars:
            if bar.endswith('sec'):
                duration_seconds = int(bar[:-3])
            elif bar.endswith('min'):
                duration_seconds = int(bar[:-3] * 60)
            elif bar.endswith('d'):
                duration_seconds = int(bar[:-1] * 60 * 60 * 24)
            self.globals()[f'k_{bar}'] = duration_seconds


s1 = MyClass()
for bar in bars:
    print(s1.[f'k_{bar}'])

My expected result:

10
60
300
1800
86400

Finally, I combined the two methods and used them together.

import re


def parse_time(bar='', secs=0):
    if bar != '':
        bar = re.split('(\d+)', bar)
        if bar[2] in ('sec', 's'):
            secs = int(bar[1])
        elif bar[2] == 'min':
            secs = int(bar[1]) * 60
        elif bar[2] in ('hour', 'h'):
            secs = int(bar[1]) * 60 * 60
        elif bar[2] in ('d', 'day', 'D'):
            secs = int(bar[1]) * 60 * 60 * 24
        else:
            pass
        return secs
    elif secs != 0:
        if secs % (60 * 60 * 24) == 0:
            bar = str(secs // (60 * 60 * 24)) + 'day'
        elif secs % (60 * 60) == 0:
            bar = str(secs // (60 * 60)) + 'hour'
        elif secs % 60 == 0:
            bar = str(secs // 60) + 'min'
        else:
            bar = str(secs) + 'sec'
        return bar
    else:
        pass


class MyClass:
    def __init__(self, bars):
        self.d = {f'k_{bar}': parse_time(bar=bar) for bar in bars}


if __name__ == '__main__':
    bars = ['10sec', '1min', '5min', '30min', '1d']
    s1 = MyClass(bars)
    pass

Solution

  • You don't need globals; that's a function in the built-in scope for providing a dict interface to the global variables. Just use a regular dict

    class MyClass:
        def __init__(self, bars):
            self.d = {}
            for bar in bars:
                if bar.endswith('sec'):
                    duration_seconds = int(bar[:-3])
                elif bar.endswith('min'):
                    duration_seconds = int(bar[:-3]) * 60
                elif bar.endswith('d'):
                    duration_seconds = int(bar[:-1]) * 60 * 60 * 24
                self.d[f'k_{bar}'] = duration_seconds
    
    s1 = MyClass(['10sec', '1min', '5min', '30min', '1d'])
    for bar in s1.d:
        print(s1.d[bar])
    

    I would move the logic of converting a time string to a number of seconds to a separate function, though:

    def parse_time(s):
        if s.endswith('sec'):
            return int(s[:-3])
        elif s.endswith('min'):
            return int(s[:-3]) * 60
        elif s.endswith('d'):
            return int(s[:-1]) * 60 * 60 * 24
    
    
    class MyClass:
        def __init__(self, bars):
            self.d = {f'k_{bar}': parse_time(bar) for bar in bars}