> Which is redundant for most functions as they only have positional parameters.
It would not need to exist if that were the case.
The “default” in Python is that a parameter can be passed both positionally and by keyword. Until Python 3.8, the only way to have positional only parameters in pure Python was to use *args and unpack them yourself.
That being said, you can find quite a lot of uses in the modules written in Python - though I'm not going to pretend I can tell you the reasoning for all them.
When parameter names are meaningless for the final result
def abs_days_difference(date1, date2, /):
# note that swapping passed params will yield the same result
delta = abs((date2 - date1).days)
return delta
d1 = date(2023, 1, 1)
d2 = date(2024, 1, 15)
abs_days_difference(d1,d2)==abs_days_difference(d2,d1)
The function returns the absolute diff in the number of days, so date1, date2 are meaningless variable names. It looks like then introduce an order(could #1 be the earlier date, while #2 be the later one?). If you don't get users any options it is clear that the order is meaningless
If you function signature is day_difference(date1, date2,*) you have to specify params as kwargs only, removing the confusion:
d1 = date(2023, 1, 1)
d2 = date(2024, 1, 15)
#this now doesn't work
day_difference(d1,d2)
# this works and is much clearer for caller
day_difference(earlier_date=d1,later_date=d2)
Edit: this is wrong, I was thinking/merging the idea of the '*' into this one, my bad.
-- original below --
> What's the advantage of stopping someone from naming the parameter when they pass it in?
From what I have seen, this feature is mostly used for the opposite direction, to force the caller to use keyword arguments past a certain number of (or zero) positional arguments.
It's not redundant because regular python parameters without a / in the list can be called by name even if they don't have default values. The author may intend them to be positional only but some callers might call them by name and you might break them when you refactor the parameter names, positional only avoids that.
Some people dislike positional only parameters but they're already used in a number of stdlib functions written in c so it makes sense to be able to write replacement with the same semantics in pure python as well as being able to express signatures for the c function
1. It's useless noise for something like help(math.sin).
2. It's everywhere and not well documented. Ironical for a help system!
Damn it's been hard to improve Python's help system. Python2 didn't have an entry for re.MatchObject. When I mentioned this on irc #python the response was to just google it. Talk about not getting the point. help() should help.
It is not useless noise for something like `help(math.sin)`. The signature displayed by help is `sin(x, /)`, which tells you that `sin(x=1)` will fail. If the signature had just been `sin(x)` then `sin(x=1)` would work.
help() should not have to re-teach you the syntax of the language every time you look up an individual help topic, though. Even though this "/" stuff is uncommonly used, it seems like it should have its own help topic. Otherwise, this means that help() has to re-explain every piece of syntax that might be considered "uncommonly used", which is kind of hard to draw a line for.
The default for python function is that params can be specified as either positional or keyword. / makes params before it positional only while * makes params after it keyword only.
Ooh that feature was new to me. See PEP 570[1] for more details. My personal opinion is that this is not something that any code should do... but I'm not the BDFL!
def spawn_coroutine(func, /, *args, **kwargs):
# func can itself have a parameter called 'func' and nothing breaks
# we could have the user provide the thunk themselves but that’s inconvenient
def thunk():
return func(*args, **kwargs)
# put thunk on some sort of task queue...
But, as the PEP points out, sometimes you just don’t want the parameter names to be part of your public contract, and it’s nice to have a way to express that.
Help on built-in function sin in module math:
sin(x, /)
Return the sine of x (measured in radians).
>>> math.sin(x=2)
~~~~~~~~^^^^^
TypeError: math.sin() takes no keyword arguments
/ is used everwhere and it's usually just noise. Unexplained noise.
It is often used for builtins, because emulating the default Python behaviour of accepting arguments both by position and by name is a pain with the Python/C API. (There are other use cases for positional-only arguments, such as accepting an arbitrary function and an arbitrary set of arguments to call it with at the same time—for example, to invoke it in a new coroutine—but they are pretty rare.) This pecularity of most builtin functions has been there since before Python 3 was a thing, it’s just been undocumented and difficult to emulate in Python before this syntax was introduced.
As for unexplained noise—well, all other parts of the function declaration syntax aren’t explained either. You’re expected to know the function declaration syntax in order to read help on individual function declarations; that’s what the syntax reference is for.
If you use Vim, SHIFT+K will bring up the help docstring for the object under your cursor. If you want `method`'s help from `object.method`, all you have to do is highlight `object.method` then do SHIFT+K.
The navigation is a little awkward but it's super handy for quick one-offs right in the buffer.
or its awesome two friends: locals() and globals() to see their names and values simultaneously; I've gotten a lot of mileage out of that as a pseudo-debugger when the only insight you have is a logger in production
An interesting side effect is that it runs the code inside the module you import, so that code can act based on whether it gets imported by help or not:
For quick lookups, I usually use pydoc[1], which displays roughly the same help string but without having to go into the repl. I think there are several *doc functions like this. Off the top of my head I can think of texdoc (which usually just opens the pdf of the package documentation) and perldoc.
pydoc -b is also very useful as a standard lib reference when you're not connected to the internet and you can live with the quite interesting default color scheme.
R has probably the best help feature for any language -- not only can you ask it about help on individual functions with "?", the tradition (and this continues with most add in packages as well as builtins) is not only does it give you info on the function, it gives you example code using it so you can understand what it does in practice.
Clojure has doc and source functions. For example:
user=> (doc clojure.core)
-------------------------
clojure.core
Fundamental library of the Clojure language
user=> (doc +)
-------------------------
clojure.core/+
([] [x] [x y] [x y & more])
Returns the sum of nums. (+) returns 0. Does not auto-promote
longs, will throw on overflow. See also: +'
user=> (source +)
(defn +
"Returns the sum of nums. (+) returns 0. Does not auto-promote
longs, will throw on overflow. See also: +'"
{:inline (nary-inline 'add 'unchecked_add)
:inline-arities >1?
:added "1.2"}
([] 0)
([x] (cast Number x))
([x y] (. clojure.lang.Numbers (add x y)))
([x y & more]
(reduce1 + (+ x y) more)))
Like many others here I once wrote a toy lisp in golang, and I added a help function. It would give usage-information for all the built-in functions.
> (help +)
Arguments N arg1..argN
Adds all arguments present to the first number.
> (help map)
Arguments lst:list fun:function
Return a list with the contents of evaluating the given function on every item of the supplied list.
See-also: map-pairs
I wrote a small thing for adding a `#doc List.find` directive. However, I don't maintain it anymore since I think it doesn't see much use and it's work to keep up on OCaml compiler internals changes (and it's my impression it never picked up much adoption). https://github.com/reynir/ocp-index-top
Although it's probably not at the top of many people's minds (includind mine) as a favorite programming language, Mathematica does have fantastic help, accessible with `?` and expandable from there as needed.
Some room for improvement on getting help for symbols:
help("**") explains the power operator, but could also mention dict unpacking.
help("<<") doesn't mention bit shifting (shows a page for "operator precedence").
I was going to say languages should emphasize help for symbols because they're hard to Google for - but I guess in the LLM age, that's no longer true.
Also uses / in the method signatures with no indication of what it means.
This article doesn't either.
Apparently "It signifies the end of the positional only parameters, parameters you cannot use as keyword parameters."
Which is redundant for most functions as they only have positional parameters.
> Which is redundant for most functions as they only have positional parameters.
It would not need to exist if that were the case.
The “default” in Python is that a parameter can be passed both positionally and by keyword. Until Python 3.8, the only way to have positional only parameters in pure Python was to use *args and unpack them yourself.
Why does it need to exist even though that's not the case?
What's the advantage of stopping someone from naming the parameter when they pass it in?
Reading the PEP for adding it, it seems primarily concerned with mirroring how the C builtins generally don't allow it, for performance.
https://peps.python.org/pep-0570/#rationale
That being said, you can find quite a lot of uses in the modules written in Python - though I'm not going to pretend I can tell you the reasoning for all them.
In my own code, the main use I've found is that they don't "reserve" a slot in kwargs - this is totally valid code: You could've worked around it by taking a dict before, but it's just a lot friendlier being able to take args as normal.I did not know that about kwargs! Very interesting and useful to be kind of pedantic and not have unintentional conflicts at that level
> What's the advantage of stopping someone from naming the parameter when they pass it in?
There are cases where a parameter name is worthless on the calling side, this is especially common for unary or binary functions.
In that case, the ability to name the parameter on the call site just constrains the implementation, and the overrides (in the case of methods).
Right. For example, something like max() or abs() have no meaningful parameter names. But for example max() does take a `key` named argument as well.
When parameter names are meaningless for the final result
The function returns the absolute diff in the number of days, so date1, date2 are meaningless variable names. It looks like then introduce an order(could #1 be the earlier date, while #2 be the later one?). If you don't get users any options it is clear that the order is meaninglessCompare with
Note that now If you function signature is day_difference(date1, date2,*) you have to specify params as kwargs only, removing the confusion:Edit: this is wrong, I was thinking/merging the idea of the '*' into this one, my bad.
-- original below --
> What's the advantage of stopping someone from naming the parameter when they pass it in?
From what I have seen, this feature is mostly used for the opposite direction, to force the caller to use keyword arguments past a certain number of (or zero) positional arguments.
But that's *, not /.
yep!
It's not redundant because regular python parameters without a / in the list can be called by name even if they don't have default values. The author may intend them to be positional only but some callers might call them by name and you might break them when you refactor the parameter names, positional only avoids that. Some people dislike positional only parameters but they're already used in a number of stdlib functions written in c so it makes sense to be able to write replacement with the same semantics in pure python as well as being able to express signatures for the c function
That is simply and obviously not true. See my example for math.sin above.
My major point still stands.
1. It's useless noise for something like help(math.sin).
2. It's everywhere and not well documented. Ironical for a help system!
Damn it's been hard to improve Python's help system. Python2 didn't have an entry for re.MatchObject. When I mentioned this on irc #python the response was to just google it. Talk about not getting the point. help() should help.
It is not useless noise for something like `help(math.sin)`. The signature displayed by help is `sin(x, /)`, which tells you that `sin(x=1)` will fail. If the signature had just been `sin(x)` then `sin(x=1)` would work.
OK you're right. But it wouldn't even have occurred to me to try sin(x=2) until I read sibling comment.
I guess that's because you don't know how function arguments work in python but that's not really the fault of the help documentation
Astonishing. As if help() cannot be improved and this is not a 'fault'.
help() should not have to re-teach you the syntax of the language every time you look up an individual help topic, though. Even though this "/" stuff is uncommonly used, it seems like it should have its own help topic. Otherwise, this means that help() has to re-explain every piece of syntax that might be considered "uncommonly used", which is kind of hard to draw a line for.
The default for python function is that params can be specified as either positional or keyword. / makes params before it positional only while * makes params after it keyword only.
Ooh that feature was new to me. See PEP 570[1] for more details. My personal opinion is that this is not something that any code should do... but I'm not the BDFL!
1: https://peps.python.org/pep-0570/
One case where this is very desirable:
But, as the PEP points out, sometimes you just don’t want the parameter names to be part of your public contract, and it’s nice to have a way to express that.> Which is redundant for most functions as they only have positional parameters.
Huh? This is not true.
This can be invoked as either `foo(1, 2, 3)` or `foo(c=3, b=2, a=1)`:It is often used for builtins, because emulating the default Python behaviour of accepting arguments both by position and by name is a pain with the Python/C API. (There are other use cases for positional-only arguments, such as accepting an arbitrary function and an arbitrary set of arguments to call it with at the same time—for example, to invoke it in a new coroutine—but they are pretty rare.) This pecularity of most builtin functions has been there since before Python 3 was a thing, it’s just been undocumented and difficult to emulate in Python before this syntax was introduced.
As for unexplained noise—well, all other parts of the function declaration syntax aren’t explained either. You’re expected to know the function declaration syntax in order to read help on individual function declarations; that’s what the syntax reference is for.
How would you discover the syntax reference via the repl help() system?
Found it.
>>> help('def')
If you use Vim, SHIFT+K will bring up the help docstring for the object under your cursor. If you want `method`'s help from `object.method`, all you have to do is highlight `object.method` then do SHIFT+K.
The navigation is a little awkward but it's super handy for quick one-offs right in the buffer.
Thank you for this, super handy
Nice. I usually fall back to dir() as my first inspection tool at the command line.
or its awesome two friends: locals() and globals() to see their names and values simultaneously; I've gotten a lot of mileage out of that as a pseudo-debugger when the only insight you have is a logger in production
Don't forget `vars()`.
I used to, but wat offers a better printout of the methods: https://github.com/igrek51/wat
I bounce back and forth. First dir() then help()...
vars() is another good one if you're looking for something with a particular value.
help() is great, but my favorite tool for getting quick info about an object from the Python REPL is still wat.
Just `pip install wat` and then if you need info about some object o, do `wat / o`. If you want full docstrings, do `wat.long / o`
It's a lifesaver when you're using a poorly documented package.
Dear god: https://github.com/igrek51/wat?tab=readme-ov-file#load-from-...
I always think of python as a more readable version of perl. I first got that impression from the "import this" statement.
That load from glyph snippet aligns with my understanding.
For the record, this is not what I would consider idiomatic Python.
The web page's stylesheet is broken (returns HTTP 404) but the text is still quite readable. Good job!
> There are other ways to use the help function, but before we dive into those I'd like to address the *, and / symbols shown in the output above.
Where is this addressed? Is there a section missing here?
I am posting this because I always forget which one it is and searching for it is damn near impossible
https://peps.python.org/pep-0457/#syntax-and-semantics
"/" marks the boundary between "positional only" and "mixed" and then "*" does the same for "mixed" and "kwargs only"
An interesting side effect is that it runs the code inside the module you import, so that code can act based on whether it gets imported by help or not:
https://tio.run/##VY6/DoIwEMb3PsUXl6ODLK7ETVcfwBhylBqIpW1KB3...
For quick lookups, I usually use pydoc[1], which displays roughly the same help string but without having to go into the repl. I think there are several *doc functions like this. Off the top of my head I can think of texdoc (which usually just opens the pdf of the package documentation) and perldoc.
pydoc -b is also very useful as a standard lib reference when you're not connected to the internet and you can live with the quite interesting default color scheme.
[1] https://docs.python.org/3/library/pydoc.html
Before 3.13: https://thejenkinscomic.net/?id=52
Cool idea. Do any other languages have this?
R has probably the best help feature for any language -- not only can you ask it about help on individual functions with "?", the tradition (and this continues with most add in packages as well as builtins) is not only does it give you info on the function, it gives you example code using it so you can understand what it does in practice.
Ruby has a similar help() function you can invoke from the REPL (irb), or from the CLI with the standalone tool `ri`[1]. Pretty nifty feature!
[1]: https://stackoverflow.com/a/25671404
Clojure has doc and source functions. For example:
Like many others here I once wrote a toy lisp in golang, and I added a help function. It would give usage-information for all the built-in functions.
utop for ocaml is cool, gives type signatures for functions. no explicit help, but does offer completions with tab.
Similarly, rtop for reason.
https://opam.ocaml.org/blog/about-utop/ and https://opam.ocaml.org/packages/rtop/
I wrote a small thing for adding a `#doc List.find` directive. However, I don't maintain it anymore since I think it doesn't see much use and it's work to keep up on OCaml compiler internals changes (and it's my impression it never picked up much adoption). https://github.com/reynir/ocp-index-top
dbuenzli's down also has a similar feature.
Smalltalk, by far, is the best in this category.
Although it's probably not at the top of many people's minds (includind mine) as a favorite programming language, Mathematica does have fantastic help, accessible with `?` and expandable from there as needed.
[dead]