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

Advanced Default Values

00:00 Advanced default values. Say that you want to give a default value to the Deck. It would, for example, be convenient if Deck() created a regular French deck of 52 playing cards.

00:14 First, specify the different ranks and suits. Then, add a function make_french_deck() that creates a list of instances of PlayingCard.

00:51 Here, the four different suits are specified using their Unicode symbols. We can do this in Python because it supports writing source code in UTF-8 by default.

01:04 The Wikipedia page on Unicode input gives some help on how to enter Unicode characters. You can also enter the Unicode symbols for the suits using the \u Unicode escapes or the \n named characters escapes as seen onscreen. If you’re having problems entering these codes, they’re included in the course resource files to allow you to copy and paste the appropriate lines into your REPL.

01:32 To simplify comparisons of cards later, the ranks and suits are also listed in their usual order. In theory, you could now use this function to specify a default value for Deck.cards.

02:04 As you can see, you shouldn’t do this. This would introduce one of the most common anti-patterns in Python: using mutable default arguments. The problem is that all instances of Deck will use the same list object as the default value of the .cards property.

02:21 This means that if, say, one card is removed from one Deck, then it disappears from all other instances of Deck as well. Data classes prevent you from doing this, as the code has raised a ValueError. Instead, data classes use something called a default_factory to handle mutable default values. To use default_factory, and many other cool features of data classes, you need to use the field() specifier.

03:07 The argument to default_factory can be any zero parameter callable. Now it’s easy to create a full deck of playing cards. The field() specifier is used to customize each field of a data class individually.

03:25 You’ll see some other examples later. For reference, here are the parameters field() supports. default: the default value of the field. default_factory: a function that returns the initial value of the field. init: whether the field is used in the .__init__() method. The default is True.

03:46 repr: use the field in the repr of the object. The default is True. compare: include the field in comparisons. The default is True.

03:56 hash: include the field when calculating hash(). The default is to use the same as for compare. metadata: a mapping with information about the field. In the Position example, you saw how to add simple default values by writing lat: float = 0.0. However, if you also want to customize the field, for instance to hide it in the repr, you need to use the default parameter as seen onscreen.

04:25 You may not specify both default and default_factory. The metadata parameter is not used by the data classes themselves but is available for you or third party packages to attach information to fields. In the Position example, you could, for instance, specify that latitude and longitude should be given in degrees.

05:21 The metadata and other information about a field can be retrieved using the fields() function.

05:35 As you can see, there’s quite a lot of information there, but it’s easy to select just the piece of information we’re interested in.

05:56 In the next section of the course, you’ll see how you can alter the appearance of data class objects.

Become a Member to join the conversation.