[](https://forum.exercism.org)
- [](https://exercism.org)
+ [](https://exercism.org)
[](https://exercism.org/blog/freeing-our-maintainers)
[](https://github.com/exercism/python/actions?query=workflow%3A%22Exercises+check%22)
-
-
-Hi. ๐๐ฝ ๐ **We are happy you are here.** ๐ ๐
-
-
-
-
+> [!IMPORTANT]
+>
We are not accepting community contributions at this time.
+>
+>
+>
+>
+> We love our community. We're grateful you are interested in improving the Python track.
+> But our maintainers are **not accepting community contributions at this time.**
+> If you would like to discuss possible future changes, please open a [thread on the forum](https://forum.exercism.org/).
+>
+> This [community blog post](https://exercism.org/blog/freeing-our-maintainers) contains more details.
+>
+>
+>
-We ๐ ๐ our community.
-**`But our maintainers are not accepting community contributions at this time.`**
-Please read this [community blog post](https://exercism.org/blog/freeing-our-maintainers) for details.
-
-
+Hi. ๐๐ฝ ๐ **We are happy you are here.** ๐ ๐
+
**`exercism/Python`** is one of many programming language tracks on [exercism(dot)org][exercism-website].
This repo holds all the instructions, tests, code, & support files for Python _exercises_ currently under development or implemented & available for students.
-๐ Track exercises support Python `3.7` - `3.11.2`.
+๐ Track exercises support Python `3.10` - `3.13.5`.
Exceptions to this support are noted where they occur.
-๐ Track tooling (_test-runner, representer, analyzer, and Continuous Integration_) runs on Python `3.11.2`.
+๐ Track tooling (_test-runner, representer, analyzer, and Continuous Integration_) runs on Python `3.13.5`.
Exercises are grouped into **concept** exercises which teach the [Python syllabus][python-syllabus], and **practice** exercises, which are unlocked by progressing in the syllabus tree ๐ด .
Concept exercises are constrained to a small set of language or syntax features.
@@ -43,34 +47,38 @@ Practice exercises are open-ended, and can be used to practice concepts learned,
It is not uncommon to discover typos, confusing directions, or incorrect implementations of certain tests or code examples. Or you might have a great suggestion for a hint to aid students ( ๐ ), see optimizations for exemplar or test code, find missing test cases to add, or want to correct factual and/or logical errors. Or maybe you have a great idea ๐ก for an exercise or feature ( ๐ ).
_Our track is always a work in progress!_ ๐๐
-While contributions are paused, we ask that you [`open a thread in our community forum`](https://forum.exercism.org) to let us know what you have found/suggest.
+While contributions are paused, we ask that you [**open a thread in our community forum**](https://forum.exercism.org) to let us know what you have found/suggest.
## ๐ง **Did you write a patch that fixes a bug?**
-**`Our maintainers are not accepting community contributions at this time.`**
-Please read this [community blog post](https://exercism.org/blog/freeing-our-maintainers) for details.
+Our maintainers are not accepting community contributions at this time.
+
+Until the pause on contributions ends, all PRs from the larger community will be **automatically closed** with a note.
+We ask that you [**open a thread in our community forum**](https://forum.exercism.org) to discuss any potential changes. Changes may or may not be approved, depending on the forum discussion.
-Once the pause ends, we will **happily** consider your PR.
-Until that time, all PRs from the larger community will be **automatically closed** with a note.
+Please read this [community blog post](https://exercism.org/blog/freeing-our-maintainers) for additional details.
+
-We're leaving the general contributing docs below for our long-term collaborators and maintainers.
+We're leaving the track contributing docs below for our long-term collaborators and maintainers.
+
+
+ Python Track Contributing Docs
In General
-- Maintainers are happy to review your work and help troubleshoot with you. ๐ ๐
+- Maintainers are happy to review your work and help troubleshoot with you. ๐ ๐ If you need help, comment in the Pull Request/issue. ๐๐ฝโโ๏ธ
+ - **Please wait at least 72 hours before pinging or `@`ing reviewers directly.**
- Requests are reviewed as soon as is practical/possible.
- - (โ ) Reviewers may be in a different timezone โ , or tied up ๐งถ with other tasks.
- - **Please wait at least 72 hours before pinging.**
-- If you need help, comment in the Pull Request/issue. ๐๐ฝโโ๏ธ
+ - (โ ) Keep in mind that reviewers may be in a different timezone โ , or tied up ๐งถ with other tasks.
- If you would like in-progress feedback/discussion, please mark your Pull Request as a **`[draft]`**
- Pull Requests should be focused around a single exercise, issue, or change.
- Pull Request titles and descriptions should make clear **what** has changed and **why**.
- - Please link ๐ to any related issues the PR addresses.
+ - Please link ๐ to any related forum discussions or issues the PR addresses.
- ๐ [ Open an issue ][open-an-issue]๐ and discuss it with ๐งฐ maintainers _**before**_:
- creating a Pull Request making significant or breaking changes.
- for changes across multiple exercises, even if they are typos or small.
@@ -195,13 +203,13 @@ _We know it, and trust us, we are working on fixing it._ But if you see
-This track officially supports Python `3.7 - 3.11.2` for students completing exercises.
-The track `test runner`, `analyzer`, and `representer` run in docker on `python:3.11.2-slim`.
+This track officially supports Python `3.10 - 3.13.5` for students completing exercises.
+The track `test runner`, `analyzer`, and `representer` run in docker on `python:3.13.5-alpine3.22`.
Although the majority of test cases are written using `unittest.TestCase`,
-- All exercises should be written for compatibility with Python `3.7` - `3.11.2`.
-- Version backward _incompatibility_ (_e.g_ an exercise using features introduced in `3.8`, `3.9`, or `3.10`) should be clearly noted in any exercise hints, links, introductions or other notes.
+- All exercises should be written for compatibility with Python `3.10` - `3.13.5`.
+- Version backward _incompatibility_ (_e.g_ an exercise using features introduced in Python `3.10`+ that would not work in Python `3.10`) should be clearly noted in any exercise hints, links, introductions or other notes.
- Here is an example of how the Python documentation handles [version-tagged ๐ท ][version-tagged-language-features] feature introduction.
@@ -222,7 +230,7 @@ Although the majority of test cases are written using `unittest.TestCase`,
- For specifications, refer to [Concept Exercise Anatomy][concept-exercise-anatomy], or [Practice Exercise Anatomy][practice-exercise-anatomy] depending on which type of exercise you are contributing to.
-- **Practice exercise**, descriptions and instructions come from a centralized, cross-track [problem specifications][problem-specifications] repository.
+- **Practice exercise** descriptions and instructions come from a centralized, cross-track [problem specifications][problem-specifications] repository.
- Any updates or changes need to be proposed/approved in `problem-specifications` first.
- If Python-specific changes become necessary, they need to be appended to the canonical instructions by creating a `instructions.append.md` file in this (`exercism/Python`) repository.
@@ -369,45 +377,32 @@ configlet generate --spec-path path/to/problem/specifications --
configlet generate --spec-path path/to/problem/specifications
```
+
+
[.flake8]: https://github.com/exercism/python/blob/main/.flake8
[.style.yapf]: https://github.com/exercism/python/blob/main/.style.yapf
[american-english]: https://github.com/exercism/docs/blob/main/building/markdown/style-guide.md
-[being-a-good-community-member]: https://github.com/exercism/docs/tree/main/community/good-member
[card-games-testfile]: https://github.com/exercism/python/blob/main/exercises/concept/card-games/lists_test.py
[cater-waiter]: https://github.com/exercism/python/tree/main/exercises/concept/cater-waiter
[concept-exercise-anatomy]: https://github.com/exercism/docs/blob/main/building/tracks/concept-exercises.md
-[concept-exercises]: https://github.com/exercism/docs/blob/main/building/tracks/concept-exercises.md
[config-json]: https://github.com/exercism/javascript/blob/main/config.json
-[config-json]: https://github.com/exercism/python/blob/main/config.json
-[configlet-general]: https://github.com/exercism/configlet
[configlet-lint]: https://github.com/exercism/configlet#configlet-lint
[configlet]: https://github.com/exercism/docs/blob/main/building/configlet/generating-documents.md
[distinguishing-test-iterations]: https://docs.python.org/3/library/unittest.html#distinguishing-test-iterations-using-subtests
[enumerate]: https://docs.python.org/3/library/functions.html#enumerate
[eol]: https://en.wikipedia.org/wiki/Newline
[exercise-config-json]: https://github.com/exercism/docs/blob/main/building/tracks/concept-exercises.md#full-example
-[exercise-presentation]: https://github.com/exercism/docs/blob/main/building/tracks/presentation.md
-[exercism-admins]: https://github.com/exercism/docs/blob/main/community/administrators.md
-[exercism-code-of-conduct]: https://exercism.org/docs/using/legal/code-of-conduct
-[exercism-concepts]: https://github.com/exercism/docs/blob/main/building/tracks/concepts.md
-[exercism-contributors]: https://github.com/exercism/docs/blob/main/community/contributors.md
[exercism-internal-linking]: https://github.com/exercism/docs/blob/main/building/markdown/internal-linking.md
[exercism-markdown-specification]: https://github.com/exercism/docs/blob/main/building/markdown/markdown.md
[exercism-markdown-widgets]: https://github.com/exercism/docs/blob/main/building/markdown/widgets.md
-[exercism-mentors]: https://github.com/exercism/docs/tree/main/mentoring
-[exercism-tasks]: https://exercism.org/docs/building/product/tasks
-[exercism-track-maintainers]: https://github.com/exercism/docs/blob/main/community/maintainers.md
-[exercism-track-structure]: https://github.com/exercism/docs/tree/main/building/tracks
[exercism-website]: https://exercism.org/
-[exercism-writing-style]: https://github.com/exercism/docs/blob/main/building/markdown/style-guide.md
[flake8-noqa]: https://flake8.pycqa.org/en/3.1.1/user/ignoring-errors.html#in-line-ignoring-errors
[flake8]: http://flake8.pycqa.org/
[google-coding-style]: https://google.github.io/styleguide/pyguide.html
[guidos-gorgeous-lasagna-testfile]: https://github.com/exercism/python/blob/main/exercises/concept/guidos-gorgeous-lasagna/lasagna_test.py
-[help-wanted]: https://github.com/exercism/python/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22
[implicit-line-joining]: https://google.github.io/styleguide/pyguide.html#32-line-length
[markdown-language]: https://guides.github.com/pdfs/markdown-cheatsheet-online.pdf
[open-an-issue]: https://github.com/exercism/python/issues/new/choose
@@ -429,5 +424,4 @@ configlet generate --spec-path path/to/problem/specifications
[the-words-that-we-use]: https://github.com/exercism/docs/blob/main/community/good-member/words.md
[unittest]: https://docs.python.org/3/library/unittest.html#unittest.TestCase
[version-tagged-language-features]: https://docs.python.org/3/library/stdtypes.html#dict.popitem
-[website-contributing-section]: https://exercism.org/docs/building
[yapf]: https://github.com/google/yapf
diff --git a/README.md b/README.md
index d8ec6644585..20c3bd1ce0c 100644
--- a/README.md
+++ b/README.md
@@ -4,22 +4,39 @@
Exercism Python Track
[](https://forum.exercism.org)
- [](https://exercism.org)
+ [](https://exercism.org)
[](https://exercism.org/blog/freeing-our-maintainers)
[](https://github.com/exercism/python/actions?query=workflow%3A%22Exercises+check%22)
-Hi. ๐๐ฝ ๐ **We are happy you are here.** ๐ ๐
+> [!IMPORTANT]
+>
We are not accepting community contributions at this time.
+>
+>
+>
+>
+> We love our community. We're grateful you are interested in improving the Python track.
+> But our maintainers are **not accepting community contributions at this time.**
+> If you would like to suggest a change / discuss an issue, please open a [thread on the forum](https://forum.exercism.org/).
+>
+> This [community blog post](https://exercism.org/blog/freeing-our-maintainers) contains more details.
+>
+>
+>
+Hi. ๐๐ฝ ๐ **We are happy you are here.** ๐ ๐
+
+
+
**`exercism/Python`** is one of many programming language tracks on [exercism(dot)org][exercism-website].
This repo holds all the instructions, tests, code, & support files for Python _exercises_ currently under development or implemented & available for students.
-๐ Track exercises support Python `3.7` - `3.11.5`.
+๐ Track exercises support Python `3.10` - `3.13.13`.
Exceptions to this support are noted where they occur.
-๐ Track tooling (_test-runner, representer, analyzer, and Continuous Integration_) runs on Python `3.11.5`.
+๐ Track tooling (_test-runner, representer, analyzer, and Continuous Integration_) runs on Python `3.13.13`.
Exercises are grouped into **concept** exercises which teach the [Python syllabus][python-syllabus], and **practice** exercises, which are unlocked by progressing in the syllabus tree ๐ด .
Concept exercises are constrained to a small set of language or syntax features.
@@ -43,15 +60,15 @@ It might also be helpful to look at [Being a Good Community Member][being-a-good
-We ๐ ๐ our community.
-**`But our maintainers are not accepting community contributions at this time.`**
+We ๐ ๐ our community.
+**But our maintainers are not accepting community contributions at this time.**
Please read this [community blog post][freeing-maintainers] for details.
Here to suggest a new feature or new exercise?? **Hooray!** ๐
-We'd love if you did that via our [Exercism Community Forum](https://forum.exercism.org/).
+We'd love if you did that via our [Community Forum](https://forum.exercism.org/).
Please read [Suggesting Exercise Improvements][suggesting-improvements] & [Chesterton's Fence][chestertons-fence].
_Thoughtful suggestions will likely result in faster & more enthusiastic responses from volunteers._
@@ -67,7 +84,7 @@ _Thoughtful suggestions will likely result in faster & more enthusiastic respons
## Python Software and Documentation
-**Copyright ยฉ 2001-2023 Python Software Foundation. All rights reserved.**
+**Copyright ยฉ 2001-2026 Python Software Foundation. All rights reserved.**
Python software and documentation are licensed under the [PSF License Agreement][psf-license].
@@ -99,7 +116,6 @@ This repository uses the [MIT License](/LICENSE).
[exercism-writing-style]: https://github.com/exercism/docs/blob/main/building/markdown/style-guide.md
[freeing-maintainers]: https://exercism.org/blog/freeing-our-maintainers
[practice-exercises]: https://github.com/exercism/docs/blob/main/building/tracks/practice-exercises.md
-[prs]: https://github.com/exercism/docs/blob/main/community/good-member/pull-requests.md
[psf-license]: https://docs.python.org/3/license.html#psf-license
[python-syllabus]: https://exercism.org/tracks/python/concepts
[suggesting-improvements]: https://github.com/exercism/docs/blob/main/community/good-member/suggesting-exercise-improvements.md
diff --git a/concepts/basics/about.md b/concepts/basics/about.md
index ef873ce418f..6f932bfd16f 100644
--- a/concepts/basics/about.md
+++ b/concepts/basics/about.md
@@ -64,20 +64,21 @@ For example, `my_first_variable` can be re-assigned many times using `=`, and ca
>>> print(my_first_variable)
2
->>> my_first_variable = "Now, I'm a string." # You may re-bind a name to a different object type and value.
+>>> my_first_variable = "Now, I'm a string." # <--You may re-bind a name to a different object type and value.
>>> print(type(my_first_variable))
+>>> my_first_variable = 'You can call me "str".' # <--Strings can be declared using single or double quote marks.
>>> print(my_first_variable)
-"Now, I'm a string." # Strings can be declared using single or double quote marks.
+You can call me "str".
-import collections
->>> my_first_variable = collections.Counter([1,1,2,3,3,3,4,5,6,7]) # Now my_first_variable has been re-bound to a Counter object.
+>>> import collections
+>>> my_first_variable = collections.Counter([1,1,2,3,3,3,4,5,6,7]) # <--Now my_first_variable has been re-bound to a Counter object.
>>> print(type(my_first_variable))
>>> print(my_first_variable)
->>> Counter({3: 3, 1: 2, 2: 1, 4: 1, 5: 1, 6: 1, 7: 1})
+Counter({3: 3, 1: 2, 2: 1, 4: 1, 5: 1, 6: 1, 7: 1})
```
@@ -101,19 +102,19 @@ MY_FIRST_CONSTANT = "Some other value"
## Functions
-In Python, units of functionality are encapsulated in [_functions._][functions], which are themselves [objects][objects] (_it's [turtles all the way down][turtles all the way down]_).
+In Python, units of functionality are encapsulated in [_functions_][functions], which are themselves [objects][objects] (_it's [turtles all the way down][turtles all the way down]_).
Functions can be executed by themselves, passed as arguments to other functions, nested, or bound to a class.
When functions are bound to a [class][classes] name, they're referred to as [methods][method objects].
Related functions and classes (_with their methods_) can be grouped together in the same file or module, and imported in part or in whole for use in other programs.
The `def` keyword begins a [function definition][function definition].
-Each function can have zero or more formal [parameters][parameters] in `()` parenthesis, followed by a `:` colon.
+Each function can have zero or more formal [parameters][parameters] in `()` parentheses, followed by a `:` colon.
Statements for the _body_ of the function begin on the line following `def` and must be _indented in a block_:
```python
-# The body of a function is indented by 2 spaces, & prints the sum of the numbers.
+# The body of a function is indented by 2 spaces & prints the sum of the numbers.
def add_two_numbers(number_one, number_two):
total = number_one + number_two
print(total)
@@ -125,7 +126,7 @@ def add_two_numbers(number_one, number_two):
# Inconsistent indentation in your code blocks will raise an error.
>>> def add_three_numbers_misformatted(number_one, number_two, number_three):
... result = number_one + number_two + number_three # This was indented by 4 spaces.
-... print(result) #this was only indented by 3 spaces
+... print(result) # <--This was only indented by 3 spaces.
...
...
File "", line 3
@@ -144,7 +145,7 @@ def add_two_numbers(number_one, number_two):
return number_one + number_two
-# Calling the function in the Python terminal returns the sum of the numbers.
+# Calling the function in the Python shell returns the sum of the numbers.
>>> add_two_numbers(3, 4)
7
@@ -155,28 +156,42 @@ def add_two_numbers(number_one, number_two):
11
```
-Functions that do not have an _explicit_ `return` expression will _implicitly_ return the [`None`][none] object.
-The details of `None` will be covered in a later exercise.
+Functions that do not have an _explicit_ expression following a `return` will _implicitly_ return the [`None`][none] object.
+The details of `None` will be covered in a later concept.
For the purposes of this exercise and explanation, `None` is a placeholder that represents nothing, or null:
```python
-# This function does not have an explicit return.
-def add_two_numbers(number_one, number_two):
- result = number_one + number_two
+# This function will return `None`
+def square_a_number(number):
+ square = number * number
+ return # <-- note that this return is not followed by an expression
-# Calling the function in the Python terminal appears
+# Calling the function in the Python shell appears
# to not return anything at all.
->>> add_two_numbers(5, 7)
+>>> square_a_number(2)
>>>
# Using print() with the function call shows that
# the function is actually returning the **None** object.
->>> print(add_two_numbers(5, 7))
+>>> print(square_a_number(2))
None
+```
+
+Functions that omit `return` will also _implicitly_ return the [`None`][none] object.
+This means that if you do not use `return` in a function, Python will return the `None` object for you.
+```python
+
+# This function omits a return keyword altogether
+def add_two_numbers(number_one, number_two):
+ result = number_one + number_two
+
+>>> add_two_numbers(5, 7)
+>>> print(add_two_numbers(5, 7))
+None
# Assigning the function call to a variable and printing
# the variable will also show None.
@@ -192,32 +207,41 @@ Functions are [_called_][calls] or invoked using their name followed by `()`.
Dot (`.`) notation is used for calling functions defined inside a class or module.
```python
->>> def number_to_the_power_of(number_one, number_two):
- return number_one ** number_two
+>>> def raise_to_power(number, power):
+... return number ** power
...
->>> number_to_the_power_of(3,3) # Invoking the function with the arguments 3 and 3.
+>>> raise_to_power(3,3) # Invoking the function with the arguments 3 and 3.
27
# A mis-match between the number of parameters and the number of arguments will raise an error.
->>> number_to_the_power_of(4,)
+>>> raise_to_power(4,)
...
Traceback (most recent call last):
File "", line 1, in
-TypeError: number_to_the_power_of() missing 1 required positional argument: 'number_two'
+TypeError: raise_to_power() missing 1 required positional argument: 'power'
# Calling methods or functions in classes and modules.
>>> start_text = "my silly sentence for examples."
->>> str.upper(start_text) # Calling the upper() method for the built-in str class.
-"MY SILLY SENTENCE FOR EXAMPLES."
+>>> str.upper(start_text) # <--Calling the upper() method from the built-in str class on start_text.
+'MY SILLY SENTENCE FOR EXAMPLES.'
+
+# Because a string is an instance of the str class, methods can also be called on them "directly".
+>>> start_text = "my silly sentence for examples."
+>>> start_text.upper() # <--Calling the upper() method on start_text directly.
+'MY SILLY SENTENCE FOR EXAMPLES.'
+
+# Alternatively, we can skip the variable assignment (although this gets messy quick).
+>>> "my silly sentence for examples.".upper()
+'MY SILLY SENTENCE FOR EXAMPLES.'
-# Importing the math module
-import math
->>> math.pow(2,4) # Calling the pow() function from the math module
->>> 16.0
+# Importing the math module
+>>> import math
+>>> math.pow(2,4) # <--Calling the pow() function from the math module.
+16.0
```
@@ -248,14 +272,18 @@ Docstrings are declared using triple double quotes (""") indented at the same le
```python
+# An example from PEP257 of a multi-line docstring
+# reformatted to use Google style non-type hinted docstrings.
+# Some additional details can be found in the Sphinx documentation:
+# https://www.sphinx-doc.org/en/master/usage/extensions/napoleon.html#getting-started
-# An example from PEP257 of a multi-line docstring.
def complex(real=0.0, imag=0.0):
"""Form a complex number.
- Keyword arguments:
- real -- the real part (default 0.0)
- imag -- the imaginary part (default 0.0)
+ Keyword Arguments:
+ real (float): The real part of the number (default 0.0)
+ imag (float): The imaginary part of the number (default 0.0)
+
"""
if imag == 0.0 and real == 0.0:
@@ -272,33 +300,40 @@ Testing and `doctest` will be covered in a later concept.
```python
-# An example on a user-defined function.
->>> def number_to_the_power_of(number_one, number_two):
- """Raise a number to an arbitrary power.
-
- :param number_one: int the base number.
- :param number_two: int the power to raise the base number to.
- :return: int - number raised to power of second number
+# An example on a user-defined function using a Google style docstring.
+>>> def raise_to_power(number, power):
+ """Raise a number to an arbitrary power.
+
+ Parameters:
+ number (int): The base number.
+ power (int): The power to raise the base number to.
+
+ Returns:
+ int: The number raised to the specified power.
+
+ Takes a number and raises it to the specified power, returning the result.
- Takes number_one and raises it to the power of number_two, returning the result.
- """
+ """
- return number_one ** number_two
+ return number ** power
...
# Calling the .__doc__ attribute of the function and printing the result.
->>> print(number_to_the_power_of.__doc__)
+>>> print(raise_to_power.__doc__)
Raise a number to an arbitrary power.
- :param number_one: int the base number.
- :param number_two: int the power to raise the base number to.
- :return: int - number raised to power of second number
+Parameters:
+ number (int): The base number.
+ power (int): The power to raise the base number to.
- Takes number_one and raises it to the power of number_two, returning the result.
+Returns:
+ int: The number raised to the specified power.
+Takes a number and raises it to the specified power, returning the result.
+...
-# Printing the __doc__ attribute for the built-in type: str.
+# Printing the __doc__ attribute of the built-in type: str.
>>> print(str.__doc__)
str(object='') -> str
str(bytes_or_buffer[, encoding[, errors]]) -> str
@@ -308,10 +343,11 @@ errors is specified, then the object must expose a data buffer
that will be decoded using the given encoding and error handler.
Otherwise, returns the result of object.__str__() (if defined)
or repr(object).
-encoding defaults to sys.getdefaultencoding().
+encoding defaults to 'utf-8'.
errors defaults to 'strict'.
```
+
[PEP257]: https://www.python.org/dev/peps/pep-0257/
[calls]: https://docs.python.org/3/reference/expressions.html#calls
[classes]: https://docs.python.org/3/reference/datamodel.html#classes
diff --git a/concepts/basics/introduction.md b/concepts/basics/introduction.md
index 2a874394ebb..cb61a0184ab 100644
--- a/concepts/basics/introduction.md
+++ b/concepts/basics/introduction.md
@@ -2,23 +2,31 @@
Python is a [dynamic and strongly typed][dynamic typing in python] programming language.
It employs both [duck typing][duck typing] and [gradual typing][gradual typing], via [type hints][type hints].
+Python puts a strong emphasis on code readability and (_similar to Haskell_) uses [significant indentation][significant indentation] to denote function, method, and class definitions.
+
+Python was created by Guido van Rossum and first released in 1991.
Imperative, declarative (e.g., functional), and object-oriented programming _styles_ are all supported, but internally **[everything in Python is an object][everythings an object]**.
-Python puts a strong emphasis on code readability and (_similar to Haskell_) uses [significant indentation][significant indentation] to denote function, method, and class definitions.
+We'll dig more into what all of that means as we continue through the Python track concepts.
-Python was created by Guido van Rossum and first released in 1991.
+This first concept (`basics`) introduces 4 major Python language features:
+1. Name Assignment (_variables and constants_),
+2. Functions (_the `def` keyword and the `return` keyword_),
+3. Comments, and
+4. Docstrings.
+
## Name Assignment (Variables & Constants)
Programmers can bind [_names_][facts-and-myths-about-python-names] (also called _variables_) to any type of object using the assignment `=` operator: ` = `.
-A name can be reassigned (or re-bound) to different values (different object types) over its lifetime.
+A name can be reassigned (or re-bound) to different values (different object types) over its lifetime:
```python
->>> my_first_variable = 1 # my_first_variable bound to an integer object of value one.
->>> my_first_variable = 2 # my_first_variable re-assigned to integer value 2.
+>>> my_first_variable = 1 # <--my_first_variable bound to an integer object of value one.
+>>> my_first_variable = 2 # <--my_first_variable re-assigned to integer value 2.
>>> print(type(my_first_variable))
@@ -26,31 +34,33 @@ A name can be reassigned (or re-bound) to different values (different object typ
>>> print(my_first_variable)
2
->>> my_first_variable = "Now, I'm a string." # You may re-bind a name to a different object type and value.
+>>> my_first_variable = "Now, I'm a string." # <--You may re-bind a name to a different object type and value.
>>> print(type(my_first_variable))
+>>> my_first_variable = 'You can call me "str".' # <--Strings can be declared using single or double quote marks.
>>> print(my_first_variable)
-"Now, I'm a string." # Strings can be declared using single or double quote marks.
+You can call me "str".
```
### Constants
-Constants are names meant to be assigned only once in a program.
-They should be defined at a [module][module] (file) level, and are typically visible to all functions and classes in the program.
-Using `SCREAMING_SNAKE_CASE` signals that the name should not be re-assigned, or its value mutated.
+Constants are names meant to be assigned only once in a program โ although Python will not prevent re-assignment.
+Using `SCREAMING_SNAKE_CASE` signals to anyone reading the code that the name should **not** be re-assigned, or its value mutated.
+Constants should be defined at a [module][module] (file) level, and are typically visible to all functions and classes in a program.
+
## Functions
The `def` keyword begins a [function definition][function definition].
-Each function can have zero or more formal [parameters][parameters] in `()` parenthesis, followed by a `:` colon.
+Each function can have zero or more formal [parameters][parameters] in `()` parentheses, followed by a `:` colon.
Statements for the _body_ of the function begin on the line following `def` and must be _indented in a block_.
```python
-# The body of this function is indented by 2 spaces,& prints the sum of the numbers.
+# The body of this function is indented by 2 spaces & prints the sum of the numbers.
def add_two_numbers(number_one, number_two):
total = number_one + number_two
print(total)
@@ -62,7 +72,7 @@ def add_two_numbers(number_one, number_two):
# Inconsistent indentation in your code blocks will raise an error.
>>> def add_three_numbers_misformatted(number_one, number_two, number_three):
... result = number_one + number_two + number_three # This was indented by 4 spaces.
-... print(result) #this was only indented by 3 spaces
+... print(result) # <--This was only indented by 3 spaces.
...
...
File "", line 3
@@ -81,7 +91,7 @@ def add_two_numbers(number_one, number_two):
return number_one + number_two
-# Calling the function in the Python terminal returns the sum of the numbers.
+# Calling the function in the Python shell returns the sum of the numbers.
>>> add_two_numbers(3, 4)
7
@@ -92,28 +102,41 @@ def add_two_numbers(number_one, number_two):
11
```
-Functions that do not have an _explicit_ `return` expression will _implicitly_ return the [`None`][none] object.
-The details of `None` will be covered in a later exercise.
+
+Functions that do not have an _explicit_ expression following a `return` will _implicitly_ return the [`None`][none] object.
+The details of `None` will be covered in a later concept.
For the purposes of this exercise and explanation, `None` is a placeholder that represents nothing, or null:
```python
-# This function does not have an explicit return.
-def add_two_numbers(number_one, number_two):
- result = number_one + number_two
-
+# This function will return `None`
+def square_a_number(number):
+ square = number * number
+ return # <-- note that this return is not followed by an expression
-# Calling the function in the Python terminal appears
+# Calling the function in the Python shell appears
# to not return anything at all.
->>> add_two_numbers(5, 7)
+>>> square_a_number(2)
>>>
# Using print() with the function call shows that
# the function is actually returning the **None** object.
->>> print(add_two_numbers(5, 7))
+>>> print(square_a_number(2))
None
+```
+Functions that omit `return` will also _implicitly_ return the [`None`][none] object.
+This means that if you do not use `return` in a function, Python will return the `None` object for you.
+
+```python
+# This function omits a return keyword altogether.
+def add_two_numbers(number_one, number_two):
+ result = number_one + number_two
+
+>>> add_two_numbers(5, 7)
+>>> print(add_two_numbers(5, 7))
+None
# Assigning the function call to a variable and printing
# the variable will also show None.
@@ -133,29 +156,35 @@ Each line of a comment block must start with the `#` character.
## Docstrings
The first statement of a function body can optionally be a [_docstring_][docstring], which concisely summarizes the function or object's purpose.
-Docstring conventions are laid out in [PEP257][pep257].
+Docstrings are read by automated documentation tools such as [Sphinx][sphinx] and are returned by calling the special attribute `.__doc__` on the function, method, or class name.
+General docstring conventions are laid out in [PEP257][pep257], but exact formats will vary by project and team.
Docstrings are declared using triple double quotes (""") indented at the same level as the code block:
```python
-
-# An example from PEP257 of a multi-line docstring.
+# An example from PEP257 of a multi-line docstring
+# reformatted to use Google style non-type hinted docstrings.
+# Some additional details can be found in the Sphinx documentation:
+# https://www.sphinx-doc.org/en/master/usage/extensions/napoleon.html#getting-started
def complex(real=0.0, imag=0.0):
"""Form a complex number.
- Keyword arguments:
- real -- the real part (default 0.0)
- imag -- the imaginary part (default 0.0)
+ Keyword Arguments:
+ real (float): The real part of the number (default 0.0)
+ imag (float): The imaginary part of the number (default 0.0)
+
"""
if imag == 0.0 and real == 0.0:
return complex_zero
-
```
-[pep257]: https://www.python.org/dev/peps/pep-0257/
+Docstrings can also function as [lightweight unit tests][doctests], which will be covered in a later concept.
+
+
[comments]: https://realpython.com/python-comments-guide/#python-commenting-basics
[docstring]: https://docs.python.org/3/tutorial/controlflow.html#tut-docstrings
+[doctests]: https://docs.python.org/3/library/doctest.html
[duck typing]: https://en.wikipedia.org/wiki/Duck_typing
[dynamic typing in python]: https://stackoverflow.com/questions/11328920/is-python-strongly-typed
[everythings an object]: https://docs.python.org/3/reference/datamodel.html
@@ -165,6 +194,8 @@ def complex(real=0.0, imag=0.0):
[module]: https://docs.python.org/3/tutorial/modules.html
[none]: https://docs.python.org/3/library/constants.html
[parameters]: https://docs.python.org/3/glossary.html#term-parameter
+[pep257]: https://www.python.org/dev/peps/pep-0257/
[return]: https://docs.python.org/3/reference/simple_stmts.html#return
-[type hints]: https://docs.python.org/3/library/typing.html
[significant indentation]: https://docs.python.org/3/reference/lexical_analysis.html#indentation
+[sphinx]: https://www.sphinx-doc.org/en/master/usage/index.html
+[type hints]: https://docs.python.org/3/library/typing.html
diff --git a/concepts/binary-octal-hexadecimal/about.md b/concepts/binary-octal-hexadecimal/about.md
index a7fca3714e3..67646aed2f2 100644
--- a/concepts/binary-octal-hexadecimal/about.md
+++ b/concepts/binary-octal-hexadecimal/about.md
@@ -18,7 +18,7 @@ A snippet from the base 2 system looks like this, although it continues infinite
| -------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- |
| 2 \*\* 7 | 2 \*\* 6 | 2 \*\* 5 | 2 \*\* 4 | 2 \*\* 3 | 2 \*\* 2 | 2 \*\* 1 | 2 \*\* 0 |
-So if we want to represent the number 6, it would in binary be: 110
+So if we want to represent the number 6 in binary, it would be 110.
| Place value | 4 | 2 | 1 |
| ------------- | --- | --- | --- |
@@ -41,7 +41,6 @@ In Python, we can represent binary literals using the `0b` prefix.
If we write `0b10011`, Python will interpret it as a binary number and convert it to base 10.
```python
-# 0b10011
>>> 0b10011
19
@@ -86,6 +85,8 @@ However, the usual mathematical operator rules apply: dividing two binary numbe
>>> 0b10011/3
6.333333333333333
+```
+
### Converting to and from Binary Representation
@@ -133,6 +134,9 @@ For example, `bit_count()` on '0b11011' will return 4:
```python
>>> 0b11011.bit_count()
4
+```
+
+
~~~~exercism/note
If you are working locally, `bit_count()` requires at least Python 3.10.
The Exercism online editor currently supports all features through Python 3.11.
@@ -148,7 +152,6 @@ In Python, we can represent octal numbers using the `0o` prefix.
As with binary, Python automatically converts an octal representation to an `int`.
```python
-# 0o123
>>> 0o123
83
```
@@ -157,7 +160,6 @@ As with binary, octal numbers **are ints** and support all integer operations.
Prefixing a number with `0o` that is not in the octal system will raise a `SyntaxError`.
### Converting to and from Octal Representation
-
To convert an `int` into an octal representation, you can use the built-in [`oct()`][oct] function.
This acts similarly to the `bin()` function, returning a string:
@@ -165,6 +167,8 @@ This acts similarly to the `bin()` function, returning a string:
```python
>>> oct(83)
'0o123'
+```
+
To convert an octal number to an integer, we can use the `int()` function, passing an octal string representation and the base (8) as arguments:
@@ -175,22 +179,21 @@ To convert an octal number to an integer, we can use the `int()` function, passi
As with binary, giving the wrong base will raise a `ValueError`.
-### Hexadecimal
+## Hexadecimal
[Hexadecimal][hexadecimal] is a base 16 numeral system.
It uses the digits 0 - 9 and the letters A, B, C, D, E, and F.
A is 10, B is 11, C is 12, D is 13, E is 14, and F is 15.
We can represent hexadecimal numbers in Python using the `0x` prefix.
-As with binary and octal, Python will automatically convert hexadecimal literals to `int`.
+As with binary and octal, Python will automatically convert hexadecimal literals to `int`s.
```python
-# 0x123
>>> 0x123
291
```
-As with binary and octal - hexadecimal literals **are ints**, and you can perform all integer operations.
+As with binary and octal โ hexadecimal literals **are ints**, and you can perform all integer operations with them.
Prefixing a non-hexadecimal number with `0x` will raise a `SyntaxError`.
@@ -202,6 +205,8 @@ This acts similarly to the `bin()` function, returning a string:
```python
>>> hex(291)
'0x123'
+```
+
To convert a hexadecimal representation to an integer, we can use the `int()` function, passing a hexadecimal string with the base (16) as arguments:
diff --git a/concepts/binary-octal-hexadecimal/introduction.md b/concepts/binary-octal-hexadecimal/introduction.md
index a06ac922faf..84ff634263d 100644
--- a/concepts/binary-octal-hexadecimal/introduction.md
+++ b/concepts/binary-octal-hexadecimal/introduction.md
@@ -1,4 +1,4 @@
-# binary, octal, hexadecimal
+# Binary, Octal, Hexadecimal
Binary, octal, and hexadecimal (_also known as hex_) are different [numeral systems][numeral-systems] with different bases.
Binary is base 2, octal is base 8, and hexadecimal is base 16.
diff --git a/concepts/bitwise-operators/about.md b/concepts/bitwise-operators/about.md
index a4ddb509c11..1cd5a237c29 100644
--- a/concepts/bitwise-operators/about.md
+++ b/concepts/bitwise-operators/about.md
@@ -112,12 +112,12 @@ See the section below for details.
In decimal representation, we distinguish positive and negative numbers by using a `+` or `-` sign to the left of the digits.
Using these symbols at a binary level proved inefficient for digital computing and raised the problem that `+0` is not the same as `-0`.
-Rather than using `-` and `+`, all modern computers use a [`twos-complement`][twos-complement] representation for negative numbers, right down to the silicon chip level.
+Rather than using `-` and `+`, all modern computers use a [`two's complement`][twos-complement] representation for negative numbers, right down to the silicon chip level.
This means that all bits are inverted and a number is _**interpreted as negative**_ if the left-most bit (also termed the "most significant bit", or MSB) is a `1`.
Positive numbers have an MSB of `0`.
This representation has the advantage of only having one version of zero, so that the programmer doesn't have to manage `-0` and `+0`.
-This way of representing negative and positive numbers adds a complication for Python: there are no finite-integer concepts like `int32` or `int64` internally in the core langauge.
+This way of representing negative and positive numbers adds a complication for Python: there are no finite-integer concepts like `int32` or `int64` internally in the core language.
In 'modern' Python, `int`s are of unlimited size (_limited only by hardware capacity_), and a negative or bit-inverted number has a (_theoretically_) infinite number of `1`'s to the left, just as a positive number has unlimited `0`'s.
This makes it difficult to give a useful example of `bitwise not`:
@@ -145,7 +145,7 @@ This is **not** the `0b10011001` we would see in languages with fixed-size integ
The `~` operator only works as expected with _**unsigned**_ byte or integer types, or with fixed-sized integer types.
These numeric types are supported in third-party packages such as [`NumPy`][numpy], [`pandas`][pandas], and [`sympy`][sympy] but not in core Python.
-In practice, Python programmers quite often use the shift operators described below and `& | ^` with positive numbers only.
+In practice, Python programmers quite often use `&`, `|`, `^`, and the shift operators described below with positive numbers only.
Bitwise operations with negative numbers are much less common.
One technique is to add [`2**32 (or 1 << 32)`][unsigned-int-python] to a negative value to make an `int` unsigned, but this gets difficult to manage.
Another strategy is to work with the [`ctypes`][ctypes-module] module, and use c-style integer types, but this is equally unwieldy.
@@ -153,13 +153,13 @@ Another strategy is to work with the [`ctypes`][ctypes-module] module, and use c
## [`Shift operators`][bitwise-shift-operators]
-The left-shift operator `x << y` simply moves all the bits in `x` by `y` places to the left, filling the new gaps with zeros.
-Note that this is arithmetically identical to multiplying a number by `2**y`.
+The left-shift operator `x << y` moves all the bits in `x` by `y` places to the left, filling the new gaps with zeros.
+Note that this is arithmetically identical to multiplying a number by `(2**y)`.
The right-shift operator `x >> y` does the opposite.
-This is arithmetically identical to integer division `x // 2**y`.
+This is arithmetically identical to integer division `x // (2**y)`.
-Keep in mind the previous section on negative numbers and their pitfalls when shifting.
+Keep in mind the previous section on negative numbers and their pitfalls when shifting them in Python.
```python
@@ -191,7 +191,7 @@ Keep in mind the previous section on negative numbers and their pitfalls when sh
[symmetric-difference]: https://math.stackexchange.com/questions/84184/relation-between-xor-and-symmetric-difference#:~:text=It%20is%20the%20same%20thing,they%20are%20indeed%20the%20same.
[sympy]: https://docs.sympy.org/latest/modules/codegen.html#predefined-types
[tilde]: https://en.wikipedia.org/wiki/Tilde
-[twos-complement]: https://en.wikipedia.org/wiki/Two%27s_complement#:~:text=Two's%20complement%20is%20the%20most,number%20is%20positive%20or%20negative.
+[twos-complement]: https://en.wikipedia.org/wiki/Two%27s_complement
[unsigned-int-python]: https://stackoverflow.com/a/20768199
[xor-cipher]: https://en.wikipedia.org/wiki/XOR_cipher
[xor]: https://stackoverflow.com/a/2451393
diff --git a/concepts/bitwise-operators/introduction.md b/concepts/bitwise-operators/introduction.md
index 88aba3a6a7b..07833339ff2 100644
--- a/concepts/bitwise-operators/introduction.md
+++ b/concepts/bitwise-operators/introduction.md
@@ -1,19 +1,19 @@
# Introduction
-Down at the hardware level, transistors can only be on or off: two states that we traditionally represent with `1` and `0`.
+Down at the hardware level, [transistors can only be on or off][how-transistors-work]: two states that we traditionally represent with `1` and `0`.
These are the [`binary digits`][binary-digits], abbreviated as [`bits`][bits].
Awareness of `bits` and `binary` is particularly important for systems programmers working in low-level languages.
-
However, for most of the history of computing the programming priority has been to find increasingly sophisticated ways to _abstract away_ this binary reality.
In Python (and many other [high-level programming languages][high-level-language]), we work with `int`, `float`, `string` and other defined _types_, up to and including audio and video formats.
-We let the Python internals take care of (eventually) translating everything to bits.
+Python internals take care of (_eventually_) translating all the higher-level data to bits.
Nevertheless, using [bitwise-operators][python-bitwise-operators] and [bitwise operations][python-bitwise-operations] can sometimes have significant advantages in speed and memory efficiency, even in a high-level language like Python.
[high-level-language]: https://en.wikipedia.org/wiki/High-level_programming_language
+[how-transistors-work]: https://www.build-electronic-circuits.com/how-transistors-work/
[binary-digits]: https://www.khanacademy.org/computing/computers-and-internet/xcae6f4a7ff015e7d:digital-information/xcae6f4a7ff015e7d:binary-numbers/v/the-binary-number-system
[bits]: https://en.wikipedia.org/wiki/Bit
[python-bitwise-operations]: https://docs.python.org/3/reference/expressions.html#binary-bitwise-operations
diff --git a/concepts/bitwise-operators/links.json b/concepts/bitwise-operators/links.json
index 7c103c84630..ed251fab33a 100644
--- a/concepts/bitwise-operators/links.json
+++ b/concepts/bitwise-operators/links.json
@@ -1,8 +1,4 @@
[
- {
- "url": "https://wiki.python.org/moin/BitwiseOperators/",
- "description": "BitwiseOperators on the Python wiki."
- },
{
"url": "https://realpython.com/python-bitwise-operators",
"description": "Real Python: Bitwise Operators in Python."
diff --git a/concepts/bools/about.md b/concepts/bools/about.md
index a2680fc06b3..7015fdfafa4 100644
--- a/concepts/bools/about.md
+++ b/concepts/bools/about.md
@@ -1,6 +1,6 @@
# About
-Python represents true and false values with the [`bool`][bools] type, which is a subtype of `int`.
+Python represents true and false values with the [`bool`][bools] type, which is a subclass of `int`.
There are only two Boolean values in this type: `True` and `False`.
These values can be assigned to a variable and combined with the [Boolean operators][boolean-operators] (`and`, `or`, `not`):
@@ -22,10 +22,10 @@ Each of the operators has a different precedence, where `not` is evaluated befor
Brackets can be used to evaluate one part of the expression before the others:
```python
->>>not True and True
+>>> not True and True
False
->>>not (True and False)
+>>> not (True and False)
True
```
@@ -45,25 +45,25 @@ A few `built-ins` are always considered `False` by definition:
```python
->>>bool(None)
+>>> bool(None)
False
->>>bool(1)
+>>> bool(1)
True
->>>bool(0)
+>>> bool(0)
False
->>>bool([1,2,3])
+>>> bool([1,2,3])
True
->>>bool([])
+>>> bool([])
False
->>>bool({"Pig" : 1, "Cow": 3})
+>>> bool({"Pig" : 1, "Cow": 3})
True
->>>bool({})
+>>> bool({})
False
```
@@ -95,10 +95,10 @@ The `bool` type is implemented as a _sub-type_ of _int_.
```python
->>>1 == True
+>>> 1 == True
True
->>>0 == False
+>>> 0 == False
True
```
@@ -106,14 +106,14 @@ However, `bools` are **still different** from `ints`, as noted when comparing th
```python
->>>1 is True
+>>> 1 is True
False
->>>0 is False
+>>> 0 is False
False
```
-> Note: in python >= 3.8, using a literal (such as 1, '', [], or {}) on the _left side_ of `is` will raise a warning.
+> Note: in python >= 3.8, using a literal (such as `1`, `''`, `[]`, or `{}`) on the _left side_ of `is` will raise a warning.
It is considered a [Python anti-pattern][comparing to true in the wrong way] to use the equality operator to compare a boolean variable to `True` or `False`.
@@ -134,10 +134,8 @@ It is considered a [Python anti-pattern][comparing to true in the wrong way] to
```
-[bool-function]: https://docs.python.org/3/library/functions.html#bool
-[bool]: https://docs.python.org/3/library/stdtypes.html#truth
[Boolean-operators]: https://docs.python.org/3/library/stdtypes.html#boolean-operations-and-or-not
+[bool-function]: https://docs.python.org/3/library/functions.html#bool
+[bools]: https://docs.python.org/3/library/stdtypes.html#typebool
[comparing to true in the wrong way]: https://docs.quantifiedcode.com/python-anti-patterns/readability/comparison_to_true.html
[comparisons]: https://docs.python.org/3/library/stdtypes.html#comparisons
-
-[bools]: https://docs.python.org/3/library/stdtypes.html#typebool
\ No newline at end of file
diff --git a/concepts/bools/introduction.md b/concepts/bools/introduction.md
index af24137025e..85eb032df25 100644
--- a/concepts/bools/introduction.md
+++ b/concepts/bools/introduction.md
@@ -1,6 +1,6 @@
# Introduction
-Python represents true and false values with the [`bool`][bools] type, which is a subtype of `int`.
+Python represents true and false values with the [`bool`][bools] type, which is a subclass of `int`.
There are only two values under that type: `True` and `False`.
These values can be bound to a variable:
@@ -22,4 +22,4 @@ We can evaluate Boolean expressions using the `and`, `or`, and `not` operators.
>>> false_variable = not True
```
-[bools]: https://docs.python.org/3/library/stdtypes.html#typebool
\ No newline at end of file
+[bools]: https://docs.python.org/3/library/stdtypes.html#typebool
diff --git a/concepts/class-inheritance/about.md b/concepts/class-inheritance/about.md
index 5db7909e2c7..9f1bdf30cd9 100644
--- a/concepts/class-inheritance/about.md
+++ b/concepts/class-inheritance/about.md
@@ -7,7 +7,7 @@ In situations where only a small amount of functionality needs to be customized
`Inheritance` describes `is a kind of` relationship between two or more classes, abstracting common details into super (_base_ or _parent_) class and storing specific ones in the subclass (_derived class_ or _child class_).
-To create a child class, specify the parent class name inside the pair of parenthesis, followed by it's name.
+To create a child class, specify the parent class name inside the pair of parenthesis, followed by its name.
Example
```python
class Child(Parent):
diff --git a/concepts/classes/about.md b/concepts/classes/about.md
index f88ce892f3b..9b6a8a0dfb7 100644
--- a/concepts/classes/about.md
+++ b/concepts/classes/about.md
@@ -118,7 +118,7 @@ class MyClass:
def __init__(self, location):
# This is an instance or object property, attribute, or variable.
- # Note that we are unpacking the tuple argument into two seperate instance variables.
+ # Note that we are unpacking the tuple argument into two separate instance variables.
self.location_x = location[0]
self.location_y = location[1]
@@ -185,10 +185,10 @@ class Demo:
The moment that `