Skip to content

Commit d7231f4

Browse files
yawpitchkhoivan88DavidGervaaldracopaparomeo
authored andcommitted
Concept extraction / references mega merge
* Create common working area * Extract Concepts from v2 exercise: reverse-string * Create reverse-string.md * Update reverse-string.md * Add Concepts from v2 exercise: variable-length-quantity * Add first concepts group * Improved concepts as per PR review * Adds concept from binary-search-tree * Add initial list First pass concepts for `allergies` to address #460 * Initial list of concepts First pass list of concepts to address #459 * Add Concepts for v2 exercise: phone-number * Add phone-number Python concepts * Small update to index access and slice topics. * Add notes from review. - more information about classes, inheritance - flesh out privacy, public and non-public - clarify wording around iterables and index/slice access * One more note about brackets and strings. * Add Concepts for v2 exercise: hamming * Add concepts for hamming * Add note about tuple unpacking. * Add notes about polymorphism, builtins, and dunder methods. * Some whitespace fixes. * [WIP] `clock` exercise concepts. * Extract Concepts from v2 exercise: markdown * Initial commit for markdown exercise concepts. * Concept starter for markdown * Added detail to Markdown concepts * Final edits before harmonization Final Markdown edits before we merge and harmonize. * Add Concepts for v2 exercise: matrix * `matrix` exercise concepts (issue #386) First pass of concepts for `matrix ` exercise in python. Pretty sure this is too detailed, but wanted to get something for review before proceeding with additional exercises. * Edits to better match #290 Formatting Edited concepts to better match the formatting of issue #290 * Typo correction * added title * Extract Concepts from v2 exercise: rna-transcription * Beginning of Concepts for rna-transcription * More detailed concepts for rna-trranscription More detailed concepts for rna-transcription exrcise. * Added title * Extract Concepts from v2 exercise: robot-simulator * Beginning of concepts for robot-simulator. * WIP Concepts * Additional detail for concepts * Detail third pass Third pass on adding concept detail. * Additional detail for concepts. * Edits per PR Feedback Numerous spelling corrections. Additional edits to address comments from last review. * [WIP] Concept implementation instructions * Adds instructions for exercise implementation * Adds correction as per PR reviews * Harmonize, part 1 * fix relative links in references/README.md * First pass at harmonization Shifts all documents to a common format, adds minimal link tagging to the "concept" currently listed in each file. These will really need multiple more passes, as they diverge from each other even when describing the same topic. Many extraneous topics have crept in, added in an "aspirational" fashion to the exercises; we may need to trim some of that. * Pulling in examples from BethanyG * [WIP] Extracted concept unification * Unification of extracted concepts * Typos and duplicates remove * Duplicates concept unification * Concepts have now links to original file * Update languages/reference/README.md Co-Authored-By: Erik Schierboom <[email protected]> Co-authored-by: khoivan88 <[email protected]> Co-authored-by: David G <[email protected]> Co-authored-by: Ashley Drake <[email protected]> Co-authored-by: Pedro Romano <[email protected]> Co-authored-by: BethanyG <[email protected]> Co-authored-by: Erik Schierboom <[email protected]>
1 parent 453fcdd commit d7231f4

17 files changed

+932
-3
lines changed
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# PEP 8 Style
2+
3+
Unlike most earlier languages -- and many newer -- Python has an "official" style guide, and has had one for quite some time.
4+
5+
> One of [Python creator Guido von Rossum]'s key insights is that code is read much more often than it is written. The guidelines provided here are intended to improve the readability of code and make it consistent across the wide spectrum of Python code. As [PEP 20](zen_of_python.md) says, "Readability counts".
6+
7+
The various conventions within it might at times seem arbitrary, but they've been carefully chosen to enhance the readability of Python code, and should generally be adopted and adhered to unless explicitly overridden by a project-specific style guide, which itself should be a derivative of PEP 8.
8+
9+
## Tools
10+
11+
Various tools exist in the Python ecosystem for ensuring that your code doesn't grossly violate PEP 8 conventions. Currently the two most recommended (if opinionated) ones would be [Pylint](https://www.pylint.org/), which will analyze your code for style as well as logical errors, and [Black](https://black.readthedocs.io/en/stable/), which will autoformat your code to take the guesswork out of readability.
12+
13+
## Resources
14+
15+
- [PEP-8](https://www.python.org/dev/peps/pep-0008/)
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# Python Enhancement Proposals (PEPs)
2+
3+
Python is an incredibly popular language with a _great_ many users across an impressive number of domains; as such evolving the language is a complex undertaking that can't be rushed. The Python Enhancement Proposal (commonly known as PEP) process exists to provide a formal mechanism by which the community can propose, debate, vote on, and ultimately adopt significant changes to the language itself.
4+
5+
Even if you doubt you'll ever submit a PEP it's a good idea to keep abreast of what PEPs are out there and what changes are coming to a Python near you.
6+
7+
Two PEPs in particular will serve as a useful jumping off point:
8+
9+
- [PEP 0](https://www.python.org/dev/peps/) lists all current and historic PEPs.
10+
- [PEP 1](https://www.python.org/dev/peps/pep-0001/) explains the PEP process.

reference/concepts/pythonic.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Pythonic
2+
3+
An adjective used to describe well-constructed, high-quality Python code that is as easily understood and well designed as is possible for the task at hand. A piece of code that is "more Pythonic" will be easier to read and understand, and therefore more pleasurable to use, then "less Pythonic" code that accomplishes the same task.
4+
5+
A quality admired in a Pythonista -- the community's name for an adept Python user -- is the desire to always write code that is as Pythonic as possible.
6+
7+
## Qualities
8+
9+
Any given piece of code tends to be considered more Pythonic if it:
10+
11+
1. Adheres to the principles of the [Zen of Python](zen_of_python.md).
12+
1. Uses the current "best practice" idioms of the language, as the language and those practices evolve.
13+
1. Uses the common style conventions described in [PEP 8](pep_8_style_guide.md)
14+
15+
## Further Reading
16+
17+
- [What is Pythonic](https://blog.startifact.com/posts/older/what-is-pythonic.html)
18+
- [Python Guide](https://docs.python-guide.org/writing/style/)

reference/concepts/zen_of_python.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# The Zen of Python
2+
3+
The _Zen of Python_ by Tim Peters, and also known as [PEP-20](https://www.python.org/dev/peps/pep-0020/) is a philosophical statement of Python's foundational principles and ideals. It's neither exhaustive nor binding, but it's often quoted in whole or in part when there's any need to determine which of two functionally identical idioms or pieces of code is _better_ or more [Pythonic](pythonic.md).
4+
5+
- Beautiful is better than ugly.
6+
- Explicit is better than implicit.
7+
- Simple is better than complex.
8+
- Complex is better than complicated.
9+
- Flat is better than nested.
10+
- Sparse is better than dense.
11+
- Readability counts.
12+
- Special cases aren't special enough to break the rules.
13+
- Although practicality beats purity.
14+
- Errors should never pass silently.
15+
- Unless explicitly silenced.
16+
- In the face of ambiguity, refuse the temptation to guess.
17+
- There should be one-- and preferably only one --obvious way to do it.
18+
- Although that way may not be obvious at first unless you're Dutch.
19+
- Now is better than never.
20+
- Although never is often better than *right* now.
21+
- If the implementation is hard to explain, it's a bad idea.
22+
- If the implementation is easy to explain, it may be a good idea.
23+
- Namespaces are one honking great idea -- let's do more of those!
24+
25+
## Easter Egg
26+
27+
If you ever need a refresher, just `import this`. And if you need an example of code that is explicitly _not_ Zen, check out the source of [this](https://github.com/python/cpython/blob/master/Lib/this.py).
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
# Concepts of `allergies`
2+
3+
## Example implementation
4+
5+
After Python 3.4 an `enum.Flag` is the "one obvious" approach:
6+
7+
```python
8+
from enum import Flag, auto
9+
10+
class Allergens(Flag):
11+
eggs = auto()
12+
peanuts = auto()
13+
shellfish = auto()
14+
strawberries = auto()
15+
tomatoes = auto()
16+
chocolate = auto()
17+
pollen = auto()
18+
cats = auto()
19+
20+
class Allergies:
21+
22+
def __init__(self, score):
23+
mask = sum(a.value for a in Allergens)
24+
self.flags = Allergens(score & mask)
25+
26+
def allergic_to(self, item):
27+
return Allergens[item] in self.flags
28+
29+
@property
30+
def lst(self):
31+
return [a.name for a in Allergens if a in self.flags]
32+
```
33+
34+
In prior versions an OrderedDict was necessary to _reliably_ ensure sort order and also O(1) lookup:
35+
36+
```python
37+
from collections import OrderedDict
38+
39+
Allergens = OrderedDict(
40+
eggs = 1,
41+
peanuts = 2,
42+
shellfish = 4,
43+
strawberries = 8,
44+
tomatoes = 16,
45+
chocolate = 32,
46+
pollen = 64,
47+
cats = 128,
48+
)
49+
50+
class Allergies:
51+
52+
def __init__(self, score):
53+
mask = sum(Allergens.values())
54+
self.score = score & mask
55+
56+
def allergic_to(self, item):
57+
return bool(self.score & Allergens[item])
58+
59+
@property
60+
def lst(self):
61+
return [a for a in Allergens if self.allergic_to(a)]
62+
```
63+
64+
There are also various solutions involving lists, but these all come with O(N) lookup.
65+
66+
## Concepts
67+
68+
- [Classes][classes]: the exercise relies on the `class` statement to create a custom class
69+
- [Methods][methods]: the exercise relies on the `def` statement to create an instance method
70+
- [Implied Argument][implied-argument]: the exercise relies on the implied passing of `self` as the first parameter of bound methods
71+
- [Dunder Methods][dunder-methods]: the exercise relies on the `__init__` dunder method to control class instantiation
72+
- [Enumerated Values][enumerated-values]: the exercise relies on a fixed enumeration of possible values in a data structure
73+
- [Data Structures][data-structures]: the exercise requires the use of a collection like enum.Flag or collections.OrderedDict
74+
- [Imports][imports]: a reasonably readable solution will require importing from the standard library
75+
- [Powers of Two][powers-of-two]: the exercise relies on the use of powers of two in fundamental binary (bitwise) operations
76+
- [Bitflags][bitflags]: a general understanding of bitflags is required to solve this exercise
77+
- [Bitwise Operators][bitwise-operators]: this exercise relies on bitwise AND (`&`) and potentially bitwise LSHIFT (`<<`) to inspect the Boolean value of individual bits in a bitflag
78+
- [Property Decorator][property-decorator]: this exercise relies on the `@property` decorator to provide read-only dynamic access to the current list of allergens
79+
- [Membership Testing][membership-testing]: this exercise relies on testing membership of a value in a collection of values
80+
- [Lookup Efficiency][lookup-efficiency]: an efficient solution requires knowing that membership testing is O(1) in **dict** and the **enum.Enum** variants, but is O(N) in **list** and other sequential types
81+
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
# Concepts of binary-search-tree
2+
3+
## Example implementation
4+
5+
From the current [example.py](https://github.com/exercism/python/blob/master/exercises/binary-search-tree/example.py):
6+
7+
```python
8+
class TreeNode:
9+
def __init__(self, data, left=None, right=None):
10+
self.data = data
11+
self.left = left
12+
self.right = right
13+
14+
def __str__(self):
15+
fmt = 'TreeNode(data={}, left={}, right={})'
16+
return fmt.format(self.data, self.left, self.right)
17+
18+
19+
class BinarySearchTree:
20+
def __init__(self, tree_data):
21+
self.root = None
22+
for data in tree_data:
23+
self.add(data)
24+
25+
def add(self, data):
26+
if self.root is None:
27+
self.root = TreeNode(data)
28+
return
29+
inserted = False
30+
cur_node = self.root
31+
32+
while not inserted:
33+
if data <= cur_node.data:
34+
if cur_node.left:
35+
cur_node = cur_node.left
36+
else:
37+
cur_node.left = TreeNode(data)
38+
inserted = True
39+
elif data > cur_node.data:
40+
if cur_node.right:
41+
cur_node = cur_node.right
42+
else:
43+
cur_node.right = TreeNode(data)
44+
inserted = True
45+
46+
def _inorder_traverse(self, node, elements):
47+
if node is not None:
48+
self._inorder_traverse(node.left, elements)
49+
elements.append(node.data)
50+
self._inorder_traverse(node.right, elements)
51+
52+
def data(self):
53+
return self.root
54+
55+
def sorted_data(self):
56+
elements = []
57+
self._inorder_traverse(self.root, elements)
58+
return elements
59+
```
60+
61+
## Concepts
62+
63+
- [class][class]: a general comprehension of class concept and and how it works is required, `class` statement
64+
- [Implied Argument][implied-argument]: student needs to know how to use statement `self` in a class
65+
- [class members][class-members]: student must know how members of a class work
66+
- [class methods][class-methods]: student must know how methods of a class work inside and outside the class, the use and meaning of `def` statement
67+
- [arguments][arguments]: concept over arguments of a function and how to use them is required
68+
- [return value][return-value]: the knowledge of `return` statement could be a useful concept in this exercise
69+
- [Dunder Methods][dunder-methods]: student needs to know when to use dunder methods `__init__` and `__str__`
70+
- [overload][overload]: students need to overload methods and specifically dunder methods in this exercise
71+
- [Constructor][constructor]: student needs to know how to build an object using its constructor
72+
- [None][none]: student needs to know the meaning of `None` and how and when assign it to a variable
73+
- [Identity][identity]: the best way to check if an element is `None` is via the _identity_ operator, `is`
74+
- [Boolean][boolean]: concept required to solve the exercise
75+
- [in][in]: use of the `in` statement is useful to look for an object into a list
76+
- [for][for]: the `for ... in` concept is useful to loop over the lists
77+
- [Loops][loops]: concept required to solve the exercise
78+
- [Integer comparison][integer-comparison]: concept required to solve the exercise
79+
- [Recursion][recursion]: recursion is a core concept in this exercise
80+
- [Lists][lists]: knowledge of lists and iteration on lists is required for this exercise
81+
- [Conditional structures][conditional-structures]: knowledge of conditional conceptis and `if...else` statements are required
82+
- [Methods of list][methods-of-list]: the use of methods of list could be useful in this exercise. Methods like `append`, `pop`...
83+

reference/exercise-concepts/clock.md

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# Concepts of `clock`
2+
3+
# Example implementation
4+
5+
From the current [example.py](https://github.com/exercism/python/blob/master/exercises/clock/example.py):
6+
7+
```python
8+
class Clock:
9+
'Clock that displays 24 hour clock that rollsover properly'
10+
11+
def __init__(self, hour, minute):
12+
self.hour = hour
13+
self.minute = minute
14+
self.cleanup()
15+
16+
def __repr__(self):
17+
return "{:02d}:{:02d}".format(self.hour, self.minute)
18+
19+
def __eq__(self, other):
20+
return repr(self) == repr(other)
21+
22+
def __add__(self, minutes):
23+
self.minute += minutes
24+
return self.cleanup()
25+
26+
def __sub__(self, minutes):
27+
self.minute -= minutes
28+
return self.cleanup()
29+
30+
def cleanup(self):
31+
self.hour += self.minute // 60
32+
self.hour %= 24
33+
self.minute %= 60
34+
return self
35+
```
36+
37+
## Concepts
38+
39+
- [PEP 8 Style][pep-8-style]: PEP 8 is the Python official style guide. Black is emerging as the defacto "pyfmt" tool: should we recommend it? (since the advent of `gofmt` and then `rustfmt`, I'm totally sold on opinionated auto-format tools: saves time and no more bikeshedding)
40+
- [Constants][constants]: Avoid "magic numbers", defining instead meaningfully named constants. PEP 8 convention for constants: `UPPER_SNAKE_CASE`
41+
- [Classes][classes]: use of `class` to create a custom data structure
42+
- [Methods][methods]: use of `def` to define a class's methods
43+
- [Operator overloading][operator-overloading]: How to overload the `+` and `-` operators using the `__add__` and `__sub__` special methods.
44+
- [Rich comparison methods][rich-comparison-methods]: The `__eq__` method is overloaded
45+
- [String formatting][string-formatting]: How to format strings, ie `%` operator, `str.format`, f-strings
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# Concepts of `hamming`
2+
3+
## Example implementation
4+
5+
From the current [example.py](https://github.com/exercism/python/blob/master/exercises/hamming/example.py):
6+
7+
``` python
8+
def distance(s1, s2):
9+
if len(s1) != len(s2):
10+
raise ValueError("Sequences not of equal length.")
11+
12+
return sum(a != b for a, b in zip(s1, s2))
13+
```
14+
15+
## Concepts
16+
17+
- [Function definition][function-definition]: functions are defined and named using the `def` keyword
18+
- [Function signature][function-signature]: functions take named arguments which are accessible within the body of the function; this one requires the student to make a function that accepts 2
19+
- [Return value][return-value]: the function must return a number (int)
20+
- [Strings][strings]: strings are used generally
21+
- [Builtin functions][builtin-functions]: strings have a length, accessible by calling `len()`, a builtin python function
22+
- [Iterable][iterable]: strings are iterable, which provides a lot of opportunity to leverage Python functions against them
23+
- [Immutable][immutable]: strings are immutable (*immutability*)
24+
- [Booleans][booleans]: this solution uses Boolean values (`True` / `False`)
25+
- [Inequality][inequality]: this solution checks if `a` is not equal to `b`.
26+
- [Booleans are integers][booleans-are-integers]: Booleans values are just named aliases for the integers 1 (`True`) and 0 (`False`)
27+
- [Zip][zip]: builtin that joins multiple iterables into a single one
28+
- [Enumeration][enumeration]: `zip()` in this solution creates an iterable, which is iterated over by using the `for ... in ` syntax
29+
- [Sum][sum]: another builtin that operates on iterables
30+
- [Tuple unpacking][tuple-unpacking]: the values in an iterable can be unpacked into variables and used, i.e. `for a, b in zip(s1, s2)`
31+
- [Exception handling][exception-handling]: the exercise requires Exception handling
32+
- [Raise][raise]: the student is required to raise an `Exception` for incorrect input
33+
- [Exception hierarchy][exception-hierarchy]: the idiomatic `Exception` type is a `ValueError`, meaning the input is incorrect
34+
- [Exception catching][exception-catching]: `Exceptions` can be caught from outside the scope where they are raised, using the `try/except` syntax. All `Exceptions` types inherit from the base class, `Exception` and thus can be caught by either checking specifically for the type of Exception, or for any Exception
35+
- [Exception message][exception-message]: Custom error messages can (and should) be supplied to an Exception when raised
36+
- [Operators][operators]: `!=` is "not equal", which is not the same thing as `is`, or an identity check, but is the inverse of `==`, which is equality
37+
- [Loops][loops]: the `for ... in` syntax is useful for looping through a list or other iterable object
38+
- [Generators][generators]: generators calculate then `yield` a value one at a time, as opposed to lists which calculate and return all values in memory at once. A generator will pick up where it leaves off, and generate one item at a time, on demand
39+
- [Generator comprehension][generator-comprehension]: a generator comprehension is passed to `sum()` to drive summation without storing all the values in a list first
40+
- [Tuple unpacking][tuple-unpacking]: iterating through a list of tuples, i.e. [(1, 2), (2,3)], each piece of each tuple can be unpacked into a separate variable (syntax: `a, b = (1, 2)`); this works for any sort of iterable (lists, for example, and even strings!) but is commonly used with tuples because they are typically of a known size/length, and so can be safely unpacked into N variables, with names.
41+
- [Dunder Methods][dunder-methods]: "dunder" -> "double under", referring to the names of these methods being prefixed with two underscores, e.g. `__init__`. There is no formal privacy in Python, but conventionally a single underscore indicates a private method, or one that the programmer should assume may change at any time; methods without an underscore are considered part of an object's public API. Double underscores are even more special - they are used by Python's builtin functions like `len()`, for example, to allow objects to implement various interfaces and functionality. They can also be used for operator overloading. If you have a custom class that you would like to be able to compare to other instances of the same class, implementing `__lt__`, `__gt__`, `__eq__` etc. allow programmers to use the `>`, `<`, `=` operators. Dunder methods allow programmers to build useful objects with simple interfaces, i.e. you can add two instances together using `+` instead of writing something like `instance1.add(instance2)`.
42+
- [Builtin Function][builtin-functions]: Python has several handy builtin functions in the stdlib that can operate on many types of data, e.g. `len()`, `max()`, `min()`. Under the hood these are implemented via dunder methods - if an object (and everything in Python is an object) implements the correct dunder methods (see that topic for more information), it can support use in these functions. (For example, if an object implements `__len__`, the len(<object>) will return that value.) Because these functions are not strictly tied to any data type, they can be used almost anywhere, and will crop up again and again as we learn Python. Docs: https://docs.python.org/3/library/functions.html
43+
- [Polymorphism][polymorphism]: Python is "dynamically typed," meaning that variable names are bound to objects only, not to a particular type. You can assign `foo` to a string, and then reassign it to an `int` with no issues. "Polymorphism" formally means that different types respond to the same function - so the ability to add custom class instances together using `+`, for example, shows how Python can define the same function against different types.
44+
- [Duck Typing][duck-typing]: Python is also a good example of "Duck typing," to wit, "if it walks like a duck, talks like a duck, it's a duck.". This is accomplished partly with "magic" or "dunder" methods (double-under) that provide various interfaces to an object. If an object implements `__iter__` and `__next__`, it can be iterated through; it doesn't matter what type the object actually is.
45+

0 commit comments

Comments
 (0)