Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Recursive {pattern} replacement in/using object's properties

I want to use an object's properties for recursive pattern replacement. Since the object's properties are not known at time of class definition I cannot use @property decorators

Example

class Test():
    def __init__(self):
        self.date = '{year}-{month}'
        self.year = '2020'
        self.month = '06'

        self.path = '/dev/null'
        self.file_name = 'ABC-{date}.mp4'
        self.file = '{path}/{file_name}'

    def print(self):
        print(__class__)
        print ("Filename is {file_name}".format(**vars(self)))
        print ("File {file} will be written to {path}".format(**vars(self)))

t = Test()
t.print()

Actual output

<class '__main__.Test'>
Filename is ABC-{date}.mp4
File {path}/{file_name} will be written to /dev/null

Desired output

<class '__main__.Test'>
Filename is ABC-2020-06.mp4
File /dev/null/ABC-2020-06.mp4 will be written to /dev/null
like image 904
Chris Avatar asked May 23 '26 02:05

Chris


2 Answers

You mentioned recursion but did not actually use any recursion in your code.

You can achieve the desired behavior by implementing a recursive method that formats a given template string until the rendered result is the same as the input:

def render(self, template):
    rendered = template.format(**vars(self))
    return rendered if rendered == template else self.render(rendered)

def print(self):
    print(self.render("Filename is {file_name}"))
    print(self.render("File {file} will be written to {path}"))

With the above changes, your code would output:

Filename is ABC-2020-06.mp4
File /dev/null/ABC-2020-06.mp4 will be written to /dev/null
like image 72
blhsing Avatar answered May 25 '26 16:05

blhsing


You can use properties. You just need to use more of them than you expected.

class Test:
    def __init__(self):
        self.year = '2020'
        self.month = '06'

        self.path = '/dev/null'

    @property
    def file(self):
        return '{0.path}/{0.file_name}'.format(self)

    @property
    def file_name(self):
        return 'ABC-{0.date}.mp4'.format(self)

    @property
    def date(self):
        return '{0.year}-{0.month}'.format(self)

    def print(self):
        print(__class__)
        print ("Filename is {0.file_name}".format(self))
        print ("File {0.file} will be written to {0.path}".format(self))

t = Test()
t.print()

path, year, and month are the only "hard-coded" attributes; the rest can be derived. The recursion (such as it is) is implicit in that each attribute access may be a property which itself invokes another property. This is the key benefit of properties: their interface is indistinguishable from an instance attribute.

like image 32
chepner Avatar answered May 25 '26 14:05

chepner



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!