0

version: Python 3.10.6 (main, Nov 14 2022, 16:10:14) [GCC 11.3.0]

Setup:

class _Mixin:
    def vars_to_dct(self, results=[]):
        dct = self.to_dict()
        for k in dct.keys():
            results.append(k)
        return results


@dataclass
class ClassA(_Mixin):
    a: str = ""
    b: str = ""


@dataclass
class ClassB(_Mixin):
    c: str = ""
    d: str = ""
    e: str = ""

Instantiate ClassA and method by itself. This is fine:

a = ClassA()
assert ["a", "b"] == a.vars_to_dct()

Instantiate ClassB and method by itself. This is fine:

b = ClassB()
assert ["c", "d", "e"] == b.vars_to_dct()

Instantiate ClassA and ClassB together. This is not fine:

AssertionError

a = ClassA()
assert ["a", "b"] == a.vars_to_dct()

b = ClassB()
assert ["c", "d", "e"] == b.vars_to_dct()

What actually happens:

b = ClassB()
assert ["a", "b", "c", "d", "e"] == b.vars_to_dct()

Explicitly redeclaring the argument also works fine:

b = ClassB()
assert ["c", "d", "e"] == b.vars_to_dct(results=[])

Note: I have tried to apply the answers here to this behaviour:

But the difference and my question is: I am explicitly declaring the argument to the method.

Why is the argument results=[] on the method not recognised when it's run again?

    def vars_to_dct(self, results=[]):

Can someone confirm for me that it really is official Python behaviour to have variables declared in methods to be "static members"/"class variables"?

Williams
  • 4,044
  • 1
  • 37
  • 53
  • 1
    The default value is evaluated when the function is defined, not when it's called. So there's just one default list, which you keep appending to for every instance. – Barmar Dec 15 '22 at 20:26
  • Yes, it is well-known (albeit surprising to many coming from other languages) that default values are evaluated *once* when a function is defined. They are quite literally simply just stored in `myfunc.__defaults__` – juanpa.arrivillaga Dec 15 '22 at 20:50

0 Answers0