Locked learning resources

Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

Locked learning resources

This lesson is for members only. Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

Using Special Parameters in Real-World Code

00:00 So, do you maybe have an example that you can show us where this is actually used in some Python source code? Yeah, absolutely. It’s a great question because yeah, sometimes seeing all this in the abstract is a bit, well, abstract.

00:15 So say you have a dictionary—we can call it ages

00:21 and we’ll say "Martin", you’re 20, right? Right.

00:29 And I am also 20.

00:34 So this is a dictionary, which means we can call a bunch of methods on it. One of them being .get(), and in IPython, what you can do is you can append the function with a question mark (?), and that will return its signature and its docstring.

00:51 So as you can see here, it’s got the signature, the signature being the function identifier and then the arguments that it accepts. And you’ll see here, the forward slash symbol (/) as a special parameter for .get(), which basically means that you can’t call .get() with any keyword arguments.

01:09 You have to call it with just positional arguments. Nice. So I can’t put default= when I call dictionary.get(). That’s going to give me that error that we’ve seen before in some of the previous parts. Right, so—. Which are you calling? .ge(). [Laughter.]

01:28 So yeah, it just serves as a way to get arguments, and you can—not default. You used defail, which kind of made sense. [Laughter.] Let’s just return 0 if there’s not, and let’s try and get a key that doesn’t exist.

01:45 But if you try and pass this as a keyword, then you’ll get an error, a TypeError. Even though when you look at the function signature, you can see that at least like the printout here in the IPython console gives you this, the name also says default=None, but you can’t pass it because of the /. Yeah, exactly.

02:04 Like the default=None is just so that’s an optional argument when you’re calling it, and it will have a default value of None. Yeah.

02:12 But it still has to be positional. Nice. That’s a good real-life example to see. Yeah. And then another one, for the asterisk (*), is in a standard-library module.

02:26 So one of the classes in subprocess, the main class, is the Popen() class, which is the process open class, which is the underlying class, which is behind the more common function of run().

02:41 But in Popen(), in the signature, as you’ll see, there’s just loads of arguments here. The first one, which is usually positional, is the args (arguments).

02:51 You might use this to call .get() from within your Python program, and you’d pass the args as the first argument. And you don’t need any of the other ones because they have default values, but there’s certain ones at the end, which have to be keyword arguments.

03:06 So when you’re calling the function, you can pass in a whole load of them as positional arguments, but there’s certain ones that Python enforces you to pass as keyword arguments.

03:16 Interesting, yeah. And that’s good to see this as examples because it might be confusing otherwise to see a *, in there and then just be like, “Wait, what’s what can I pass here? Is it like a regex symbol, and I can pass anything that I want?” Right, yeah.

03:33 It’s easy to get confused. It kind of reminds you of, like, the unpacking operators, maybe. Yeah. You might think it’s some kind of weird parameter that you can pass in.

03:43 I certainly thought that the first time I saw these symbols, which made me want to look into a bit further. But all it that it really means here is that starting from user, even though they have default values, the rest of the parameters that are defined here need to be passed in as keyword arguments. That’s right. Cool. Well, thanks for showing me these examples. Yeah, no problem. Okay.

04:06 So just to recap that, looking at the .get() method of a dictionary whose signature has a / symbol, which just means that all the arguments that you pass into the .get() method need to be positional and they cannot be keyword arguments.

04:21 Whereas with a class constructor like Popen(), which has loads of keyword arguments, Python wants you to use certain of the arguments as keyword arguments only.

Avatar image for Pavneet Ghai

Pavneet Ghai on Aug. 15, 2022

In this video at 0:40 they mentioned about ipython, I want to know what are diffrent pythons available in market and what are they used for, All my learning is in google colab, want to know which python is that. Please responce

Avatar image for Ian

Ian RP Team on Aug. 16, 2022

Thanks for your comment, Pavneet.

I’m not sure exactly what Google Colab uses, but it looks to be some form of Jupyter Notebook. Jupyter Notebook incidentally, uses IPython as a kernal.

This is not strictly another Python, despite the name. It’s like a normal Python interpreter but with more features, like some that were demonstrated here. That said, it’s still running the most common CPython implementation of Python. IPython and Jupyter are generally more common where data science and machine learning are involved.

There are other implementations of Python too, such as PyPy, which can be faster that CPython for many applications. Some other implementations can be found signposted on the Python website.

As for alternative interpreters/shells, there are PtPython, DreamPie, and bpython, to name a few, but I don’t have much experience with them.

Avatar image for rogerhurwitz

rogerhurwitz on Aug. 22, 2022

The videos did a good job of discussing how to use special parameters, but did not discuss why to use special parameters. Demonstrating usages (get and Popen) was not enlightening since the motivation behind those usages was not discussed. In sum, for developers considering the use of special parameters, what are the motivations behind limiting callers to either positional only, keyword only, or combined usages?

Avatar image for Ian

Ian RP Team on Aug. 22, 2022

Thanks for your comment and good question, rogerhurwitz. You’re right, I just mention in passing that you might want to use it to customize how people use your functions, but we don’t really explore the pros and cons of why a package developer might want to use it.

In the docs, there’s some minimal guidance on this topic:

Use positional-only if you want the name of the parameters to not be available to the user. This is useful when parameter names have no real meaning, if you want to enforce the order of the arguments when the function is called or if you need to take some positional parameters and arbitrary keywords.

Use keyword-only when names have meaning and the function definition is more understandable by being explicit with names or you want to prevent users relying on the position of the argument being passed.

For an API, use positional-only to prevent breaking API changes if the parameter’s name is modified in the future.

It’s an interesting concept to explore further. I think in many cases, using or not using special parameters will also come down to what style you think is best.

For instance, in the case of .get() it might make sense to limit that to positional arguments because it enforces a clear coding style. .get() is already reasonably self explanatory, so calling .get(key="Martin") might be considered redundant.

The default keyword argument, on the other hand, I was initially on the fence about not allowing it. I thought allowing .get("Martin", default=20) wouldn’t be so terrible, but then again, keeping it as positional only will allow the developers of Python to add another argument or change the existing name “default”, without breaking existing code.

In the case of subprocess, its similar. Forcing some keyword-only arguments makes sense because having so many arguments means that code can get confusing. Imagine 10 positional arguments, you’d have to look at the docs to understand what’s going on.

Forcing keyword arguments makes things more readable for subprocess but I would ideally go further and make more arguments keyword-only, because there are so many of them.

The main drawbacks of keyword-only arguments seems to be that if you update your function to only accept keyword only arguments you’ll break some users code. Additionally, just allowing keyword arguments means that you can’t change the name of parameters down the line without breaking changes too.

Avatar image for rogerhurwitz

rogerhurwitz on Aug. 23, 2022

Thanks for the thoughtful reply. Here is an interesting example from the Scikit-learn organization considering the pros and cons of moving to a keyword-only argument model.

Avatar image for Ian

Ian RP Team on Aug. 24, 2022

That’s a great find, thanks for sharing it!

Become a Member to join the conversation.