0

When I execute the below code, the first time name value is printed it prints the correct name i.e "John".

But when I create second empty instance, it still prints the name "John". Expected output should be, it will print only "Empty name" since friend_2 uses a new empty instance.

class User:
    def __init__(self,name ="Empty name"):
        self.__name = name
        
    def get_name(self):
        return self.__name
        
    def set_name(self,word):
        self.__name = word        
        
class Friend:
    def __init__(self,user = User()):
        self.__user = user
        
    def get_user(self):
        return self.__user.get_name()
    
    def set_n(self,name):
         self.__user.set_name(name)    
        

   


friend_1 = Friend()
# Only friendd_1 instance is being set to name John
friend_1.set_n("John") 

name_1 = friend_1.get_user()  # expected as we set John to friend_1 instance

friend_2 = Friend()    # use new User empty instance

name_2 = friend_2.get_user()  # This value is also John, but it should print "Empty value" as we are using default argument.
martineau
  • 119,623
  • 25
  • 170
  • 301
NNikN
  • 3,720
  • 6
  • 44
  • 86
  • Does this answer your question? [Instantiation time for mutable default arguments of closures in Python](https://stackoverflow.com/questions/41231472/instantiation-time-for-mutable-default-arguments-of-closures-in-python) – IcyIcicle Oct 22 '21 at 23:06
  • Because it's always *the same `User` object*. Common gotcha – juanpa.arrivillaga Oct 22 '21 at 23:06
  • 1
    There is a good article on this topic. [Python Mutable Defaults Are The Source of All Evil](https://florimond.dev/en/posts/2018/08/python-mutable-defaults-are-the-source-of-all-evil/) – IcyIcicle Oct 22 '21 at 23:06
  • That helps setting to None and then initializing it every time we want. I was expecting since each Friend instance is different it would be a different User Object. – NNikN Oct 22 '21 at 23:09

1 Answers1

1

As stated in the comments mutable default arguments are a common gotcha.

class Friend:
    def __init__(self, user = None):
        # Default to None instead and then create the object during initialization 
        self.__user = user if user else User()
TheLazyScripter
  • 2,541
  • 1
  • 10
  • 19
  • I wonder if `user or User()` might be a little more Pythonic, though perhaps less obvious as to what it does. – sj95126 Oct 22 '21 at 23:18