Search code examples
python-3.xdictionaryoopf-string

parameters inside f-string in a dictionary cannot update later


I encounter this issue, when I instantiate an Test object and call the main() method, it prints out

https://bunch/of/urls/with/None/

Although I am expecting to have

https://bunch/of/urls/with/1234/

It cannot update the self.id inside the dictionary f-string later inside the main function.

My expectation is when the dictionary value retrieves given the key, it will update the self.id as well while returning the value.

The reason I am expecting that because I call self.b_func(1234) before I call self.a_func() so it updates the self.id.

However, it is not updating the self.id inside the f-string. This behavior I don't understand why. What concept am I missing? How can I fix this?

class Test():
    def __init__(self,id=None):
        self.id = id
        #                               Problem happens here
        self.a_dict = {'a' : f'https://bunch/of/urls/with/{self.id}/'}
        
    def a_func(self):
      val = self.a_dict['a']
      print(val)
      # It prints
      # https://bunch/of/urls/with/None/
      # Not
      # https://bunch/of/urls/with/1234/
      
    def b_func(self, id):
      self.id = id
      return True
      
    def main(self):
      self.b_func(1234)
      self.a_func()
      
if __name__ == '__main__':
    a = Test()
    a.main()

Solution

  • f-strings are evaluated right where they are defined. They do not magically update themselves when the values of the expressions inside change afterwards.

    You can consider making a_dict a property instead so that its value would be dynamically generated:

    class Test():
        def __init__(self,id=None):
            self.id = id
    
        @property
        def a_dict(self):
            return {'a' : f'https://bunch/of/urls/with/{self.id}/'}
    

    Demo: https://replit.com/@blhsing/UnnaturalElasticClasslibrary