Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 43 additions & 32 deletions concepts/basics/about.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,16 +64,16 @@ 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))
<class 'str'>

>>> my_first_variable = 'You can call me "str".' # Strings can be declared using single or double quote marks.
>>> my_first_variable = 'You can call me "str".' # <--Strings can be declared using single or double quote marks.
>>> print(my_first_variable)
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))
<class 'collections.Counter'>

Expand Down Expand Up @@ -102,7 +102,7 @@ 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].
Expand All @@ -114,7 +114,7 @@ Statements for the _body_ of the function begin on the line following `def` and


```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)
Expand All @@ -126,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 "<stdin>", line 3
Expand Down Expand Up @@ -157,7 +157,7 @@ def add_two_numbers(number_one, number_two):
```

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 exercise.
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:


Expand Down Expand Up @@ -208,7 +208,7 @@ Dot (`.`) notation is used for calling functions defined inside a class or modul

```python
>>> def raise_to_power(number, power):
return number ** power
... return number ** power
...

>>> raise_to_power(3,3) # Invoking the function with the arguments 3 and 3.
Expand All @@ -225,12 +225,12 @@ 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 from the built-in str class on start_text.
>>> 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.
>>> 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).
Expand All @@ -239,9 +239,8 @@ TypeError: raise_to_power() missing 1 required positional argument: 'power'


# Importing the math module
import math

>>> math.pow(2,4) # Calling the pow() function from the math module
>>> import math
>>> math.pow(2,4) # <--Calling the pow() function from the math module.
Comment thread
BethanyG marked this conversation as resolved.
16.0
```

Expand Down Expand Up @@ -273,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:
Expand All @@ -297,31 +300,38 @@ Testing and `doctest` will be covered in a later concept.


```python
# An example on a user-defined function.
# 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.

:param number: int the base number.
:param power: int the power to raise the base number to.
:return: int - number raised to the specified 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 a number and raises it to the specified power, returning the result.
"""
"""

return number ** power
return number ** power
...

# Calling the .__doc__ attribute of the function and printing the result.
>>> print(raise_to_power.__doc__)
Raise a number to an arbitrary power.

:param number: int the base number.
:param power: int the power to raise the base number to.
:return: int - number raised to the specified power.
Parameters:
number (int): The base number.
power (int): The power to raise the base number to.

Takes a number and raises it to the specified power, 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 of the built-in type: str.
>>> print(str.__doc__)
Expand All @@ -333,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'.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was this statement just incorrect before? I think sys.getdefaultencoding() doesn't always return "utf-8".

Copy link
Copy Markdown
Member Author

@BethanyG BethanyG May 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this example is copied directly from the terminal after running print(str.__doc__), I am assuming that it changed between Python versions. Not positive, but I think that this bit was last touched on Exercism prior to Python 3.11.5, but I can't find it in the history. You might be able to find the .__doc__ change for str in the Python language repo or docs (careful! these default to Python 3.14, so you need to search by Python version) somewhere, but you'd have to dig by Python version. It is the Python docsring for the str class/type.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Huh... "utf-8" seems to have been the default as far back as Python 3.2, and the docs don't seem to specify the default before then. I wonder where the sys.getdefaultencoding() came from.

Copy link
Copy Markdown
Member Author

@BethanyG BethanyG May 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dunno. It might have been me or someone else running (unknowingly) a Python 2.7 version in an env. It's fixed now, tho. 🤷🏽‍♀️ These are the sorts of things that make me crazy when we upgrade the Python versions. 🙂 It's never "as simple as installing a new Python". 😉

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
Expand Down
44 changes: 25 additions & 19 deletions concepts/basics/introduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,20 +25,20 @@ A name can be reassigned (or re-bound) to different values (different object typ


```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))
<class 'int'>

>>> 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))
<class 'str'>

>>> my_first_variable = 'You can call me "str".' #<-- Strings can be declared using single or double quote marks.
>>> my_first_variable = 'You can call me "str".' # <--Strings can be declared using single or double quote marks.
>>> print(my_first_variable)
You can call me "str".
```
Expand All @@ -60,7 +60,7 @@ Statements for the _body_ of the function begin on the line following `def` and


```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)
Expand All @@ -72,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 "<stdin>", line 3
Expand Down Expand Up @@ -104,12 +104,11 @@ def add_two_numbers(number_one, number_two):


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 exercise.
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 will return `None`
def square_a_number(number):
square = number * number
Expand All @@ -131,8 +130,7 @@ Functions that omit `return` will also _implicitly_ return the [`None`][none] o
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
# This function omits a return keyword altogether.
def add_two_numbers(number_one, number_two):
result = number_one + number_two

Expand All @@ -158,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
Expand All @@ -190,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
Loading
Loading