Hacker News new | past | comments | ask | show | jobs | submit login

I've always felt like the args and kwargs syntax in python is a blemish on an otherwise beautiful language. I'm wondering why not just let any function accept variable args, and reserve the keywords args and kwargs (without stars), where in a function body they refer to non-specified / explicitly defined arguments?

The only downside I see to that is the ability to write code poorly by passing junk arguments into functions that never get used. But you can do that with any function that declares kwargs or args right now.

Or just reserve args and kwargs and have it so functions with them in their arguments list have the same behavior as args an kwargs (just without the ugly stars). Maybe even denote them as __args__ and __kwargs__ in the same way you access special member functions of objects through __foo__ syntax, that would at least (to me) be consistent. I did a cursory google search if there is any language wide syntax surrounding star + variable name, and I couldn't find any, which seems to mean the name was just a hack using the syntax of a pointer dereference from C.

Am I wrong here and just missing some grand logic behind it? The rest of the language is really sensible so I probably am.




I don't know the history behind star args / kwargs, but I don't think what you're proposing is a good idea:

* You wouldn't get TypeErrors for broken code. Most code doesn't use or need star args / kwargs, but if I understand correctly your first proposal, it'd mean no TypeErrors on function signatures, making it harder to find coding errors.

* Python has very few keywords on purpose, and I don't think they'd like adding the fairly generic, non-keyword-seeming names like "args" and "kwargs".

* "Explicit is better than implicit" is part of the Python philosophy. The single and double stars may "look ugly", but that's part of the point. They're not just ordinary variables, and they do something special, so they need to stand out.

* Your proposal of using __args__ is at least explicit in their use, but not in the function definition.

For what it's worth, I mostly use star args / kwargs in wrapper or "proxy" functions: functions that do something like logging and then call through to another function to do the main work.


I work on Hy, a Lisp that compiles to Python AST, and my intuition tells me that it's a bit of a wart too. Particularly how the syntax for calling is conflated with the definition and partly in how the arguments are filled in the Call node (basically, left to right). It lets you do things like:

  >>> def foo(a, b="Default"):
  ...     print(a, b)
  ...
  >>> foo(1, 2)
  (1, 2)
  >>> foo(1)
  (1, 'Default')
  >>> foo(1, b="bar")
  (1, 'bar')
  >>> def baz(*args, **kwargs):
  ...     print(args, kwargs)
  ...
  >>> args = (1, 2, 3)
  >>> kwargs = {'foo': "bar"}
  >>> baz(*args, **kwargs)
  ((1, 2, 3), {'foo': 'bar'})
It's the first example that kind of seems 'off'. It's probably just cross-polination from my CL experience (which seems 'more correct'):

  ?> (defun foo (a &key (b "Default")) (list a b))
  FOO
  ?> (foo 1 2)
  Error: Incorrect keyword arguments
For the most part it hasn't been an issue when I'm writing the code. But when I read code that does this stuff on the call side frequently (or isn't consistent in its use over time) it can be a little frustrating.


Python 3 lets you define functions with keyword-only arguments:

    >>> def foo(a, *, b="Default"):
    ...     print((a, b))
    ...
    >>> foo(1, b="bar")
    (1, 'bar')
    >>> foo(1, 2)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: foo() takes 1 positional argument but 2 were given


Right, I should've specified the Python version. Python 3's grammar for argument lists changed a bit and added kwonlyargs to the mix. IIRC the call node's arglist isn't just filled in left-to-right and handed names for keyword arguments anymore.

Python 3 is definitely a step in the right direction. I wish adoption was a little more rapid.


It seems like what you really want is for b to be a keyword-only argument. Python 3 provides this fwiw.


It's the same as self.

    Beautiful is better than ugly.
    Explicit is better than implicit.
    Simple is better than complex.
    Complex is better than complicated.
    etc.
There are a few implicit things in Python, but I would consider those the blemishes on the language.


If you need to check arguments passed into kwargs (and you do need kwargs for some reason) then why not, well, check them?




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: