[Feature Request] Member variable as member function default argument values
Hello guys, First time for me to submit a feature request for python. A lot of time we try to use a member variable as the default value of a member function argument. So we write the code like this: ```python class A: def __init__(self, a: int = 3): self.a = a def func(self, a: int = None): if a is None: a = self.a a += 1 return a ``` This seems okay, but when there are more than 10 arguments need to set their default values as correlated member variables (with the same name at most times), it'll be very painful and the codes turn out to be quite ugly. I wish a clean coding style, so I write something like this ```python def func(self, a: int = 'self'): for k, v in process(a=a, b=b): eval(f'{k} = v') a += 1 return a def process(self, **kwargs): return {k: getattr(self, k) if (v == 'self' and k in self.__dict__.keys()) else v for k, v in kwargs.items()} ``` That seems absolutely much worse for sure! I dream I can just write ```python def func(self, a: int = 'self'): a += 1 return a ``` where I know the default value cannot be 'self', but a special flag which won't get conflict with any other valid argument values. I don't know what it should be though. Some related questions: python: https://stackoverflow.com/questions/39928345/python-member-variable-as-param... C++: https://stackoverflow.com/questions/32399730/default-arguments-as-non-static... Let me know your ideas! Ren Pang
If I ran into this (never have), my first inclination would be to write a decorator. The decorator would capture the relevant arguments (either just all of them, or perhaps using the argument names supplied to the decorator when it is called, or perhaps using a custom type hint applied to the method signature letting it know which args to modify) and update their values with the state of the object members in the desired manner. Would look something like: @object_state_args('a') def func(self, a): # value of a has already been updated to self.a, if needed a+=1 return a The opinions regarding the details of what this decorator ought to do would probably vary by use case and by individual preference and I doubt it would be very profitable to add to the std lib, personally. Seems like the type of thing better put in your own toolkit. On Wed, Dec 16, 2020, 8:12 AM Local-State <ain-soph@live.com> wrote:
Hello guys, First time for me to submit a feature request for python.
A lot of time we try to use a member variable as the default value of a member function argument. So we write the code like this: ```python class A: def __init__(self, a: int = 3): self.a = a
def func(self, a: int = None): if a is None: a = self.a a += 1 return a ``` This seems okay, but when there are more than 10 arguments need to set their default values as correlated member variables (with the same name at most times), it'll be very painful and the codes turn out to be quite ugly. I wish a clean coding style, so I write something like this ```python def func(self, a: int = 'self'): for k, v in process(a=a, b=b): eval(f'{k} = v') a += 1 return a
def process(self, **kwargs): return {k: getattr(self, k) if (v == 'self' and k in self.__dict__.keys()) else v for k, v in kwargs.items()} ``` That seems absolutely much worse for sure!
I dream I can just write ```python def func(self, a: int = 'self'): a += 1 return a ``` where I know the default value cannot be 'self', but a special flag which won't get conflict with any other valid argument values. I don't know what it should be though.
Some related questions: python:
https://stackoverflow.com/questions/39928345/python-member-variable-as-param... C++:
https://stackoverflow.com/questions/32399730/default-arguments-as-non-static...
Let me know your ideas!
Ren Pang _______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-leave@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/CTLUXD... Code of Conduct: http://python.org/psf/codeofconduct/
On Wed, Dec 16, 2020 at 09:11:18AM -0000, Local-State wrote:
This seems okay, but when there are more than 10 arguments need to set their default values as correlated member variables (with the same name at most times), it'll be very painful and the codes turn out to be quite ugly.
If the code is ugly, that is a hint that having a method with more than ten arguments is ugly. But it isn't *very* ugly; each test only requires one line, or two if you spread it out, and very simple code: def method(self, spam, eggs, cheese, tomato, aardvark): if spam is None: spam = self.spam if eggs is None: eggs = self.eggs # etc A bit tedious to write, but it's clear and obvious.
I wish a clean coding style, so I write something like this ```python def func(self, a: int = 'self'): for k, v in process(a=a, b=b): eval(f'{k} = v') a += 1 return a
def process(self, **kwargs): return {k: getattr(self, k) if (v == 'self' and k in self.__dict__.keys()) else v for k, v in kwargs.items()} ``` That seems absolutely much worse for sure!
Indeed. There is nothing "clean" about that. Are you sure it works? `eval(f'{k} = v')` will give a SyntaxError: >>> eval('name = 1') Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<string>", line 1 name = 1 ^ SyntaxError: invalid syntax -- Steve
Or more concise def method(self, spam, eggs, cheese, *args): spam = spam or self.spam eggs = eggs or self.eggs #etc., The above is equivelent to the following: spam = spam if spam else self.spam eggs = eggs if eggs else self.eggs # I prefer the first approach..
On Dec 16, 2020, at 6:14 PM, Steven D'Aprano <steve@pearwood.info> wrote:
def method(self, spam, eggs, cheese, tomato, aardvark): if spam is None: spam = self.spam if eggs is None: eggs = self.eggs # etc
On Wed, 16 Dec 2020 at 19:52, Abdulla Al Kathiri <alkathiri.abdulla@gmail.com> wrote:
Or more concise def method(self, spam, eggs, cheese, *args): spam = spam or self.spam eggs = eggs or self.eggs #etc., The above is equivelent to the following: spam = spam if spam else self.spam eggs = eggs if eggs else self.eggs # I prefer the first approach..
What if spam, for example, is zero?
In that case: spam = spam if spam is not None else self.spam The “or” won’t work with zero.
On Dec 16, 2020, at 11:00 PM, Marco Sulla <Marco.Sulla.Python@gmail.com> wrote:
On Wed, 16 Dec 2020 at 19:52, Abdulla Al Kathiri <alkathiri.abdulla@gmail.com> wrote:
Or more concise def method(self, spam, eggs, cheese, *args): spam = spam or self.spam eggs = eggs or self.eggs #etc., The above is equivelent to the following: spam = spam if spam else self.spam eggs = eggs if eggs else self.eggs # I prefer the first approach..
What if spam, for example, is zero? _______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-leave@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/2R5BBC... Code of Conduct: http://python.org/psf/codeofconduct/
Thanks a lot! You guys provide quite better ways than mine! finally for 1 or 2 arguments, I would use ``` a = a if a is None else self.a ``` if there are too many arguments, I would like to adopt the decoration idea (Ricky Teachey), which seems better. Sorry for the `eval` part error, that is not well tested before I posted. And another potential error for my initial post is `'self'` is not a good default value since many other types can't compare with `str`. `None` will be much better but will be annoying when we really want to pass `None` to the argument though.
Damn, I'm a careless programmer for sure. ``` a = a if a is not None else self.a ```
participants (5)
-
Abdulla Al Kathiri
-
Local-State
-
Marco Sulla
-
Ricky Teachey
-
Steven D'Aprano