Search code examples
pythonf-string

Using f-string inside a method


I have code that looks like this:

from dataclasses import dataclass

@dataclass
class Example:
    a: str
    b: str
    c: str
    
    def repeated_code(self):
        if self.c == 'A':
            if self.a != "":
                print(f"as {self.c = } and {self.a = }, set self.a to ''")
                self.a = ""

        if self.c == 'B':
            if self.b != "":
                print(f"as {self.c = } and {self.b = }, set self.b to ''")
                self.b = ""

but I have many similar cases (> 10) in repeated code. I want to refactor this. I'm thinking about this:

@dataclass
class Example2:
    a: str
    b: str
    c: str
    
    def repeated_code(self):
        if self.c == 'A':
            if self.a != "":
                self.log_and_set(self.a, "", self.c)
              
        if self.c == 'B':
            if self.b != "":
                self.log_and_set(self.b, "", self.c)

    def log_and_set(self, a, a_value, c):
        print(f"as {c = } and {a = }, set {a} to ''")
        a = a_value

But:

  • Setting new value doesn't work in log_and_set (may be able to solve this, not too worried about this).
  • The printing is all wrong! I would like to print the b values when using the b variable and the a values otherwise, is there a way to do this using f-strings?

Solution

  • If I'm understanding you correctly, maybe this will be helpful. This uses getattr and setattr to set based on a string given to log_and_set. It also uses a simplified empty check since you know the types are str.

    #!/usr/bin/env python
    from dataclasses import dataclass
    
    
    @dataclass
    class Example3:
        a: str
        b: str
        c: str
    
        def repeated_code(self):
            if self.c == "A" and not self.a:
                self.log_and_set("a")
    
            if self.c == "B" and not self.b:
                self.log_and_set("b")
    
        def log_and_set(self, x):
            print(f"as {self.c = } and {x} = '{getattr(self, x)}', set {x} to ''")
            setattr(self, x, "")
    
    
    if __name__ == "__main__":
        ex_a = Example3("", "", "A")
        ex_a.repeated_code()
    
        ex_b = Example3("", "", "B")
        ex_b.repeated_code()
    

    This prints:

    ᐅ ./main.py
    as self.c = 'A' and a = '', set a to ''
    as self.c = 'B' and b = '', set b to ''