Created
February 25, 2020 15:26
-
-
Save josemarcosrf/5011ac543b450fa6c7e27dba23d35042 to your computer and use it in GitHub Desktop.
Careful with python default list parameters!
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| class A: | |
| """This is an example of wrong functions default parameters: | |
| This should actually be: | |
| def __init__(self, l=None): | |
| if l is None: | |
| self.l = [] | |
| """ | |
| def __init__(self, l=[]): | |
| self.l = l | |
| print(f"A.l mem: {id(self.l)}") | |
| def f(a=1, b=[], do_return=False): | |
| print(f"received a-mem: {id(a)}") | |
| print(f"received b-mem: {id(b)}") | |
| if do_return: | |
| return b | |
| # In this example, the list instance passed onto parameter 'b' is the same across | |
| # function calls. | |
| # The mem address of 'b' inside the function in both calls is the same!! | |
| # Happens when we do not return 'b', so when the scope is limited to the function? | |
| # See: http://effbot.org/zone/default-values.htm | |
| b = f(a=5, b=[]) | |
| print(f"1st call (no return) -> returned b-mem: {id(b)}") | |
| print("-" * 20) | |
| b = f(a=4, b=[]) | |
| print(f"2nd call (no return) -> returned b-mem: {id(b)}") | |
| print("*" * 40) | |
| # But... | |
| # When we do want 'b' returned, the mem address of 'b' inside the function | |
| # is different during different calls: | |
| b = f(a=5, b=[], do_return=True) | |
| print(f"1st call (with return) -> returned b-mem: {id(b)}") | |
| print("-" * 20) | |
| b = f(a=4, b=[], do_return=True) | |
| print(f"2nd call (with return) -> returned b-mem: {id(b)}") | |
| print("*" * 40) | |
| # This issue is much more dngerous when we have a class with instantiates | |
| # an attribute from a false 'default list parameter': | |
| a1 = A() | |
| a1.l.append(1) | |
| a2 = A() | |
| a2.l.append(2) | |
| # a1.l and a2.l are the same list! Hence we now have only one list with values=[1, 2] | |
| print(a1.l) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment