diff --git a/.circleci/config.yml b/.circleci/config.yml deleted file mode 100644 index 3f5de212..00000000 --- a/.circleci/config.yml +++ /dev/null @@ -1,31 +0,0 @@ -version: 2.1 - -orbs: - python: circleci/python@2.1.1 - codecov: codecov/codecov@3.2.3 - -jobs: - build-and-test: - executor: python/default - steps: - - checkout - - python/install-packages: - pkg-manager: pip - - run: - command: flake8 - name: Lint - - run: - command: coverage run -m runner - name: Test - - run: - command: coverage xml -o /tmp/coverage.xml - name: Prepare coverage results - - store_artifacts: - path: /tmp/coverage.xml - - codecov/upload: - file: /tmp/coverage.xml - -workflows: - main: - jobs: - - build-and-test diff --git a/.editorconfig b/.editorconfig index bdbda7b8..3be246be 100644 --- a/.editorconfig +++ b/.editorconfig @@ -6,7 +6,7 @@ end_of_line = lf insert_final_newline = true trim_trailing_whitespace = true -[*.py] +[*.{py,toml,md}] indent_size = 4 indent_style = space diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 000a8182..38ab8116 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,4 +1,4 @@ -*Please read the [contributing guidelines](https://github.com/huangsam/ultimate-python/blob/master/CONTRIBUTING.md) before submitting a pull request.* +*Please read the [contributing guidelines](https://github.com/huangsam/ultimate-python/blob/main/CONTRIBUTING.md) before submitting a pull request.* --- diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000..4a24b3ee --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,45 @@ +name: CI + +on: + push: + branches: [main] + pull_request: + branches: [main] + +permissions: + contents: read + +jobs: + python-build: + name: Python + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v5 + - name: Set up Python 3.14 + uses: actions/setup-python@v6 + with: + python-version: '3.14' + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install -r requirements.txt + - name: Lint with ruff + run: | + ruff check + - name: Type check with mypy + run: | + mypy ultimatepython + - name: Run tests and report with coverage + run: | + coverage run runner.py + coverage report + - name: Generate coverage.xml artifact + run: | + coverage xml -o ./coverage.xml + - name: Upload coverage data to Codecov + uses: codecov/codecov-action@v4 + with: + files: ./coverage.xml + token: ${{ secrets.CODECOV_TOKEN }} diff --git a/.gitignore b/.gitignore index 18804740..d64421e7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,10 +1,19 @@ +# System +.DS_Store + +# IDE .idea/ -venv/ -__pycache__/ -*.egg-info/ -htmlcov/ +.vscode/ + +# Python *.pyc -.DS_Store .coverage -coverage.xml coverage.json +coverage.xml +*.egg-info/ +.ruff_cache/ +__pycache__/ +build/ +htmlcov/ +venv/ +brainstorm/ diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 00000000..e4efa791 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,58 @@ +# Quick orientation for AI coding agents + +## Key facts an agent must know (short): + +- The runner: `runner.py` dynamically imports every module under `ultimatepython` and runs any callable named `main` with zero parameters. Keep `main()` functions parameterless, idempotent, and side-effect safe for CI. +- Single-file runs are supported: modules are runnable with `python ultimatepython//.py`. Most modules already include `if __name__ == "__main__": main()`. +- Examples use plain Python stdlib only. Avoid adding new third-party dependencies without updating `requirements.txt` and `pyproject.toml`. +- Assertions are used as the primary verification mechanism inside examples (not pytest tests). Preserve their intent and messages when editing. + +## Patterns and conventions to follow + +- main() contract: must be a function, accept zero parameters, and not raise exceptions when run. The runner asserts the function is callable and has zero parameters. Example: `ultimatepython/syntax/function.py` and `ultimatepython/classes/basic_class.py`. +- Module structure: brief module docstring, helper functions/classes, then `main()` demonstrating usage via asserts, and final `if __name__ == "__main__": main()`. +- Avoid long-running or destructive operations in examples. If a module interacts with the filesystem (e.g., `advanced/file_handling.py`), keep operations local to ephemeral files (module uses `_TARGET_FILE = "sample.txt"`), and clean up after running. +- Typing: some modules include simple type hints; prefer to keep existing style and minimal typing additions only. +- Formatting & linting: the repo uses `ruff` and `isort` settings in `pyproject.toml`. Try to keep line-length <= 160 and maintain import ordering consistent with isort defaults. + +## When creating or modifying modules + +- Preserve the didactic nature: keep explanatory comments and short, clear examples. +- If you add new modules, include them under the appropriate folder and follow the same pattern (module docstring, helpers, `main()`, `if __name__...`). The runner will pick them up automatically. +- If a change requires a new dependency, add it to `requirements.txt` and update `pyproject.toml` before proposing a PR. + +## Top-level README files + +- The top-level `README.md` is the primary project landing page: it explains the repo goals, running instructions, and links to example modules (it also shows badges for CI and coverage). When changing top-level documentation, keep the runner guidance intact (it points to `runner.py`) and preserve any badges and links. +- Translated files like `README.ko.md`, `README.zh_tw.md`, `README.es.md`, `README.de.md`, `README.fr.md`, and `README.hi.md` are language variants of the same content. If you update the English `README.md`, consider updating translations or add a brief note in the PR explaining why translations were not updated. + +## Developer workflows and useful commands + +- Run all examples locally (fast smoke): + +```bash +python runner.py +``` + +- Run a single example (recommended when editing): + +```bash +python ultimatepython/syntax/function.py +``` + +- Check formatting/linting (ruff/isort configured in `pyproject.toml`): run your local ruff/isort commands or CI. +- Coverage config exists in `pyproject.toml` (coverage fail_under=80). The examples use assertions; running `runner.py` is a good quick coverage smoke. + +## Integration points & CI notes + +- CI expects that running `runner.py` and executing each `main()` will succeed. Avoid adding code that requires network access, long sleeps, or interactive input. +- Do not introduce external services or config files; this repo intentionally uses only the Python standard library. + +## Files and locations of interest (examples to inspect) + +- `runner.py` — how modules are discovered and executed (pkgutil.walk_packages + `main` lookups). +- `ultimatepython/syntax/*.py` — simple, illustrative examples of the `main()` pattern. +- `ultimatepython/advanced/*` — more involved examples; watch for filesystem or concurrency code (e.g., `advanced/file_handling.py`, `advanced/async.py`). +- `pyproject.toml` — linting/format settings and coverage rules. + +If anything in these instructions is unclear or you want additional examples (CI commands, recommended local dev Docker container, or a tiny unit-test harness), tell me which areas to expand and I'll iterate. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f043dc95..aaa87332 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,95 +1,126 @@ -# Contributing +# 🚀 Welcome to the Ultimate Python Study Guide! 📚 -Thanks for taking the time to understand how you can contribute to the -Ultimate Python Study guide! +🎉 Thank you for considering contributing to this awesome project! 🎉 -Please take a look at the [code of conduct](CODE_OF_CONDUCT.md) before -proceeding further. +But first, before you jump in, let's vibe with our [Code of Conduct](CODE_OF_CONDUCT.md). We want this space to be 🌈 inclusive, respectful, and nothing but fun! ---- +## 🐍 What's This All About? -The repository consists of documentation and Python modules. Before you -contribute to the repository with a pull request, review all of the standards -listed in upcoming sections. That way, you can maintain the craftsmanship of -this project and still make an impact on the developers using this project -for learning purposes. +Our Python Study Guide is your ticket to Python mastery! 🐍 This place is all about energy, excitement, and pure Python magic. 💫 -## README documentation +## 📖 Let's Talk Documentation -The [README](README.md) is important because it is the most frequently viewed -page in this repository. As such, any changes that are made to this page must -follow these guidelines: +Our README is like the opening act at a concert. It's where the party starts, and we want it to be sensational! Here are the keys to this performance: -- Translations are referenced at the top -- Python modules are referenced in the ToC -- External links point to HTTPS resources that return a `2xx` status -- Python documentation is useful for newcomers and professionals -- GitHub repositories have at least 1k stars -- Practice resources have Python exercises +- Translations? 🌍 Yes, they're right at the top for everyone to enjoy! +- Python modules? 🤓 Oh, they've got a VIP seat in our Table of Contents (ToC). +- External links? 🔗 They're all about HTTPS and that sweet `2xx` status. +- Python documentation? For both newbies and wizards, it's all in here! +- GitHub repositories? 🌟 We love stars! If it's got at least 1k stars, bring it on! +- Practice resources? 🏋️‍♂️ We've got Python exercises to keep you in shape. -## Python modules +## 📚 Get into Python Modules -Every Python module is a standalone lesson which helps developers build -their own intuition for core Python. Each module has a name that corresponds -to a topic and explores concepts with `assert` statements. This approach -encourages test-driven development and makes it simple for developers to -discern what the expected output from the code is. +Our Python modules are like mini-python-parties that you can host anywhere! They're packed with energy and make learning a blast! 🎉 -Certain Python concepts are skipped in this study guide because the modules -do not reference each other and make small use of I/O operations. But this -limitation also allows the lessons to be pasted freely to any computing -environment such as an IDE, a browser window or a standalone application. +### 🧩 The Setup -When creating or updating Python modules, please respect the guidelines in -the sub-sections below. - -### Standard structure - -Every standalone Python module consists of the following: +Each Python module follows a rock-solid structure: ```python -# Main function +# The main event 🎉 def main(): - # Assertion comments + # Here's where the magic happens! assert 1 + 1 == 2 assert True is not False - -# Main function conditional +# The show must go on if __name__ == "__main__": main() ``` -If the module involves additional functions and classes, they are placed -above the `main` function. +If there's more Python goodness, it's up front before the main event! -### Style conventions +### ✨ Style and Shine -The project follows conventions from these PEP proposals: +We've got style, oh baby! Check out the PEPs: -- [PEP 8 -- Style Guide for Python Code](https://www.python.org/dev/peps/pep-0008/) -- [PEP 257 -- Docstring Conventions](https://www.python.org/dev/peps/pep-0257/) +- [PEP 8](https://www.python.org/dev/peps/pep-0008) - Our fashion bible! +- [PEP 257](https://www.python.org/dev/peps/pep-0257) - Docstring Glamour! -The project has additional conventions: +But there's more! We have our own style: -- Module imports are arranged by [isort](https://github.com/timothycrosley/isort) -- Module constants follow an `_UNDER_SCORE_FIRST` convention -- Strings have "double-quotes" unless a `"` exists in the string -- Dynamic strings make use of [f-strings](https://www.python.org/dev/peps/pep-0498/) +- Imports are perfectly sorted with [isort](https://github.com/timothycrosley/isort). +- Constants? They follow the `_UNDER_SCORE_FIRST` party rule. +- Strings love double-quotes, but if there's a `"`, they'll use single quotes! +- For dynamic strings, it's all about those fabulous f-strings! 🎤 -### Code coverage +### 📈 Code Coverage Stars -Each module should have 80-100% code coverage with the [test runner](runner.py). -The reason for this high standard is that the repository code is relatively -simple. All interactive learning tends to revolve around the `main` function -since that is where the assertions are. That way, developers immediately know -when they make a mistake in the module. This is valuable feedback because it -helps them improve quickly. +We like to keep the energy high, and that means every module should have a whopping 80-100% code coverage! Our modules are like dance floors, and we don't want any empty spaces. That's because each module is a standalone lesson, and the `main` function is where the magic happens. -To validate code coverage, run the following commands: +## 🌟 Your Contribution -```bash -$ coverage run -m runner -$ coverage html -$ open htmlcov/index.html -``` +Your contributions are like the encore at a concert - they're a big deal! We appreciate your dedication to making this project even more amazing. Don't hesitate to reach out if you have any questions. Your contributions, no matter how small, are making a big difference in the Python learning world! + +So, get ready to rock and roll, Python style! 🤘🐍💥 + +# 💥 Dive into the Python World + +Python is a versatile language used in web development, data analysis, artificial intelligence, and more. As a contributor, you're joining a vibrant community of learners and mentors. + +# 🧑‍💻 Learning Together + +Our project isn't just a repository; it's a collaborative learning experience. You can learn from the contributions of others and share your Python wisdom with the world. Together, we can unlock the true potential of this fantastic language. + +# 🚀 Opportunities Galore + +When you contribute to this project, you're not just improving it; you're also enhancing your own skills. You might discover new Python tricks, learn more about best practices, and even find inspiration for your own projects. + +# 🌍 Global Impact + +Python is a worldwide phenomenon, and your contributions will impact Python enthusiasts globally. Your work can help someone on the other side of the planet learn Python, kickstart their career, or solve a problem they've been struggling with. + +# 🙋‍♀️ Join a Supportive Community + +Our community is welcoming and supportive. If you have questions or need guidance, don't hesitate to ask. We're all here to help each other and grow together. + +# 📢 Your Voice Matters + +Your unique perspective is valuable. If you have ideas to make this guide even more engaging or fun, share them with us! We're open to creative and innovative suggestions. + +# 🤖 Evolving with Python + +Python is constantly evolving, and so is our guide. You can help keep it up-to-date, ensuring that learners always have access to the latest Python features and best practices. + +# 🎉 Your Contribution Matters + +Your contributions, whether they are big or small, are the building blocks of our project's success. Together, we're creating a resource that makes Python more accessible and exciting. + +# 🌟 Be a Python Star + +By contributing to this project, you're becoming a Python star, and you're helping others shine brightly too. Let's light up the Python world together! + +## How to Contribute + +Ready to dive in? Here's how you can contribute: + +1. **Fork the Repository**: Head to [https://github.com/huangsam/ultimate-python/](https://github.com/huangsam/ultimate-python/) and click the "Fork" button in the top right corner. + +2. **Clone Your Fork**: After forking, you'll have your copy of the repository. Clone it to your local machine. + +3. **Make Your Contributions**: Create or update Python modules, documentation, or anything that adds value to the project. + +4. **Push Your Changes**: Once your work is ready, push your changes to your forked repository. + +5. **Create a Pull Request**: Head back to the original repository (https://github.com/huangsam/ultimate-python/) and create a pull request. Describe your changes and let us know why they're awesome. + +We're excited to see what you bring to the table! Your contributions are making the Python world a better place. + +Please don't hesitate to reach out if you have any questions. Your contributions, no matter how small, are making a big difference! 🌟🐍💥 + +## 🌍 README translations + +Please update `README.md` (English) first - it's the source of truth. If you can, mirror important changes like link updates in the corresponding `README..md` files so translations stay current. If you can't, no worries — just add a short note in your PR listing which translation files need updates. Thanks - your help keeps the docs welcoming for everyone! 🙏 + +## Feel the Pythonic Energy - Contribute Now! 🔥 diff --git a/README.de.md b/README.de.md index eb7dd51c..7ecfe09a 100644 --- a/README.de.md +++ b/README.de.md @@ -1,12 +1,12 @@ # Ultimativer Python-Lernführer -[![CircleCI](https://img.shields.io/circleci/build/github/huangsam/ultimate-python)](https://circleci.com/gh/huangsam/ultimate-python) +[![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/huangsam/ultimate-python/ci.yml)](https://github.com/huangsam/ultimate-python/actions) [![Code Coverage](https://img.shields.io/codecov/c/github/huangsam/ultimate-python)](https://codecov.io/gh/huangsam/ultimate-python) [![Quality Gate Status](https://img.shields.io/sonar/quality_gate/huangsam_ultimate-python?server=https%3A%2F%2Fsonarcloud.io)](https://sonarcloud.io/dashboard?id=huangsam_ultimate-python) -[![License](https://img.shields.io/github/license/huangsam/ultimate-python)](https://github.com/huangsam/ultimate-python/blob/master/LICENSE) -[![r/Python](https://img.shields.io/reddit/subreddit-subscribers/Python)](https://www.reddit.com/r/Python/comments/inllmf/ultimate_python_study_guide/) +[![License](https://img.shields.io/github/license/huangsam/ultimate-python)](https://github.com/huangsam/ultimate-python/blob/main/LICENSE) +[![r/Python](https://img.shields.io/badge/reddit-original_post-red)](https://www.reddit.com/r/Python/comments/inllmf/ultimate_python_study_guide/) -Der ultimative Python-Lernführer für Einsteiger und Profis gleichermaßen. :snake: :snake: :snake: +Der ultimative Python-Lernführer für Einsteiger und Profis gleichermaßen. 🐍 🐍 🐍 ```python print("Ultimativer Python-Lernführer") @@ -16,7 +16,12 @@ print("Ultimativer Python-Lernführer") [한국어](README.ko.md) | [繁体中文](README.zh_tw.md) | [Español](README.es.md) | -[Deutsch](README.de.md) +[Deutsch](README.de.md) | +[Français](README.fr.md) | +[हिन्दी](README.hi.md) | +[Português - Brasil](README.pt_br.md) + +Ultimate Python ## Motivation @@ -25,22 +30,22 @@ in den letzten 5 Jahren als Hochschulabsolvent, Angestellter in großen Unternehmen und als Open-Source-Mitarbeiter von Repositories wie [Celery](https://github.com/celery/celery) und [Full Stack Python](https://github.com/mattmakai/fullstackpython.com) weiterzugeben. -Ich freue mich darauf, dass noch mehr Menschen Python lernen und damit ihren Leidenschaften nachgehen. :mortar_board: +Ich freue mich darauf, dass noch mehr Menschen Python lernen und damit ihren Leidenschaften nachgehen. 🎓 ## Ziele Dies sind die Hauptziele bei der Erstellung dieses Leitfadens: -:trophy: **Als Ressource fungieren** für Python-Neulinge, die es vorziehen, praktisch zu lernen. +🏆 **Als Ressource fungieren** für Python-Neulinge, die es vorziehen, praktisch zu lernen. Dieses Repository enthält eine Sammlung von eigenständigen Modulen, die in einer IDE -wie [PyCharm](https://www.jetbrains.com/pycharm/) und im Browser wie -[Replit](https://replit.com/languages/python3). Wleches wie ein einfaches Terminal -mit den Beispielen funktioniert. Die meisten Zeilen haben sorgfältig ausgearbeitete Kommentare, die den Leser -Schritt für Schritt durch das Programm führen. Die Benutzer werden ermutigt, den -Quellcode überall zu ändern, solange die "Haupt"-Routinen nicht gelöscht werden und -[run successfully](runner.py) nach jeder Änderung. - -:trophy: **Als reiner Leitfaden dienen** für diejenigen, die die wichtigsten Python-Konzepte wiederholen möchten. + wie [PyCharm](https://www.jetbrains.com/pycharm/) oder im Browser via + [Replit](https://replit.com/languages/python3) ausgeführt werden können. Ein Terminal funktioniert + ebenfalls gut für die Beispiele. Die meisten Zeilen enthalten sorgfälltig formulierte Kommentare, die den Leser + Schritt für Schritt durch die Abläufe führen. Benutzer werden ermutigt, den Quellcode zu ändern, + sofern die `main`-Routinen nicht entfernt werden und die Programme nach Änderungen weiterhin erfolgreich + ausgeführt werden (siehe `runner.py`). + +🏆 **Als reiner Leitfaden dienen** für diejenigen, die die wichtigsten Python-Konzepte wiederholen möchten. Wo nur [builtin libraries](https://docs.python.org/3/library/) genutzt werden, so dass diese Konzepte ohne den Overhead der bereichsspezifischen Konzepte vermittelt werden können. Als beliebte Open-Source-Bibliotheken und -Frameworks (d.h. `sqlalchemy`, `requests`, @@ -65,83 +70,122 @@ Es gibt zwei Möglichkeiten, die Module auszuführen: ## Inhaltsübersicht -:books: = Externe Ressource, -:cake: = Thema für Anfänger, -:exploding_head: = Fortgeschrittenes Thema +📚 = Externe Ressource, +🍰 = Thema für Anfänger, +🤯 = Fortgeschrittenes Thema 1. **Über Python** - - Overview: [What is Python](https://github.com/trekhleb/learn-python/blob/master/src/getting_started/what_is_python.md) (:books:, :cake:) - - Design philosophy: [The Zen of Python](https://www.python.org/dev/peps/pep-0020/) (:books:) - - Style guide: [Style Guide for Python Code](https://www.python.org/dev/peps/pep-0008/) (:books:, :exploding_head:) - - Data model: [Data model](https://docs.python.org/3/reference/datamodel.html) (:books:, :exploding_head:) - - Standard library: [The Python Standard Library](https://docs.python.org/3/library/) (:books:, :exploding_head:) - - Built-in functions: [Built-in Functions](https://docs.python.org/3/library/functions.html) (:books:) + - Overview: [What is Python](https://github.com/trekhleb/learn-python/blob/master/src/getting_started/what_is_python.md) ( 📚, 🍰 ) + - Design philosophy: [The Zen of Python](https://www.python.org/dev/peps/pep-0020/) ( 📚 ) + - Style guide: [Style Guide for Python Code](https://www.python.org/dev/peps/pep-0008/) ( 📚, 🤯 ) + - Data model: [Data model](https://docs.python.org/3/reference/datamodel.html) ( 📚, 🤯 ) + - Standard library: [The Python Standard Library](https://docs.python.org/3/library/) ( 📚, 🤯 ) + - Built-in functions: [Built-in Functions](https://docs.python.org/3/library/functions.html) ( 📚 ) 2. **Syntax** - - Variable: [Built-in literals](ultimatepython/syntax/variable.py) (:cake:) - - Expression: [Numeric operations](ultimatepython/syntax/expression.py) (:cake:) - - Conditional: [if | if-else | if-elif-else](ultimatepython/syntax/conditional.py) (:cake:) - - Loop: [for-loop | while-loop](ultimatepython/syntax/loop.py) (:cake:) - - Function: [def | lambda](ultimatepython/syntax/function.py) (:cake:) + - Variable: [Built-in literals](ultimatepython/syntax/variable.py) ( 🍰 ) + - Expression: [Numeric operations](ultimatepython/syntax/expression.py) ( 🍰 ) + - Bitwise: [Bitwise operators](ultimatepython/syntax/bitwise.py) ( 🍰 ), [One's/Two's Complement](https://www.geeksforgeeks.org/difference-between-1s-complement-representation-and-2s-complement-representation-technique/) ( 📚 ) + - Conditional: [if | if-else | if-elif-else](ultimatepython/syntax/conditional.py) ( 🍰 ) + - Loop: [for-loop | while-loop](ultimatepython/syntax/loop.py) ( 🍰 ) + - Function: [def | lambda](ultimatepython/syntax/function.py) ( 🍰 ) + - Walrus operator: [Assignment expressions :=](ultimatepython/syntax/walrus_operator.py) ( 🤯 ) + - Argument enforcement: [Positional-only / | Keyword-only *](ultimatepython/syntax/arg_enforcement.py) ( 🤯 ) 3. **Daten-Strukturen** - - List: [List operations](ultimatepython/data_structures/list.py) (:cake:) + - List: [List operations](ultimatepython/data_structures/list.py) ( 🍰 ) - Tuple: [Tuple operations](ultimatepython/data_structures/tuple.py) - Set: [Set operations](ultimatepython/data_structures/set.py) - - Dict: [Dictionary operations](ultimatepython/data_structures/dict.py) (:cake:) + - Dict: [Dictionary operations](ultimatepython/data_structures/dict.py) ( 🍰 ) + - Dict union: [Dictionary merge | and |=](ultimatepython/data_structures/dict_union.py) ( 🤯 ) - Comprehension: [list | tuple | set | dict](ultimatepython/data_structures/comprehension.py) - - String: [String operations](ultimatepython/data_structures/string.py) (:cake:) - - Deque: [deque](ultimatepython/data_structures/deque.py) (:exploding_head:) - - Time complexity: [cPython operations](https://wiki.python.org/moin/TimeComplexity) (:books:, :exploding_head:) + - String: [String operations](ultimatepython/data_structures/string.py) ( 🍰 ) + - Deque: [deque](ultimatepython/data_structures/deque.py) ( 🤯 ) + - Namedtuple: [namedtuple](ultimatepython/data_structures/namedtuple.py) ( 🤯 ) + - Defaultdict: [defaultdict](ultimatepython/data_structures/defaultdict.py) ( 🤯 ) + - Iterator-Tools: [Iterator-Tools](ultimatepython/data_structures/itertools.py) ( 🤯 ) + - Time complexity: [cPython operations](https://wiki.python.org/moin/TimeComplexity) ( 📚, 🤯 ) 4. **Klassen** - - Basic class: [Basic definition](ultimatepython/classes/basic_class.py) (:cake:) + - Basic class: [Basic definition](ultimatepython/classes/basic_class.py) ( 🍰 ) + - Inheritance: [Inheritance](ultimatepython/classes/inheritance.py) ( 🍰 ) - Abstract class: [Abstract definition](ultimatepython/classes/abstract_class.py) - Exception class: [Exception definition](ultimatepython/classes/exception_class.py) - - Iterator class: [Iterator definition | yield](ultimatepython/classes/iterator_class.py) (:exploding_head:) + - Iterator class: [Iterator definition | yield](ultimatepython/classes/iterator_class.py) ( 🤯 ) + - Encapsulation: [Encapsulation definition](ultimatepython/classes/encapsulation.py) 5. **Fortgeschrittene** - - Decorator: [Decorator definition | wraps](ultimatepython/advanced/decorator.py) (:exploding_head:) - - Context manager: [Context managers](ultimatepython/advanced/context_manager.py) (:exploding_head:) - - Method resolution order: [mro](ultimatepython/advanced/mro.py) (:exploding_head:) - - Mixin: [Mixin definition](ultimatepython/advanced/mixin.py) (:exploding_head:) - - Metaclass: [Metaclass definition](ultimatepython/advanced/meta_class.py) (:exploding_head:) - - Thread: [ThreadPoolExecutor](ultimatepython/advanced/thread.py) (:exploding_head:) - - Asyncio: [async | await](ultimatepython/advanced/async.py) (:exploding_head:) - - Weak reference: [weakref](ultimatepython/advanced/weak_ref.py) (:exploding_head:) - - Benchmark: [cProfile | pstats](ultimatepython/advanced/benchmark.py) (:exploding_head:) - - Mocking: [MagicMock | PropertyMock | patch](ultimatepython/advanced/mocking.py) (:exploding_head:) - - Regular expression: [search | findall | match | fullmatch](ultimatepython/advanced/regex.py) (:exploding_head:) - - Data format: [json | xml | csv](ultimatepython/advanced/data_format.py) (:exploding_head:) - - Datetime: [datetime | timezone](ultimatepython/advanced/date_time.py) (:exploding_head:) + - Decorator: [Decorator definition | wraps](ultimatepython/advanced/decorator.py) ( 🤯 ) + - File Handling: [File Handling](ultimatepython/advanced/file_handling.py) ( 🤯 ) + - Context manager: [Context managers](ultimatepython/advanced/context_manager.py) ( 🤯 ) + - Method resolution order: [mro](ultimatepython/advanced/mro.py) ( 🤯 ) + - Mixin: [Mixin definition](ultimatepython/advanced/mixin.py) ( 🤯 ) + - Metaclass: [Metaclass definition](ultimatepython/advanced/meta_class.py) ( 🤯 ) + - Thread: [ThreadPoolExecutor](ultimatepython/advanced/thread.py) ( 🤯 ) + - Asyncio: [async | await](ultimatepython/advanced/async.py) ( 🤯 ) + - Weak reference: [weakref](ultimatepython/advanced/weak_ref.py) ( 🤯 ) + - Benchmark: [cProfile | pstats](ultimatepython/advanced/benchmark.py) ( 🤯 ) + - Mocking: [MagicMock | PropertyMock | patch](ultimatepython/advanced/mocking.py) ( 🤯 ) + - Regular expression: [search | findall | match | fullmatch](ultimatepython/advanced/regex.py) ( 🤯 ) + - Data format: [json | xml | csv](ultimatepython/advanced/data_format.py) ( 🤯 ) + - Datetime: [datetime | timezone](ultimatepython/advanced/date_time.py) ( 🤯 ) + - Pattern Matching: [match | case](ultimatepython/advanced/pattern_matching.py) ( 🤯 ) ## Zusätzliche Ressourcen -:necktie: = Interview-Ressource, -:test_tube: = Code-Beispiele, -:brain: = Projektideen +👔 = Interview-Ressource, +🧪 = Code-Beispiele, +🧠 = Projektideen ### GitHub repositories Lernen Sie weiter, indem Sie von anderen Quellen lesen. -- [TheAlgorithms/Python](https://github.com/TheAlgorithms/Python) (:necktie:, :test_tube:) -- [faif/python-patterns](https://github.com/faif/python-patterns) (:necktie:, :test_tube:) -- [geekcomputers/Python](https://github.com/geekcomputers/Python) (:test_tube:) -- [trekhleb/homemade-machine-learning](https://github.com/trekhleb/homemade-machine-learning) (:test_tube:) -- [karan/Projects](https://github.com/karan/Projects) (:brain:) -- [MunGell/awesome-for-beginners](https://github.com/MunGell/awesome-for-beginners) (:brain:) +- [TheAlgorithms/Python](https://github.com/TheAlgorithms/Python) ( 👔 , 🧪 ) +- [faif/python-patterns](https://github.com/faif/python-patterns) ( 👔 , 🧪 ) +- [geekcomputers/Python](https://github.com/geekcomputers/Python) ( 🧪 ) +- [trekhleb/homemade-machine-learning](https://github.com/trekhleb/homemade-machine-learning) ( 🧪 ) +- [karan/Projects](https://github.com/karan/Projects) ( 🧠 ) +- [MunGell/awesome-for-beginners](https://github.com/MunGell/awesome-for-beginners) ( 🧠 ) - [vinta/awesome-python](https://github.com/vinta/awesome-python) - [academic/awesome-datascience](https://github.com/academic/awesome-datascience) - [josephmisiti/awesome-machine-learning](https://github.com/josephmisiti/awesome-machine-learning) - [ZuzooVn/machine-learning-for-software-engineers](https://github.com/ZuzooVn/machine-learning-for-software-engineers) -- [30-seconds/30-seconds-of-python](https://github.com/30-seconds/30-seconds-of-python) (:test_tube:) +- [30-seconds/30-seconds-of-python](https://github.com/30-seconds/30-seconds-of-python) ( 🧪 ) - [ml-tooling/best-of-python](https://github.com/ml-tooling/best-of-python) +- [practical-tutorials/project-based-learning](https://github.com/practical-tutorials/project-based-learning#python) +- [freeCodeCamp/freeCodeCamp](https://github.com/freeCodeCamp/freeCodeCamp) ( 👔 ) +- [microsoft/ML-For-Beginners](https://github.com/microsoft/ML-For-Beginners) ( 🧪 ) +- [microsoft/Data-Science-For-Beginners](https://github.com/microsoft/Data-Science-For-Beginners) ( 🧪 ) +- [Avik-Jain/100-Days-Of-ML-Code](https://github.com/Avik-Jain/100-Days-Of-ML-Code) ( 🧪 ) + +### Projekte des Autors + +Projekte, die ich mit Python erstellt habe und die zeigen, was man nach dem Erlernen dieser Konzepte erstellen kann: + +- [huangsam/chowist](https://github.com/huangsam/chowist) ( 🧪 ) +- [huangsam/githooks](https://github.com/huangsam/githooks) ( 🧪 ) +- [huangsam/ragchain](https://github.com/huangsam/ragchain) ( 🧪 ) +- [huangsam/mailprune](https://github.com/huangsam/mailprune) ( 🧪 ) ### Interaktive Übungen Üben Sie weiter, damit Ihre Programmierkenntnisse nicht einrosten. -- [leetcode.com](https://leetcode.com/) (:necktie:) -- [hackerrank.com](https://www.hackerrank.com/) (:necktie:) -- [kaggle.com](https://www.kaggle.com/) (:brain:) +- [codechef.com](https://www.codechef.com/) ( 👔 ) +- [codeforces.com](https://codeforces.com/) +- [codementor.io](https://www.codementor.io) ( 🧠 ) +- [coderbyte.com](https://www.coderbyte.com/) ( 👔 ) +- [codewars.com](https://www.codewars.com/) - [exercism.io](https://exercism.io/) +- [geeksforgeeks.org](https://www.geeksforgeeks.org/) ( 👔 ) +- [hackerearth.com](https://www.hackerearth.com/) +- [hackerrank.com](https://www.hackerrank.com/) ( 👔 ) +- [kaggle.com](https://www.kaggle.com/) ( 🧠 ) +- [labex.io](https://labex.io/exercises/python)( 🧪 ) +- [leetcode.com](https://leetcode.com/) ( 👔 ) - [projecteuler.net](https://projecteuler.net/) -- [DevProjects](https://www.codementor.io/projects/python) -- [codewars.com](https://www.codewars.com/) +- [replit.com](https://replit.com/) +- [w3schools.com](https://www.w3schools.com/python/) ( 🧪 ) +- [teclado.com](https://teclado.com/30-days-of-python/#prerequisites) ( 👔 ) +- [fullstakpython.org](https://fullstackpython.org/) ( 🧪 ) + +## Sternengucker der Zeit + +[![Stargazers over time](https://starchart.cc/huangsam/ultimate-python.svg?variant=adaptive)](https://starchart.cc/huangsam/ultimate-python) diff --git a/README.es.md b/README.es.md index 57dad2d1..138ad36e 100644 --- a/README.es.md +++ b/README.es.md @@ -1,12 +1,12 @@ # Guía de estudio "Python Definitivo" -[![CircleCI](https://img.shields.io/circleci/build/github/huangsam/ultimate-python)](https://circleci.com/gh/huangsam/ultimate-python) +[![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/huangsam/ultimate-python/ci.yml)](https://github.com/huangsam/ultimate-python/actions) [![Code Coverage](https://img.shields.io/codecov/c/github/huangsam/ultimate-python)](https://codecov.io/gh/huangsam/ultimate-python) [![Quality Gate Status](https://img.shields.io/sonar/quality_gate/huangsam_ultimate-python?server=https%3A%2F%2Fsonarcloud.io)](https://sonarcloud.io/dashboard?id=huangsam_ultimate-python) -[![License](https://img.shields.io/github/license/huangsam/ultimate-python)](https://github.com/huangsam/ultimate-python/blob/master/LICENSE) -[![r/Python](https://img.shields.io/reddit/subreddit-subscribers/Python)](https://www.reddit.com/r/Python/comments/inllmf/ultimate_python_study_guide/) +[![License](https://img.shields.io/github/license/huangsam/ultimate-python)](https://github.com/huangsam/ultimate-python/blob/main/LICENSE) +[![r/Python](https://img.shields.io/badge/reddit-original_post-red)](https://www.reddit.com/r/Python/comments/inllmf/ultimate_python_study_guide/) -Guía de estudio "Python Definitivo" para principiantes y profesionales. :snake: :snake: :snake: +Guía de estudio "Python Definitivo" para principiantes y profesionales. 🐍 🐍 🐍 ```python print("Guía de estudio 'Python Definitivo'") @@ -16,40 +16,44 @@ print("Guía de estudio 'Python Definitivo'") [한국어](README.ko.md) | [繁体中文](README.zh_tw.md) | [Español](README.es.md) | -[Deutsch](README.de.md) +[Deutsch](README.de.md) | +[Français](README.fr.md) | +[हिन्दी](README.hi.md) | +[Português - Brasil](README.pt_br.md) + +Ultimate Python ## Motivación Creé este repositorio de GitHub para compartir lo que he aprendido sobre [Python](https://www.python.org/) -durante más de 5 años usándolo como graduado de universidad, empleado en grandes empresas y como contribuidor -de código abierto en repositorios como [Celery](https://github.com/celery/celery) y +durante más de 5 años usándolo como graduado de universidad, empleado en grandes empresas y como contribuidor +de código abierto en repositorios como [Celery](https://github.com/celery/celery) y [Full Stack Python](https://github.com/mattmakai/fullstackpython.com). -Espero ver a más personas aprendiendo Python y persiguiendo su pasión a través de él. :mortar_board: +Espero ver a más personas aprendiendo Python y persiguiendo su pasión a través de él. 🎓 ## Objetivos Estos son los objetivos principales de esta guía: -:trophy: **Servir como un recurso** para principiantes de Python que prefieren aprender por su cuenta. -Este repositorio enumera una colección de módulos independientes que pueden ser ejecutados en -un IDE como [PyCharm](https://www.jetbrains.com/pycharm/) e incluso en el navegador, como -[Repl.it](https://repl.it/languages/python3). Incluso una terminal antigua funcionará igual de bien -con los ejemplos. La mayoría de las líneas de código tienen comentarios útiles que ayudan a guiar -al lector para entender paso a paso el proceso que el programa está ejecutando. Se anima a los usuarios -a que modifiquen el código fuente en cualquier parte siempre y cuando las rutinas principales (`main`) -se eliminen y se [ejecuten con éxito](runner.py) tras cada cambio. +🏆 **Servir como un recurso** para principiantes de Python que prefieren aprender de forma práctica. +Este repositorio contiene una colección de módulos independientes que pueden ejecutarse en +un IDE como [PyCharm](https://www.jetbrains.com/pycharm/) y en el navegador, como +[Replit](https://replit.com/languages/python3). Incluso una terminal sencilla funcionará con los ejemplos. +La mayoría de las líneas de código tienen comentarios útiles que guían al lector paso a paso. +Se anima a los usuarios a modificar el código fuente en cualquier parte siempre y cuando las rutinas +principales (`main`) no se eliminen y los programas se ejecuten con éxito tras cada cambio (ver `runner.py`). -:trophy: **Servir como una guía pura** para aquellos que quieren reforzar los conceptos base de +🏆 **Servir como una guía pura** para aquellos que quieren reforzar los conceptos base de Python. Se utilizan sólo las [librerías integradas](https://docs.python.org/3/library/) para que estos conceptos puedan adquirirse sin el esfuerzo de aprender conocimientos de dominios específicos. -Por ello no se han instalado librerías y entornos de código abierto populares (como `sqlalchemy`, +Por ello no se han instalado librerías y entornos de código abierto populares (como `sqlalchemy`, `requests`, `pandas`). No obstante, leer el código fuente de estos frameworks es inspirador y altamente recomendado si tu objetivo es convertirte en un verdadero [Pythonista](https://www.urbandictionary.com/define.php?term=pythonista). ## Empezando -[![Run on Repl.it](https://repl.it/badge/github/huangsam/ultimate-python)](https://repl.it/github/huangsam/ultimate-python) +[![Run on Replit](https://replit.com/badge/github/huangsam/ultimate-python)](https://replit.com/github/huangsam/ultimate-python) Haz clic en la imagen de arriba para crear un ambiente de trabajo en el navegador sin necesidad de tener Git y Python instalados en tu ordenador local. Si estos requisitos ya se cumplen, @@ -64,83 +68,122 @@ Hay dos maneras de ejecutar los módulos: ## Contenido -:books: = Recurso externo, -:cake: = Tema principiante, -:exploding_head: = Tema avanzado +📚 = Recurso externo, +🍰 = Tema principiante, +🤯 = Tema avanzado 1. **Sobre Python** - - Resumen: [¿Qué es Python?](https://github.com/trekhleb/learn-python/blob/master/src/getting_started/what_is_python.md) (:books:, :cake:) - - Filosofía de diseño: [El Zen de Python](https://www.python.org/dev/peps/pep-0020/) (:books:) - - Guía de estilos: [Guía de estilos para código de Python](https://www.python.org/dev/peps/pep-0008/) (:books:, :exploding_head:) - - Modelo de datos: [Modelo de datos](https://docs.python.org/3/reference/datamodel.html) (:books:, :exploding_head:) - - Librería estándar: [La librería estándar de Python](https://docs.python.org/3/library/) (:books:, :exploding_head:) - - Funciones integradas: [Funciones integradas](https://docs.python.org/3/library/functions.html) (:books:) + - Resumen: [¿Qué es Python?](https://github.com/trekhleb/learn-python/blob/master/src/getting_started/what_is_python.md) ( 📚, 🍰 ) + - Filosofía de diseño: [El Zen de Python](https://www.python.org/dev/peps/pep-0020/) ( 📚 ) + - Guía de estilos: [Guía de estilos para código de Python](https://www.python.org/dev/peps/pep-0008/) ( 📚, 🤯 ) + - Modelo de datos: [Modelo de datos](https://docs.python.org/3/reference/datamodel.html) ( 📚, 🤯 ) + - Librería estándar: [La librería estándar de Python](https://docs.python.org/3/library/) ( 📚, 🤯 ) + - Funciones integradas: [Funciones integradas](https://docs.python.org/3/library/functions.html) ( 📚 ) 2. **Sintaxis** - - Variables: [Literales integrados](ultimatepython/syntax/variable.py) (:cake:) - - Expresiones: [Operaciones numéricas](ultimatepython/syntax/expression.py) (:cake:) - - Condicionales: [if | if-else | if-elif-else](ultimatepython/syntax/conditional.py) (:cake:) - - Iteraciones: [for-loop | while-loop](ultimatepython/syntax/loop.py) (:cake:) - - Funciones: [def | lambda](ultimatepython/syntax/function.py) (:cake:) + - Variables: [Literales integrados](ultimatepython/syntax/variable.py) ( 🍰 ) + - Expresiones: [Operaciones numéricas](ultimatepython/syntax/expression.py) ( 🍰 ) + - Bit a bit: [Operadores bit a bit](ultimatepython/syntax/bitwise.py) ( 🍰 ), [Complemento a uno/dos](https://www.geeksforgeeks.org/difference-between-1s-complement-representation-and-2s-complement-representation-technique/) ( 📚 ) + - Condicionales: [if | if-else | if-elif-else](ultimatepython/syntax/conditional.py) ( 🍰 ) + - Iteraciones: [for-loop | while-loop](ultimatepython/syntax/loop.py) ( 🍰 ) + - Funciones: [def | lambda](ultimatepython/syntax/function.py) ( 🍰 ) + - Operador morsa: [Expresiones de asignación :=](ultimatepython/syntax/walrus_operator.py) ( 🤯 ) + - Aplicación de argumentos: [Solo posicional / | Solo palabra clave *](ultimatepython/syntax/arg_enforcement.py) ( 🤯 ) 3. **Estructura de datos** - - Lista: [Operaciones con listas](ultimatepython/data_structures/list.py) (:cake:) + - Lista: [Operaciones con listas](ultimatepython/data_structures/list.py) ( 🍰 ) - Tupla: [Operaciones con tuplas](ultimatepython/data_structures/tuple.py) - Set: [Operaciones con sets](ultimatepython/data_structures/set.py) - - Diccionario: [Operaciones con dicts](ultimatepython/data_structures/dict.py) (:cake:) + - Diccionario: [Operaciones con dicts](ultimatepython/data_structures/dict.py) ( 🍰 ) + - Unión de diccionarios: [Fusión de diccionarios | y |=](ultimatepython/data_structures/dict_union.py) ( 🤯 ) - Comprensión: [list | tuple | set | dict](ultimatepython/data_structures/comprehension.py) - - Cadena: [Operaciones con strings](ultimatepython/data_structures/string.py) (:cake:) - - Deque: [deque](ultimatepython/data_structures/deque.py) (:exploding_head:) - - Complejidad de tiempo: [Operaciones de cPython](https://wiki.python.org/moin/TimeComplexity) (:books:, :exploding_head:) + - Cadena: [Operaciones con strings](ultimatepython/data_structures/string.py) ( 🍰 ) + - Deque: [deque](ultimatepython/data_structures/deque.py) ( 🤯 ) + - Namedtuple: [namedtuple](ultimatepython/data_structures/namedtuple.py) ( 🤯 ) + - Defaultdict: [defaultdict](ultimatepython/data_structures/defaultdict.py) ( 🤯 ) + - Herramientas de iteradores: [Herramientas de iteradores](ultimatepython/data_structures/itertools.py) ( 🤯 ) + - Complejidad de tiempo: [Operaciones de cPython](https://wiki.python.org/moin/TimeComplexity) ( 📚, 🤯 ) 4. **Clases** - - Clase básica: [Definición de básica](ultimatepython/classes/basic_class.py) (:cake:) + - Clase básica: [Definición de básica](ultimatepython/classes/basic_class.py) ( 🍰 ) + - Herencia: [Herencia](ultimatepython/classes/inheritance.py) ( 🍰 ) - Clase abstracta: [Definición de abstracta](ultimatepython/classes/abstract_class.py) - - Clase de excepción: [Defición de excepción](ultimatepython/classes/exception_class.py) - - Clase iteradora: [Definición de iteradora | yield](ultimatepython/classes/iterator_class.py) (:exploding_head:) + - Clase de excepción: [Definición de excepción](ultimatepython/classes/exception_class.py) + - Clase iteradora: [Definición de iteradora | yield](ultimatepython/classes/iterator_class.py) ( 🤯 ) + - Encapsulación: [Definición de encapsulación](ultimatepython/classes/encapsulation.py) 5. **Avanzado** - - Decorador: [Definición de decorador | wraps](ultimatepython/advanced/decorator.py) (:exploding_head:) - - Gestor de contexto: [Gestores de contexto](ultimatepython/advanced/context_manager.py) (:exploding_head:) - - Orden de resolución de método (MRO por sus siglas en inglés): [mro](ultimatepython/advanced/mro.py) (:exploding_head:) - - Mixin: [Definición de Mixin](ultimatepython/advanced/mixin.py) (:exploding_head:) - - Metaclase: [Definición de metaclase](ultimatepython/advanced/meta_class.py) (:exploding_head:) - - Hilos: [ThreadPoolExecutor](ultimatepython/advanced/thread.py) (:exploding_head:) - - Asyncio: [async | await](ultimatepython/advanced/async.py) (:exploding_head:) - - Referencias débiles: [weakref](ultimatepython/advanced/weak_ref.py) (:exploding_head:) - - Referencia: [cProfile | pstats](ultimatepython/advanced/benchmark.py) (:exploding_head:) - - Mocking: [MagicMock | PropertyMock | patch](ultimatepython/advanced/mocking.py) (:exploding_head:) - - Expresiones regulares: [search | findall | match | fullmatch](ultimatepython/advanced/regex.py) (:exploding_head:) - - Formatos de datos: [json | xml | csv](ultimatepython/advanced/data_format.py) (:exploding_head:) - - Fecha y hora: [datetime | timezone](ultimatepython/advanced/date_time.py) (:exploding_head:) + - Decorador: [Definición de decorador | wraps](ultimatepython/advanced/decorator.py) ( 🤯 ) + - Manejo de archivos: [Manejo de archivos](ultimatepython/advanced/file_handling.py) ( 🤯 ) + - Gestor de contexto: [Gestores de contexto](ultimatepython/advanced/context_manager.py) ( 🤯 ) + - Orden de resolución de método (MRO por sus siglas en inglés): [mro](ultimatepython/advanced/mro.py) ( 🤯 ) + - Mixin: [Definición de Mixin](ultimatepython/advanced/mixin.py) ( 🤯 ) + - Metaclase: [Definición de metaclase](ultimatepython/advanced/meta_class.py) ( 🤯 ) + - Hilos: [ThreadPoolExecutor](ultimatepython/advanced/thread.py) ( 🤯 ) + - Asyncio: [async | await](ultimatepython/advanced/async.py) ( 🤯 ) + - Referencias débiles: [weakref](ultimatepython/advanced/weak_ref.py) ( 🤯 ) + - Referencia: [cProfile | pstats](ultimatepython/advanced/benchmark.py) ( 🤯 ) + - Mocking: [MagicMock | PropertyMock | patch](ultimatepython/advanced/mocking.py) ( 🤯 ) + - Expresiones regulares: [search | findall | match | fullmatch](ultimatepython/advanced/regex.py) ( 🤯 ) + - Formatos de datos: [json | xml | csv](ultimatepython/advanced/data_format.py) ( 🤯 ) + - Fecha y hora: [datetime | timezone](ultimatepython/advanced/date_time.py) ( 🤯 ) + - Coincidencia de patrones: [match | case](ultimatepython/advanced/pattern_matching.py) ( 🤯 ) ## Recursos adicionales -:necktie: = Recurso de entrevista, -:test_tube: = Ejemplos de código, -:brain: = Ideas para proyecto +👔 = Recurso de entrevista, +🧪 = Ejemplos de código, +🧠 = Ideas para proyecto ### Repositorios de GitHub Sigue aprendiendo leyendo otros buenos recursos. -- [TheAlgorithms/Python](https://github.com/TheAlgorithms/Python) (:necktie:, :test_tube:) -- [faif/python-patterns](https://github.com/faif/python-patterns) (:necktie:, :test_tube:) -- [geekcomputers/Python](https://github.com/geekcomputers/Python) (:test_tube:) -- [trekhleb/homemade-machine-learning](https://github.com/trekhleb/homemade-machine-learning) (:test_tube:) -- [karan/Projects](https://github.com/karan/Projects) (:brain:) -- [MunGell/awesome-for-beginners](https://github.com/MunGell/awesome-for-beginners) (:brain:) +- [TheAlgorithms/Python](https://github.com/TheAlgorithms/Python) ( 👔 , 🧪 ) +- [faif/python-patterns](https://github.com/faif/python-patterns) ( 👔 , 🧪 ) +- [geekcomputers/Python](https://github.com/geekcomputers/Python) ( 🧪 ) +- [trekhleb/homemade-machine-learning](https://github.com/trekhleb/homemade-machine-learning) ( 🧪 ) +- [karan/Projects](https://github.com/karan/Projects) ( 🧠 ) +- [MunGell/awesome-for-beginners](https://github.com/MunGell/awesome-for-beginners) ( 🧠 ) - [vinta/awesome-python](https://github.com/vinta/awesome-python) - [academic/awesome-datascience](https://github.com/academic/awesome-datascience) - [josephmisiti/awesome-machine-learning](https://github.com/josephmisiti/awesome-machine-learning) - [ZuzooVn/machine-learning-for-software-engineers](https://github.com/ZuzooVn/machine-learning-for-software-engineers) -- [30-seconds/30-seconds-of-python](https://github.com/30-seconds/30-seconds-of-python) (:test_tube:) +- [30-seconds/30-seconds-of-python](https://github.com/30-seconds/30-seconds-of-python) ( 🧪 ) - [ml-tooling/best-of-python](https://github.com/ml-tooling/best-of-python) +- [practical-tutorials/project-based-learning](https://github.com/practical-tutorials/project-based-learning#python) +- [freeCodeCamp/freeCodeCamp](https://github.com/freeCodeCamp/freeCodeCamp) ( 👔 ) +- [microsoft/ML-For-Beginners](https://github.com/microsoft/ML-For-Beginners) ( 🧪 ) +- [microsoft/Data-Science-For-Beginners](https://github.com/microsoft/Data-Science-For-Beginners) ( 🧪 ) +- [Avik-Jain/100-Days-Of-ML-Code](https://github.com/Avik-Jain/100-Days-Of-ML-Code) ( 🧪 ) + +### Proyectos del autor + +Proyectos que he creado con Python que muestran lo que puedes crear después de aprender estos conceptos: + +- [huangsam/chowist](https://github.com/huangsam/chowist) ( 🧪 ) +- [huangsam/githooks](https://github.com/huangsam/githooks) ( 🧪 ) +- [huangsam/ragchain](https://github.com/huangsam/ragchain) ( 🧪 ) +- [huangsam/mailprune](https://github.com/huangsam/mailprune) ( 🧪 ) ### Práctica interactiva Continua practicando para que no se oxiden tus habilidades de programación. -- [leetcode.com](https://leetcode.com/) (:necktie:) -- [hackerrank.com](https://www.hackerrank.com/) (:necktie:) -- [kaggle.com](https://www.kaggle.com/) (:brain:) +- [codechef.com](https://www.codechef.com/) ( 👔 ) +- [codeforces.com](https://codeforces.com/) +- [codementor.io](https://www.codementor.io) ( 🧠 ) +- [coderbyte.com](https://www.coderbyte.com/) ( 👔 ) +- [codewars.com](https://www.codewars.com/) - [exercism.io](https://exercism.io/) +- [geeksforgeeks.org](https://www.geeksforgeeks.org/) ( 👔 ) +- [hackerearth.com](https://www.hackerearth.com/) +- [hackerrank.com](https://www.hackerrank.com/) ( 👔 ) +- [kaggle.com](https://www.kaggle.com/) ( 🧠 ) +- [labex.io](https://labex.io/exercises/python)( 🧪 ) +- [leetcode.com](https://leetcode.com/) ( 👔 ) - [projecteuler.net](https://projecteuler.net/) -- [DevProjects](https://www.codementor.io/projects/python) -- [codewars.com](https://www.codewars.com/) +- [replit.com](https://replit.com/) +- [w3schools.com](https://www.w3schools.com/python/) ( 🧪 ) +- [teclado.com](https://teclado.com/30-days-of-python/#prerequisites) ( 👔 ) +- [fullstakpython.org](https://fullstackpython.org/) ( 🧪 ) + +## Astrónomos en el tiempo + +[![Stargazers over time](https://starchart.cc/huangsam/ultimate-python.svg?variant=adaptive)](https://starchart.cc/huangsam/ultimate-python) diff --git a/README.fr.md b/README.fr.md new file mode 100644 index 00000000..63698a55 --- /dev/null +++ b/README.fr.md @@ -0,0 +1,201 @@ +# Guide d’étude Python ultime + +[![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/huangsam/ultimate-python/ci.yml)](https://github.com/huangsam/ultimate-python/actions) +[![Code Coverage](https://img.shields.io/codecov/c/github/huangsam/ultimate-python)](https://codecov.io/gh/huangsam/ultimate-python) +[![Quality Gate Status](https://img.shields.io/sonar/quality_gate/huangsam_ultimate-python?server=https%3A%2F%2Fsonarcloud.io)](https://sonarcloud.io/dashboard?id=huangsam_ultimate-python) +[![License](https://img.shields.io/github/license/huangsam/ultimate-python)](https://github.com/huangsam/ultimate-python/blob/main/LICENSE) +[![r/Python](https://img.shields.io/badge/reddit-original_post-red)](https://www.reddit.com/r/Python/comments/inllmf/ultimate_python_study_guide/) + +Guide d’étude Python ultime pour les débutants comme pour les professionnels. 🐍 🐍 🐍 + +```python +print("Guide d’étude Python ultime") +``` + +[English](README.md) | +[한국어](README.ko.md) | +[繁体中文](README.zh_tw.md) | +[Español](README.es.md) | +[Deutsch](README.de.md) | +[Français](README.fr.md) | +[हिन्दी](README.hi.md) | +[Português - Brasil](README.pt_br.md) + +Ultimate Python + +## Motivation + +J’ai créé ce dépôt GitHub pour partager ce que j’ai appris sur le [cœur de Python](https://www.python.org/) +au cours de plus de 5 années d’utilisation: en tant que diplômé universitaire, employé +dans de grandes entreprises et contributeur open-source à des dépôts tels que +[Celery](https://github.com/celery/celery) et +[Full Stack Python](https://github.com/mattmakai/fullstackpython.com). +J’espère voir de plus en plus de personnes apprendre Python et poursuivre leurs passions +grâce à ce langage. 🎓 + +## Objectifs + +Voici les principaux objectifs de ce guide : + +🏆 **Servir de ressource** pour les débutants en Python qui préfèrent apprendre de manière pratique. +Ce dépôt contient une collection de modules indépendants pouvant être exécutés dans un IDE +comme [PyCharm](https://www.jetbrains.com/pycharm/) ou dans le navigateur via +[Replit](https://replit.com/languages/python3). Même un simple terminal suffit +pour exécuter les exemples. La plupart des lignes contiennent des commentaires détaillés +qui guident le lecteur pas à pas. +Les utilisateurs sont encouragés à modifier le code source à leur guise tant que les +routines `main` ne sont pas supprimées et que les programmes +[s’exécutent correctement](runner.py) après chaque modification. + +🏆 **Servir de guide pur** pour ceux qui souhaitent revoir les concepts fondamentaux de Python. +Seules les [bibliothèques intégrées](https://docs.python.org/3/library/) sont utilisées afin de +présenter les concepts sans dépendre de notions spécifiques à un domaine. Ainsi, les +bibliothèques open-source populaires comme `sqlalchemy`, `requests` ou `pandas` +ne sont pas installées. +Cependant, lire le code source de ces frameworks est fortement recommandé +si ton objectif est de devenir un véritable +[Pythonista](https://www.urbandictionary.com/define.php?term=pythonista). + +## Pour commencer + +[![Run on Replit](https://replit.com/badge/github/huangsam/ultimate-python)](https://replit.com/github/huangsam/ultimate-python) + +Clique sur le badge ci-dessus pour lancer un environnement fonctionnel dans ton navigateur +sans avoir besoin d’installer Git ou Python localement. +Si ces outils sont déjà installés, tu peux cloner directement le dépôt. + +Une fois le dépôt accessible, tu es prêt à apprendre à partir des modules indépendants. +Pour tirer le meilleur parti de chaque module, lis le code et exécute-le. + +Deux méthodes sont possibles : + +1. Exécuter un seul module : +  `python ultimatepython/syntax/variable.py` +2. Exécuter tous les modules : +  `python runner.py` + +## Table des matières + +📚 = Ressource externe +🍰 = Sujet débutant +🤯 = Sujet avancé + +1. **À propos de Python** +    - Vue d’ensemble : [Qu’est-ce que Python](https://github.com/trekhleb/learn-python/blob/master/src/getting_started/what_is_python.md) ( 📚, 🍰 ) +    - Philosophie : [Le Zen de Python](https://www.python.org/dev/peps/pep-0020/) ( 📚 ) +    - Guide de style : [Guide de style du code Python](https://www.python.org/dev/peps/pep-0008/) ( 📚, 🤯 ) +    - Modèle de données : [Modèle de données](https://docs.python.org/3/reference/datamodel.html) ( 📚, 🤯 ) +    - Bibliothèque standard : [Bibliothèque standard Python](https://docs.python.org/3/library/) ( 📚, 🤯 ) +    - Fonctions intégrées : [Fonctions intégrées](https://docs.python.org/3/library/functions.html) ( 📚 ) + +2. **Syntaxe** +    - Variable : [Littéraux intégrés](ultimatepython/syntax/variable.py) ( 🍰 ) +    - Expression : [Opérations numériques](ultimatepython/syntax/expression.py) ( 🍰 ) +    - Opérateurs binaires : [Opérateurs binaires](ultimatepython/syntax/bitwise.py) ( 🍰 ), [Complément à un et à deux](https://www.geeksforgeeks.org/difference-between-1s-complement-representation-and-2s-complement-representation-technique/) ( 📚 ) +    - Conditionnelle : [if | if-else | if-elif-else](ultimatepython/syntax/conditional.py) ( 🍰 ) +    - Boucle : [for-loop | while-loop](ultimatepython/syntax/loop.py) ( 🍰 ) +    - Fonction : [def | lambda](ultimatepython/syntax/function.py) ( 🍰 ) + - Opérateur morse : [Expressions d'affectation :=](ultimatepython/syntax/walrus_operator.py) ( 🤯 ) + - Application d'arguments : [Positionnels uniquement / | Mots-clés uniquement *](ultimatepython/syntax/arg_enforcement.py) ( 🤯 ) + +3. **Structures de données** +    - Liste : [Opérations sur les listes](ultimatepython/data_structures/list.py) ( 🍰 ) +    - Tuple : [Opérations sur les tuples](ultimatepython/data_structures/tuple.py) +    - Ensemble : [Opérations sur les ensembles](ultimatepython/data_structures/set.py) +    - Dictionnaire : [Opérations sur les dictionnaires](ultimatepython/data_structures/dict.py) ( 🍰 ) + - Union de dictionnaires : [Fusion de dictionnaires | et |=](ultimatepython/data_structures/dict_union.py) ( 🤯 ) +    - Compréhension : [list | tuple | set | dict](ultimatepython/data_structures/comprehension.py) +    - Chaîne : [Opérations sur les chaînes](ultimatepython/data_structures/string.py) ( 🍰 ) +    - Deque : [deque](ultimatepython/data_structures/deque.py) ( 🤯 ) +    - Namedtuple : [namedtuple](ultimatepython/data_structures/namedtuple.py) ( 🤯 ) +    - Defaultdict : [defaultdict](ultimatepython/data_structures/defaultdict.py) ( 🤯 ) +    - Outils d'itérateurs : [Outils d'itérateurs](ultimatepython/data_structures/itertools.py) ( 🤯 ) +    - Complexité temporelle : [Opérations CPython](https://wiki.python.org/moin/TimeComplexity) ( 📚, 🤯 ) + +4. **Classes** +    - Classe basique : [Définition basique](ultimatepython/classes/basic_class.py) ( 🍰 ) +    - Héritage : [Héritage](ultimatepython/classes/inheritance.py) ( 🍰 ) +    - Classe abstraite : [Définition abstraite](ultimatepython/classes/abstract_class.py) +    - Classe d’exception : [Définition d’exception](ultimatepython/classes/exception_class.py) +    - Itérateur : [Définition d’itérateur | yield](ultimatepython/classes/iterator_class.py) ( 🤯 ) +    - Encapsulation : [Définition de l’encapsulation](ultimatepython/classes/encapsulation.py) + +5. **Avancé** +    - Décorateur : [Définition de décorateur | wraps](ultimatepython/advanced/decorator.py) ( 🤯 ) +    - Gestion de fichiers : [File Handling](ultimatepython/advanced/file_handling.py) ( 🤯 ) +    - Gestionnaire de contexte : [Context managers](ultimatepython/advanced/context_manager.py) ( 🤯 ) +    - Ordre de résolution des méthodes : [mro](ultimatepython/advanced/mro.py) ( 🤯 ) +    - Mixin : [Définition de Mixin](ultimatepython/advanced/mixin.py) ( 🤯 ) +    - Métaclasse : [Définition de métaclasse](ultimatepython/advanced/meta_class.py) ( 🤯 ) +    - Thread : [ThreadPoolExecutor](ultimatepython/advanced/thread.py) ( 🤯 ) +    - Asyncio : [async | await](ultimatepython/advanced/async.py) ( 🤯 ) +    - Référence faible : [weakref](ultimatepython/advanced/weak_ref.py) ( 🤯 ) +    - Benchmark : [cProfile | pstats](ultimatepython/advanced/benchmark.py) ( 🤯 ) +    - Mocking : [MagicMock | PropertyMock | patch](ultimatepython/advanced/mocking.py) ( 🤯 ) +    - Expressions régulières : [search | findall | match | fullmatch](ultimatepython/advanced/regex.py) ( 🤯 ) +    - Format de données : [json | xml | csv](ultimatepython/advanced/data_format.py) ( 🤯 ) +    - Date et heure : [datetime | timezone](ultimatepython/advanced/date_time.py) ( 🤯 ) + - Correspondance de motifs : [match | case](ultimatepython/advanced/pattern_matching.py) ( 🤯 ) + +## Ressources supplémentaires + +👔 = Ressource d’entretien +🧪 = Exemples de code +🧠 = Idées de projets + +### Dépôts GitHub + +Continue d’apprendre grâce à ces ressources bien établies : + +- [TheAlgorithms/Python](https://github.com/TheAlgorithms/Python) ( 👔 , 🧪 ) +- [faif/python-patterns](https://github.com/faif/python-patterns) ( 👔 , 🧪 ) +- [geekcomputers/Python](https://github.com/geekcomputers/Python) ( 🧪 ) +- [trekhleb/homemade-machine-learning](https://github.com/trekhleb/homemade-machine-learning) ( 🧪 ) +- [karan/Projects](https://github.com/karan/Projects) ( 🧠 ) +- [MunGell/awesome-for-beginners](https://github.com/MunGell/awesome-for-beginners) ( 🧠 ) +- [vinta/awesome-python](https://github.com/vinta/awesome-python) +- [academic/awesome-datascience](https://github.com/academic/awesome-datascience) +- [josephmisiti/awesome-machine-learning](https://github.com/josephmisiti/awesome-machine-learning) +- [ZuzooVn/machine-learning-for-software-engineers](https://github.com/ZuzooVn/machine-learning-for-software-engineers) +- [30-seconds/30-seconds-of-python](https://github.com/30-seconds/30-seconds-of-python) ( 🧪 ) +- [ml-tooling/best-of-python](https://github.com/ml-tooling/best-of-python) +- [practical-tutorials/project-based-learning](https://github.com/practical-tutorials/project-based-learning#python) +- [freeCodeCamp/freeCodeCamp](https://github.com/freeCodeCamp/freeCodeCamp) ( 👔 ) +- [microsoft/ML-For-Beginners](https://github.com/microsoft/ML-For-Beginners) ( 🧪 ) +- [microsoft/Data-Science-For-Beginners](https://github.com/microsoft/Data-Science-For-Beginners) ( 🧪 ) +- [Avik-Jain/100-Days-Of-ML-Code](https://github.com/Avik-Jain/100-Days-Of-ML-Code) ( 🧪 ) + +### Projets de l'auteur + +Projets que j'ai créés avec Python qui montrent ce que vous pouvez créer après avoir appris ces concepts : + +- [huangsam/chowist](https://github.com/huangsam/chowist) ( 🧪 ) +- [huangsam/githooks](https://github.com/huangsam/githooks) ( 🧪 ) +- [huangsam/ragchain](https://github.com/huangsam/ragchain) ( 🧪 ) +- [huangsam/mailprune](https://github.com/huangsam/mailprune) ( 🧪 ) + +### Pratique interactive + +Continue à t’exercer pour ne pas perdre la main : + +- [codechef.com](https://www.codechef.com/) ( 👔 ) +- [codeforces.com](https://codeforces.com/) +- [codementor.io](https://www.codementor.io) ( 🧠 ) +- [coderbyte.com](https://www.coderbyte.com/) ( 👔 ) +- [codewars.com](https://www.codewars.com/) +- [exercism.io](https://exercism.io/) +- [geeksforgeeks.org](https://www.geeksforgeeks.org/) ( 👔 ) +- [hackerearth.com](https://www.hackerearth.com/) +- [hackerrank.com](https://www.hackerrank.com/) ( 👔 ) +- [kaggle.com](https://www.kaggle.com/) ( 🧠 ) +- [labex.io](https://labex.io/exercises/python)( 🧪 ) +- [leetcode.com](https://leetcode.com/) ( 👔 ) +- [projecteuler.net](https://projecteuler.net/) +- [replit.com](https://replit.com/) +- [w3schools.com](https://www.w3schools.com/python/) ( 🧪 ) +- [teclado.com](https://teclado.com/30-days-of-python/#prerequisites) ( 👔 ) +- [fullstakpython.org](https://fullstackpython.org/) ( 🧪 ) + +## Observateurs d'étoiles dans le temps + +[![Stargazers over time](https://starchart.cc/huangsam/ultimate-python.svg?variant=adaptive)](https://starchart.cc/huangsam/ultimate-python) diff --git a/README.hi.md b/README.hi.md new file mode 100644 index 00000000..fdb77a67 --- /dev/null +++ b/README.hi.md @@ -0,0 +1,174 @@ +# अल्टीमेट Python अध्ययन गाइड + +[![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/huangsam/ultimate-python/ci.yml)](https://github.com/huangsam/ultimate-python/actions) +[![Code Coverage](https://img.shields.io/codecov/c/github/huangsam/ultimate-python)](https://codecov.io/gh/huangsam/ultimate-python) +[![Quality Gate Status](https://img.shields.io/sonar/quality_gate/huangsam_ultimate-python?server=https%3A%2F%2Fsonarcloud.io)](https://sonarcloud.io/dashboard?id=huangsam_ultimate-python) +[![License](https://img.shields.io/github/license/huangsam/ultimate-python)](https://github.com/huangsam/ultimate-python/blob/main/LICENSE) +[![r/Python](https://img.shields.io/badge/reddit-original_post-red)](https://www.reddit.com/r/Python/comments/inllmf/ultimate_python_study_guide/) + +नए और पेशेवर लोगों के लिए अल्टीमेट पायथन अध्ययन गाइड। 🐍 🐍 🐍 + +```python +print("Ultimate Python स्टडी गाइड") +``` + +[English](README.md) | +[한국어](README.ko.md) | +[繁体中文](README.zh_tw.md) | +[Español](README.es.md) | +[Deutsch](README.de.md) | +[Français](README.fr.md) | +[हिन्दी](README.hi.md) | +[Português - Brasil](README.pt_br.md) + +Ultimate Python + +## प्रेरणा + +मैंने यह गिटहब रिपोजिटरी [core Python](https://www.python.org/) के बारे में जो कुछ मैंने पिछले 5+ वर्षों में सीखा है, उसे साझा करने के लिए बनाई है। मैंने इसे एक कॉलेज ग्रेजुएट, बड़ी कंपनियों के कर्मचारी, और [Celery](https://github.com/celery/celery) और [Full Stack Python](https://github.com/mattmakai/fullstackpython.com) जैसी रिपोजिटरी के ओपन-सोर्स कंट्रीब्यूटर के रूप में उपयोग किया है। मैं यह देखने के लिए उत्सुक हूँ कि और लोग पायथन सीखें और इसके माध्यम से अपने जुनून को आगे बढ़ाएं। 🎓 + + +## लक्ष्य + +इस गाइड को बनाने के मुख्य लक्ष्य निम्नलिखित हैं: + +🏆 **संसाधन के रूप में सेवा देना** उन नए पायथन उपयोगकर्ताओं के लिए जो प्रैक्टिकल तरीके से सीखना पसंद करते हैं। इस रिपोजिटरी में स्वतंत्र मॉड्यूलों का एक संग्रह है, जिन्हें IDE जैसे [PyCharm](https://www.jetbrains.com/pycharm/) में या [Replit](https://replit.com/languages/python3) जैसे ब्राउज़र में चलाया जा सकता है। पुराने साधारण टर्मिनल में भी इन उदाहरणों को चलाया जा सकता है। अधिकतर लाइनों में बहुत ही अच्छे से लिखे गए comments होते हैं, जो पाठक को प्रोग्राम्स के प्रत्येक चरण के माध्यम से मार्गदर्शन करते हैं। उपयोगकर्ताओं को कोड में बदलाव करने के लिए प्रोत्साहित किया जाता है, बशर्ते कि `main` रूटीन को हटाया न जाए और हर परिवर्तन के बाद [सफलतापूर्वक चलाया जाए](runner.py)। + +🏆 **शुद्ध गाइड के रूप में सेवा देना** उन लोगों के लिए जो मुख्य पायथन अवधारणाओं को फिर से समझना चाहते हैं। केवल [बिल्ट-इन लाइब्रेरीज़](https://docs.python.org/3/library/) का उपयोग किया गया है ताकि इन अवधारणाओं को बिना किसी विशेष डोमेन की अवधारणाओं के सरलता से समझाया जा सके। इसी कारण से लोकप्रिय ओपन-सोर्स लाइब्रेरीज़ और फ्रेमवर्क (जैसे `sqlalchemy`, `requests`, `pandas`) को इंस्टॉल नहीं किया गया है। हालांकि, इन फ्रेमवर्क्स के स्रोत कोड को पढ़ना प्रेरणादायक है और यदि आपका लक्ष्य एक सच्चे [Pythonista](https://www.urbandictionary.com/define.php?term=pythonista) बनने का है तो इसे ज़रूर पढ़ना चाहिए। + + +## शुरूआत + +[![Run on Replit](https://replit.com/badge/github/huangsam/ultimate-python)](https://replit.com/github/huangsam/ultimate-python) + +ऊपर दिए गए बैज पर क्लिक करें ताकि आप ब्राउज़र में एक कार्यशील वातावरण शुरू कर सकें, इसके लिए आपके स्थानीय मशीन पर Git और पायथन की आवश्यकता नहीं होगी। यदि ये आवश्यकताएँ पहले से ही पूरी हो चुकी हैं, तो आप सीधे रिपोजिटरी को क्लोन कर सकते हैं। + +एक बार जब रिपोजिटरी उपलब्ध हो जाती है, तो आप स्वतंत्र मॉड्यूल से सीखने के लिए तैयार हैं। प्रत्येक मॉड्यूल का अधिकतम लाभ उठाने के लिए, मॉड्यूल का कोड पढ़ें और इसे चलाएं। मॉड्यूल चलाने के दो तरीके हैं: + +1. एकल मॉड्यूल चलाएं: `python ultimatepython/syntax/variable.py` +2. सभी मॉड्यूल चलाएं: `python runner.py` + +## विषय सूची + +📚 = बाहरी स्रोत, +🍰 = शुरुआती विषय, +🤯 = उन्नत विषय + + +1. **पायथन के बारे में** + - अवलोकन: [पायथन क्या है](https://github.com/trekhleb/learn-python/blob/master/src/getting_started/what_is_python.md) ( 📚, 🍰 ) + - डिज़ाइन दर्शन: [पायथन का ज़ेन](https://www.python.org/dev/peps/pep-0020/) ( 📚 ) + - शैली मार्गदर्शिका: [पायथन कोड के लिए शैली मार्गदर्शिका](https://www.python.org/dev/peps/pep-0008/) ( 📚, 🤯 ) + - डेटा मॉडल: [डेटा मॉडल](https://docs.python.org/3/reference/datamodel.html) ( 📚, 🤯 ) + - मानक पुस्तकालय: [पायथन मानक पुस्तकालय](https://docs.python.org/3/library/) ( 📚, 🤯 ) + - अंतर्निहित कार्य: [अंतर्निहित कार्य](https://docs.python.org/3/library/functions.html) ( 📚 ) +2. **सिंटेक्स** + - वेरिएबल: [अंतर्निहित लिटरल](ultimatepython/syntax/variable.py) ( 🍰 ) + - अभिव्यक्ति: [संख्यात्मक ऑपरेशन्स](ultimatepython/syntax/expression.py) ( 🍰 ) + - बाइनरी: [बाइनरी ऑपरेटर](ultimatepython/syntax/bitwise.py) ( 🍰 ), [एक्स/टू का पूरक](https://www.geeksforgeeks.org/difference-between-1s-complement-representation-and-2s-complement-representation-technique/) ( 📚 ) + - कंडीशनल: [if | if-else | if-elif-else](ultimatepython/syntax/conditional.py) ( 🍰 ) + - लूप: [for-loop | while-loop](ultimatepython/syntax/loop.py) ( 🍰 ) + - फ़ंक्शन: [def | lambda](ultimatepython/syntax/function.py) ( 🍰 ) + - वॉलरस ऑपरेटर: [असाइनमेंट एक्सप्रेशन :=](ultimatepython/syntax/walrus_operator.py) ( 🤯 ) + - तर्क प्रवर्तन: [केवल स्थितीय / | केवल कीवर्ड *](ultimatepython/syntax/arg_enforcement.py) ( 🤯 ) +3. **डेटा संरचनाएँ** + - लिसट: [लिसट ऑपरेशन्स](ultimatepython/data_structures/list.py) ( 🍰 ) + - ट्यूपल: [ट्यूपल ऑपरेशन्स](ultimatepython/data_structures/tuple.py) + - सेट: [सेट ऑपरेशन्स](ultimatepython/data_structures/set.py) + - डिक्ट: [डिक्शनरी ऑपरेशन्स](ultimatepython/data_structures/dict.py) ( 🍰 ) + - डिक्शनरी यूनियन: [डिक्शनरी मर्ज | और |=](ultimatepython/data_structures/dict_union.py) ( 🤯 ) + - संकलन: [लिसट | ट्यूपल | सेट | डिक्ट](ultimatepython/data_structures/comprehension.py) + - स्ट्रिंग: [स्ट्रिंग ऑपरेशन्स](ultimatepython/data_structures/string.py) ( 🍰 ) + - डेक: [डेक](ultimatepython/data_structures/deque.py) ( 🤯 ) + - नामित ट्यूपल: [नामित ट्यूपल](ultimatepython/data_structures/namedtuple.py) ( 🤯 ) + - डिफ़ॉल्ट डिक्ट: [डिफ़ॉल्ट डिक्ट](ultimatepython/data_structures/defaultdict.py) ( 🤯 ) + - इटरेटर टूल्स: [इटरेटर टूल्स](ultimatepython/data_structures/itertools.py) ( 🤯 ) + - समय कोम्पलेक्सिटी: [cPython ऑपरेशन्स](https://wiki.python.org/moin/TimeComplexity) ( 📚, 🤯 ) +4. **क्लासेज़** + - बेसिक क्लास: [बेसिक परिभाषा](ultimatepython/classes/basic_class.py) ( 🍰 ) + - इन्हरिटैंस: [इन्हरिटैंस](ultimatepython/classes/inheritance.py) ( 🍰 ) + - एैबस्टराक्ट क्लास: [एैबस्टराक्ट परिभाषा](ultimatepython/classes/abstract_class.py) + - एक्सेपशन क्लास: [एक्सेपशन परिभाषा](ultimatepython/classes/exception_class.py) + - इटरेटर क्लास: [इटरेटर परिभाषा | yield](ultimatepython/classes/iterator_class.py) ( 🤯 ) + - ऐनकैपसुलेषन: [ऐनकैपसुलेषन परिभाषा](ultimatepython/classes/encapsulation.py) +5. **उन्नत** + - डेकोरेटर: [डेकोरेटर परिभाषा | wraps](ultimatepython/advanced/decorator.py) ( 🤯 ) + - फ़ाइल प्रबंधन: [फ़ाइल प्रबंधन](ultimatepython/advanced/file_handling.py) ( 🤯 ) + - संदर्भ प्रबंधक: [संदर्भ प्रबंधक](ultimatepython/advanced/context_manager.py) ( 🤯 ) + - मेथड रिज़ॉल्यूशन क्रम: [mro](ultimatepython/advanced/mro.py) ( 🤯 ) + - मिक्सिन: [मिक्सिन परिभाषा](ultimatepython/advanced/mixin.py) ( 🤯 ) + - मेटाक्लास: [मेटाक्लास परिभाषा](ultimatepython/advanced/meta_class.py) ( 🤯 ) + - थ्रेड: [ThreadPoolExecutor](ultimatepython/advanced/thread.py) ( 🤯 ) + - एसिंको: [async | await](ultimatepython/advanced/async.py) ( 🤯 ) + - वीक रेफरेंस: [weakref](ultimatepython/advanced/weak_ref.py) ( 🤯 ) + - बेंचमार्क: [cProfile | pstats](ultimatepython/advanced/benchmark.py) ( 🤯 ) + - मॉकिंग: [MagicMock | PropertyMock | patch](ultimatepython/advanced/mocking.py) ( 🤯 ) + - नियमित अभिव्यक्ति: [search | findall | match | fullmatch](ultimatepython/advanced/regex.py) ( 🤯 ) + - डेटा फ़ॉर्मेट: [json | xml | csv](ultimatepython/advanced/data_format.py) ( 🤯 ) + - दिनांक और समय: [datetime | timezone](ultimatepython/advanced/date_time.py) ( 🤯 ) + - पैटर्न मिलान: [match | case](ultimatepython/advanced/pattern_matching.py) ( 🤯 ) + + +## अतिरिक्त संसाधन + +👔 = इंटरव्यू संसाधन, +🧪 = कोड नमूने, +🧠 = प्रोजेक्ट विचार + + +### गिटहब रिपॉजिटरी + +अन्य उच्च मानक संसाधनों से पढ़कर सीखना जारी रखें। + +- [TheAlgorithms/Python](https://github.com/TheAlgorithms/Python) ( 👔 , 🧪 ) +- [faif/python-patterns](https://github.com/faif/python-patterns) ( 👔 , 🧪 ) +- [geekcomputers/Python](https://github.com/geekcomputers/Python) ( 🧪 ) +- [trekhleb/homemade-machine-learning](https://github.com/trekhleb/homemade-machine-learning) ( 🧪 ) +- [karan/Projects](https://github.com/karan/Projects) ( 🧠 ) +- [MunGell/awesome-for-beginners](https://github.com/MunGell/awesome-for-beginners) ( 🧠 ) +- [vinta/awesome-python](https://github.com/vinta/awesome-python) +- [academic/awesome-datascience](https://github.com/academic/awesome-datascience) +- [josephmisiti/awesome-machine-learning](https://github.com/josephmisiti/awesome-machine-learning) +- [ZuzooVn/machine-learning-for-software-engineers](https://github.com/ZuzooVn/machine-learning-for-software-engineers) +- [30-seconds/30-seconds-of-python](https://github.com/30-seconds/30-seconds-of-python) ( 🧪 ) +- [ml-tooling/best-of-python](https://github.com/ml-tooling/best-of-python) +- [practical-tutorials/project-based-learning](https://github.com/practical-tutorials/project-based-learning#python) +- [freeCodeCamp/freeCodeCamp](https://github.com/freeCodeCamp/freeCodeCamp) ( 👔 ) +- [microsoft/ML-For-Beginners](https://github.com/microsoft/ML-For-Beginners) ( 🧪 ) +- [microsoft/Data-Science-For-Beginners](https://github.com/microsoft/Data-Science-For-Beginners) ( 🧪 ) +- [Avik-Jain/100-Days-Of-ML-Code](https://github.com/Avik-Jain/100-Days-Of-ML-Code) ( 🧪 ) + +### लेखक की परियोजनाएँ + +Python से बनाई गई परियोजनाएं जो दिखाती हैं कि इन अवधारणाओं को सीखने के बाद आप क्या बना सकते हैं: + +- [huangsam/chowist](https://github.com/huangsam/chowist) ( 🧪 ) +- [huangsam/githooks](https://github.com/huangsam/githooks) ( 🧪 ) +- [huangsam/ragchain](https://github.com/huangsam/ragchain) ( 🧪 ) +- [huangsam/mailprune](https://github.com/huangsam/mailprune) ( 🧪 ) + +### इंटरैक्टिव प्रैक्टिस + +अभ्यास करते रहें ताकि आपकी कोडिंग कौशल खराब न हों। + +- [codechef.com](https://www.codechef.com/) ( 👔 ) +- [codeforces.com](https://codeforces.com/) +- [codementor.io](https://www.codementor.io) ( 🧠 ) +- [coderbyte.com](https://www.coderbyte.com/) ( 👔 ) +- [codewars.com](https://www.codewars.com/) +- [exercism.io](https://exercism.io/) +- [geeksforgeeks.org](https://www.geeksforgeeks.org/) ( 👔 ) +- [hackerearth.com](https://www.hackerearth.com/) +- [hackerrank.com](https://www.hackerrank.com/) ( 👔 ) +- [kaggle.com](https://www.kaggle.com/) ( 🧠 ) +- [labex.io](https://labex.io/exercises/python)( 🧪 ) +- [leetcode.com](https://leetcode.com/) ( 👔 ) +- [projecteuler.net](https://projecteuler.net/) +- [replit.com](https://replit.com/) +- [w3schools.com](https://www.w3schools.com/python/) ( 🧪 ) +- [teclado.com](https://teclado.com/30-days-of-python/#prerequisites) ( 👔 ) +- [fullstakpython.org](https://fullstackpython.org/) ( 🧪 ) + +## समय के खगोलशास्त्री + +[![Stargazers over time](https://starchart.cc/huangsam/ultimate-python.svg?variant=adaptive)](https://starchart.cc/huangsam/ultimate-python) diff --git a/README.ko.md b/README.ko.md index 2afd6ade..42c47f29 100644 --- a/README.ko.md +++ b/README.ko.md @@ -1,12 +1,12 @@ # Ultimate Python 학습 가이드 -[![CircleCI](https://img.shields.io/circleci/build/github/huangsam/ultimate-python)](https://circleci.com/gh/huangsam/ultimate-python) +[![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/huangsam/ultimate-python/ci.yml)](https://github.com/huangsam/ultimate-python/actions) [![Code Coverage](https://img.shields.io/codecov/c/github/huangsam/ultimate-python)](https://codecov.io/gh/huangsam/ultimate-python) [![Quality Gate Status](https://img.shields.io/sonar/quality_gate/huangsam_ultimate-python?server=https%3A%2F%2Fsonarcloud.io)](https://sonarcloud.io/dashboard?id=huangsam_ultimate-python) -[![License](https://img.shields.io/github/license/huangsam/ultimate-python)](https://github.com/huangsam/ultimate-python/blob/master/LICENSE) -[![r/Python](https://img.shields.io/reddit/subreddit-subscribers/Python)](https://www.reddit.com/r/Python/comments/inllmf/ultimate_python_study_guide/) +[![License](https://img.shields.io/github/license/huangsam/ultimate-python)](https://github.com/huangsam/ultimate-python/blob/main/LICENSE) +[![r/Python](https://img.shields.io/badge/reddit-original_post-red)](https://www.reddit.com/r/Python/comments/inllmf/ultimate_python_study_guide/) -초보자와 전문가 모두를위한 최고의 Python 학습 가이드입니다. :snake: :snake: :snake: +초보자와 전문가 모두를 위한 최고의 Python 학습 가이드입니다. 🐍 🐍 🐍 ```python print("Ultimate Python 학습 가이드") @@ -16,120 +16,165 @@ print("Ultimate Python 학습 가이드") [한국어](README.ko.md) | [繁体中文](README.zh_tw.md) | [Español](README.es.md) | -[Deutsch](README.de.md) +[Deutsch](README.de.md) | +[Français](README.fr.md) | +[हिन्दी](README.hi.md) | +[Português - Brasil](README.pt_br.md) -## 이 학습 가이드를 만든 이유 +Ultimate Python -저는 지난 5 년 동안 대학 졸업생, 대규모 회사의 직원, 셀러리 및 풀 스택 Python과 같은 저장소의 오픈 소스 기고자로 -Python을 사용하면서 핵심 Python에 대해 배운 내용을 공유하기 위해 GitHub 저장소를 만들었습니다. 더 많은 사람들이 -파이썬을 배우고 그것을 통해 그들의 열정을 추구하는 것을 기대합니다. :mortar_board: +## 동기 + +이 GitHub 저장소는 대학 졸업 후, 대규모 회사에서 근무하면서 +그리고 [Celery](https://github.com/celery/celery)와 [Full Stack Python](https://github.com/mattmakai/fullstackpython.com) 같은 오픈소스 프로젝트에 기여하면서 +지난 5년 이상 동안 배운 [core Python](https://www.python.org/)에 대한 지식을 공유하기 위해 만들었습니다. +저는 더 많은 사람들이 Python을 배우고 자신의 열정을 추구하길 기대합니다. 🎓 ## 목표 -이 가이드를 만드는 기본 목표는 다음과 같습니다. +이 가이드를 만드는 주요 목표는 다음과 같습니다: -:trophy: 실습 학습을 선호하는 Python 초보자를위한 리소스 역할을합니다. 이 저장소에는 PyCharm과 같은 IDE 및 -Repl.it와 같은 브라우저에서 실행할 수있는 독립형 모듈 모음이 있습니다. 평범한 오래된 터미널조차도 예제와 함께 -작동합니다. 대부분의 줄에는 프로그램이 단계별로 수행하는 작업을 독자에게 안내하는 신중하게 작성된 주석이 있습니다. -기본 루틴이 삭제되지 않고 각 변경 후 성공적으로 실행되는 한 사용자는 어디에서나 소스 코드를 수정하는 것이 좋습니다. +🏆 실습 학습을 선호하는 Python 초보자를 위한 **학습 자료를 제공합니다.** +이 저장소에는 [PyCharm](https://www.jetbrains.com/pycharm/)과 같은 IDE 및 [Replit](https://replit.com/languages/python3)와 같은 브라우저에서 실행할 수 있는 독립형 모듈 모음이 있습니다. 기본 터미널에서도 예제를 실행할 수 있습니다. +대부분의 코드 라인에 프로그램이 단계별로 어떤 작업을 하는지 안내하는 신중하게 작성된 주석이 있습니다. +사용자는 `main` 루틴을 삭제하지 않고, 각 변경 후에 [성공적으로 실행](runner.py)되는 한 소스 코드를 얼마든지 수정할 수 있습니다. -:trophy: 핵심 Python 개념을 다시 검토하려는 사용자를위한 순수한 가이드 역할을합니다. 기본 라이브러리 만 활용되므로 -도메인 별 개념의 오버 헤드없이 이러한 개념을 전달할 수 있습니다. 따라서 인기있는 오픈 소스 라이브러리 및 프레임 워크 -(예 : `sqlalchemy`, `requests`, `pandas`)는 설치되지 않습니다. 그러나 목표가 진정한 Pythonista가되는 것이라면 -이러한 프레임 워크의 소스 코드를 읽는 것은 고무적이고 적극 권장됩니다. +🏆 core Python 개념을 다시 복습하고 싶은 사람들을 위한 **순수 가이드를 제공합니다.** +여기서는 오직 [내장 라이브러리](https://docs.python.org/3/library/)만을 사용하여 이러한 개념을 도메인 특화된 개념의 오버헤드 없이 전달합니다. +따라서 유명한 오픈소스 라이브러리와 프레임워크(`sqlalchemy`, `requests`, `pandas` 등)는 설치되어 있지 않습니다. +그러나, 당신의 목표가 진정한 진정한 [Pythonista](https://www.urbandictionary.com/define.php?term=pythonista)이 되는 것 이라면 이러한 프레임워크의 소스 코드를 읽는 것은 매우 고무적이고 권장이 됩니다. ## 시작하기 -[![Run on Repl.it](https://repl.it/badge/github/huangsam/ultimate-python)](https://repl.it/github/huangsam/ultimate-python) +[![Run on Replit](https://replit.com/badge/github/huangsam/ultimate-python)](https://replit.com/github/huangsam/ultimate-python) 로컬 컴퓨터에 Git 및 Python을 설치하지 않고도 브라우저에서 작업 환경을 시작하려면 위의 배지를 클릭하세요. 이러한 -요구 사항이 이미 충족 된 경우 저장소를 직접 복제해도됩니다. +요구 사항이 이미 충족된 경우, 저장소를 바로 clone해도 됩니다. -저장소에 액세스 할 수있게되면 독립형 모듈에서 배울 준비가 된 것입니다. 각 모듈을 최대한 활용하려면 모듈 코드를 -읽고 실행하십시오. 모듈을 실행하는 두 가지 방법이 있습니다. +저장소에 접근할 수 있게 되면 단독 모듈에서 배울 준비가 된 것입니다. 각 모듈을 최대한 활용하려면 모듈 코드를 +읽고 실행하십시오. 모듈을 실행하는 두 가지 방법이 있습니다: 1. 단일 모듈 실행 : `python ultimatepython/syntax/variable.py` -2. 모든 모듈을 실행합니다. `python runner.py` +2. 전체 모듈 실행 : `python runner.py` ## 목차 -:books: = 외부 리소스, -:cake: = 초급 주제, -:exploding_head: = 고급 주제 +📚 = 외부 리소스, +🍰 = 초급 주제, +🤯 = 고급 주제 1. **Python 정보** - - 개요 : [Python이란 무엇입니까](https://github.com/trekhleb/learn-python/blob/master/src/getting_started/what_is_python.md) (:books:, :cake:) - - 디자인 철학 : [The Zen of Python](https://www.python.org/dev/peps/pep-0020/) (:books:) - - 스타일 가이드 : [Python 코드 용 스타일 가이드](https://www.python.org/dev/peps/pep-0008/) (:books:, :exploding_head:) - - 데이터 모델 : [데이터 모델](https://docs.python.org/3/reference/datamodel.html) (:books:, :exploding_head:) - - 표준 라이브러리 : [Python 표준 라이브러리](https://docs.python.org/3/library/) (:books:, :exploding_head:) - - 내장 기능 : [내장 기능](https://docs.python.org/3/library/functions.html) (:books:) + - 개요 : [Python이란 무엇인가](https://github.com/trekhleb/learn-python/blob/master/src/getting_started/what_is_python.md) ( 📚, 🍰 ) + - 디자인 철학 : [The Zen of Python](https://www.python.org/dev/peps/pep-0020/) ( 📚 ) + - 스타일 가이드 : [Python 코드 스타일 가이드](https://www.python.org/dev/peps/pep-0008/) ( 📚, 🤯 ) + - 데이터 모델 : [데이터 모델](https://docs.python.org/3/reference/datamodel.html) ( 📚, 🤯 ) + - 표준 라이브러리 : [Python 표준 라이브러리](https://docs.python.org/3/library/) ( 📚, 🤯 ) + - 내장 함수 : [내장 함수](https://docs.python.org/3/library/functions.html) ( 📚 ) 2. **통사론** - - 변수 : [내장 리터럴](ultimatepython/syntax/variable.py) (:cake:) - - 식 : [숫자 연산](ultimatepython/syntax/expression.py) (:cake:) - - 조건부 : [if | if-else | if-elif-else](ultimatepython/syntax/conditional.py) (:cake:) - - 루프 : [for 루프 | while-loop](ultimatepython/syntax/loop.py) (:cake:) - - 함수 : [def | 람다](ultimatepython/syntax/function.py) (:cake:) + - 변수 : [내장 리터럴](ultimatepython/syntax/variable.py) ( 🍰 ) + - 표현식 : [숫자 연산](ultimatepython/syntax/expression.py) ( 🍰 ) + - 비트 연산 : [비트 연산자](ultimatepython/syntax/bitwise.py) ( 🍰 ), [1의 보수/2의 보수](https://www.geeksforgeeks.org/difference-between-1s-complement-representation-and-2s-complement-representation-technique/) ( 📚 ) + - 조건문 : [if | if-else | if-elif-else](ultimatepython/syntax/conditional.py) ( 🍰 ) + - 반복문 : [for-loop | while-loop](ultimatepython/syntax/loop.py) ( 🍰 ) + - 함수 : [def | lambda](ultimatepython/syntax/function.py) ( 🍰 ) + - 바다코끼리 연산자 : [할당 표현식 :=](ultimatepython/syntax/walrus_operator.py) ( 🤯 ) + - 인수 강제 : [위치 전용 / | 키워드 전용 *](ultimatepython/syntax/arg_enforcement.py) ( 🤯 ) 3. **데이터 구조** - - 목록 : [목록 작업](ultimatepython/data_structures/list.py) (:cake:) + - 리스트 : [리스트 연산](ultimatepython/data_structures/list.py) ( 🍰 ) - 튜플 : [튜플 연산](ultimatepython/data_structures/tuple.py) - - 설정 : [설정 작업](ultimatepython/data_structures/set.py) - - Dict : [사전 작업](ultimatepython/data_structures/dict.py) (:cake:) - - 이해력 : [목록 | 튜플 | 세트 | dict](ultimatepython/data_structures/comprehension.py) - - 문자열 : [문자열 연산](ultimatepython/data_structures/string.py) (:cake:) - - Deque: [deque](ultimatepython/data_structures/deque.py) (:exploding_head:) - - 시간 복잡성 : [cPython 작업](https://wiki.python.org/moin/TimeComplexity) (:books:, :exploding_head:) + - 세트 : [세트 연산](ultimatepython/data_structures/set.py) + - 딕셔너리 : [딕셔너리 연산](ultimatepython/data_structures/dict.py) ( 🍰 ) + - 딕셔너리 합병 : [딕셔너리 병합 | 및 |=](ultimatepython/data_structures/dict_union.py) ( 🤯 ) + - 컴프리헨션 : [리스트 | 튜플 | 세트 | 딕셔너리](ultimatepython/data_structures/comprehension.py) + - 문자열 : [문자열 연산](ultimatepython/data_structures/string.py) ( 🍰 ) + - 덱: [deque](ultimatepython/data_structures/deque.py) ( 🤯 ) + - Namedtuple: [namedtuple](ultimatepython/data_structures/namedtuple.py) ( 🤯 ) + - Defaultdict: [defaultdict](ultimatepython/data_structures/defaultdict.py) ( 🤯 ) + - 이터레이터 도구: [이터레이터 도구](ultimatepython/data_structures/itertools.py) ( 🤯 ) + - 시간 복잡도 : [cPython 연산](https://wiki.python.org/moin/TimeComplexity) ( 📚, 🤯 ) 4. **클래스** - - 기본 클래스 : [기본 정의](ultimatepython/classes/basic_class.py) (:cake:) + - 기본 클래스 : [기본 정의](ultimatepython/classes/basic_class.py) ( 🍰 ) + - 계승: [계승](ultimatepython/classes/inheritance.py) ( 🍰 ) - 추상 클래스 : [추상 정의](ultimatepython/classes/abstract_class.py) - 예외 클래스 : [예외 정의](ultimatepython/classes/exception_class.py) - - 반복기 클래스 : [반복기 정의 | 수익률](ultimatepython/classes/iterator_class.py) (:exploding_head:) + - 이터레이터 클래스 : [이터레이터 정의 | yield](ultimatepython/classes/iterator_class.py) ( 🤯 ) + - 캡슐화: [캡슐화 정의](ultimatepython/classes/encapsulation.py) 5. **고급** - - 데코레이터 : [데코레이터 정의 | 랩](ultimatepython/advanced/decorator.py) (:exploding_head:) - - 컨텍스트 관리자 : [컨텍스트 관리자](ultimatepython/advanced/context_manager.py) (:exploding_head:) - - 메서드 해결 순서 : [mro](ultimatepython/advanced/mro.py) (:exploding_head:) - - Mixin : [Mixin 정의](ultimatepython/advanced/mixin.py) (:exploding_head:) - - 메타 클래스 : [메타 클래스 정의](ultimatepython/advanced/meta_class.py) (:exploding_head:) - - 글타래 (쓰레드) : [ThreadPoolExecutor](ultimatepython/advanced/thread.py) (:exploding_head:) - - Asyncio : [비동기 | 기다리다](ultimatepython/advanced/async.py) (:exploding_head:) - - 약한 참조 : [weakref](ultimatepython/advanced/weak_ref.py) (:exploding_head:) - - 벤치 마크 : [cProfile | pstats](ultimatepython/advanced/benchmark.py) (:exploding_head:) - - 조롱 : [MagicMock | PropertyMock | 패치](ultimatepython/advanced/mocking.py) (:exploding_head:) - - 정규식 : [검색 | findall | 일치 | fullmatch](ultimatepython/advanced/regex.py) (:exploding_head:) - - 데이터 형식 : [json | xml | csv](ultimatepython/advanced/data_format.py) (:exploding_head:) - - 날짜 시간 : [datetime | timezone](ultimatepython/advanced/date_time.py) (:exploding_head:) + - 데코레이터 : [데코레이터 정의 | wraps](ultimatepython/advanced/decorator.py) ( 🤯 ) + - 파일 처리: [파일 처리](ultimatepython/advanced/file_handling.py) ( 🤯 ) + - 컨텍스트 매니저 : [컨텍스트 매니저](ultimatepython/advanced/context_manager.py) ( 🤯 ) + - 메서드 결정 순서 : [mro](ultimatepython/advanced/mro.py) ( 🤯 ) + - 믹스인 : [믹스인 정의](ultimatepython/advanced/mixin.py) ( 🤯 ) + - 메타클래스 : [메타클래스 정의](ultimatepython/advanced/meta_class.py) ( 🤯 ) + - 스레드 : [ThreadPoolExecutor](ultimatepython/advanced/thread.py) ( 🤯 ) + - Asyncio : [async | await](ultimatepython/advanced/async.py) ( 🤯 ) + - 약한 참조 : [weakref](ultimatepython/advanced/weak_ref.py) ( 🤯 ) + - 벤치마크 : [cProfile | pstats](ultimatepython/advanced/benchmark.py) ( 🤯 ) + - 모킹 : [MagicMock | PropertyMock | patch](ultimatepython/advanced/mocking.py) ( 🤯 ) + - 정규식 : [search | findall | match | fullmatch](ultimatepython/advanced/regex.py) ( 🤯 ) + - 데이터 포맷 : [json | xml | csv](ultimatepython/advanced/data_format.py) ( 🤯 ) + - 날짜와 시간 : [datetime | timezone](ultimatepython/advanced/date_time.py) ( 🤯 ) + - 패턴 매칭: [match | case](ultimatepython/advanced/pattern_matching.py) ( 🤯 ) ## 추가 자료 -:necktie: = 인터뷰 리소스, -:test_tube: = 코드 샘플, -:brain: = 프로젝트 아이디어 +👔 = 인터뷰 자료, +🧪 = 코드 샘플, +🧠 = 프로젝트 아이디어 ### GitHub 저장소 -다른 잘 알려진 자료를 읽으면서 계속 배우십시오. +잘 알려진 다른 자료를 읽으면서 계속 배우세요. -- [TheAlgorithms/Python](https://github.com/TheAlgorithms/Python) (:necktie:, :test_tube:) -- [faif/python-patterns](https://github.com/faif/python-patterns) (:necktie:, :test_tube:) -- [geekcomputers/Python](https://github.com/geekcomputers/Python) (:test_tube:) -- [trekhleb/homemade-machine-learning](https://github.com/trekhleb/homemade-machine-learning) (:test_tube:) -- [karan/Projects](https://github.com/karan/Projects) (:brain:) -- [MunGell/awesome-for-beginners](https://github.com/MunGell/awesome-for-beginners) (:brain:) +- [TheAlgorithms/Python](https://github.com/TheAlgorithms/Python) ( 👔 , 🧪 ) +- [faif/python-patterns](https://github.com/faif/python-patterns) ( 👔 , 🧪 ) +- [geekcomputers/Python](https://github.com/geekcomputers/Python) ( 🧪 ) +- [trekhleb/homemade-machine-learning](https://github.com/trekhleb/homemade-machine-learning) ( 🧪 ) +- [karan/Projects](https://github.com/karan/Projects) ( 🧠 ) +- [MunGell/awesome-for-beginners](https://github.com/MunGell/awesome-for-beginners) ( 🧠 ) - [vinta/awesome-python](https://github.com/vinta/awesome-python) - [academic/awesome-datascience](https://github.com/academic/awesome-datascience) - [josephmisiti/awesome-machine-learning](https://github.com/josephmisiti/awesome-machine-learning) - [ZuzooVn/machine-learning-for-software-engineers](https://github.com/ZuzooVn/machine-learning-for-software-engineers) -- [30-seconds/30-seconds-of-python](https://github.com/30-seconds/30-seconds-of-python) (:test_tube:) +- [30-seconds/30-seconds-of-python](https://github.com/30-seconds/30-seconds-of-python) ( 🧪 ) - [ml-tooling/best-of-python](https://github.com/ml-tooling/best-of-python) +- [practical-tutorials/project-based-learning](https://github.com/practical-tutorials/project-based-learning#python) +- [freeCodeCamp/freeCodeCamp](https://github.com/freeCodeCamp/freeCodeCamp) ( 👔 ) +- [microsoft/ML-For-Beginners](https://github.com/microsoft/ML-For-Beginners) ( 🧪 ) +- [microsoft/Data-Science-For-Beginners](https://github.com/microsoft/Data-Science-For-Beginners) ( 🧪 ) +- [Avik-Jain/100-Days-Of-ML-Code](https://github.com/Avik-Jain/100-Days-Of-ML-Code) ( 🧪 ) + +### 저자의 프로젝트 + +이러한 개념을 익힌 후 무엇을 만들 수 있는지 보여주는 Python으로 제작한 프로젝트들입니다: + +- [huangsam/chowist](https://github.com/huangsam/chowist) ( 🧪 ) +- [huangsam/githooks](https://github.com/huangsam/githooks) ( 🧪 ) +- [huangsam/ragchain](https://github.com/huangsam/ragchain) ( 🧪 ) +- [huangsam/mailprune](https://github.com/huangsam/mailprune) ( 🧪 ) -### 대화 형 연습 +### 대화형 연습 -코딩 기술이 녹슬지 않도록 계속 연습하십시오. +코딩 실력이 녹슬지 않기 위해 계속 연습하세요. -- [leetcode.com](https://leetcode.com/) (:necktie:) -- [hackerrank.com](https://www.hackerrank.com/) (:necktie:) -- [kaggle.com](https://www.kaggle.com/) (:brain:) +- [codechef.com](https://www.codechef.com/) ( 👔 ) +- [codeforces.com](https://codeforces.com/) +- [codementor.io](https://www.codementor.io) ( 🧠 ) +- [coderbyte.com](https://www.coderbyte.com/) ( 👔 ) +- [codewars.com](https://www.codewars.com/) - [exercism.io](https://exercism.io/) +- [geeksforgeeks.org](https://www.geeksforgeeks.org/) ( 👔 ) +- [hackerearth.com](https://www.hackerearth.com/) +- [hackerrank.com](https://www.hackerrank.com/) ( 👔 ) +- [kaggle.com](https://www.kaggle.com/) ( 🧠 ) +- [labex.io](https://labex.io/exercises/python)( 🧪 ) +- [leetcode.com](https://leetcode.com/) ( 👔 ) - [projecteuler.net](https://projecteuler.net/) -- [DevProjects](https://www.codementor.io/projects/python) -- [codewars.com](https://www.codewars.com/) +- [replit.com](https://replit.com/) +- [w3schools.com](https://www.w3schools.com/python/) ( 🧪 ) +- [teclado.com](https://teclado.com/30-days-of-python/#prerequisites) ( 👔 ) +- [fullstakpython.org](https://fullstackpython.org/) ( 🧪 ) + +## 시대의 별 관측자 + +[![Stargazers over time](https://starchart.cc/huangsam/ultimate-python.svg?variant=adaptive)](https://starchart.cc/huangsam/ultimate-python) diff --git a/README.md b/README.md index a34fb4bb..bcdc806b 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,12 @@ # Ultimate Python study guide -[![CircleCI](https://img.shields.io/circleci/build/github/huangsam/ultimate-python)](https://circleci.com/gh/huangsam/ultimate-python) +[![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/huangsam/ultimate-python/ci.yml)](https://github.com/huangsam/ultimate-python/actions) [![Code Coverage](https://img.shields.io/codecov/c/github/huangsam/ultimate-python)](https://codecov.io/gh/huangsam/ultimate-python) [![Quality Gate Status](https://img.shields.io/sonar/quality_gate/huangsam_ultimate-python?server=https%3A%2F%2Fsonarcloud.io)](https://sonarcloud.io/dashboard?id=huangsam_ultimate-python) -[![License](https://img.shields.io/github/license/huangsam/ultimate-python)](https://github.com/huangsam/ultimate-python/blob/master/LICENSE) -[![r/Python](https://img.shields.io/reddit/subreddit-subscribers/Python)](https://www.reddit.com/r/Python/comments/inllmf/ultimate_python_study_guide/) +[![License](https://img.shields.io/github/license/huangsam/ultimate-python)](https://github.com/huangsam/ultimate-python/blob/main/LICENSE) +[![r/Python](https://img.shields.io/badge/reddit-original_post-red)](https://www.reddit.com/r/Python/comments/inllmf/ultimate_python_study_guide/) -Ultimate Python study guide for newcomers and professionals alike. :snake: :snake: :snake: +Ultimate Python study guide for newcomers and professionals alike. 🐍 🐍 🐍 ```python print("Ultimate Python study guide") @@ -16,7 +16,12 @@ print("Ultimate Python study guide") [한국어](README.ko.md) | [繁体中文](README.zh_tw.md) | [Español](README.es.md) | -[Deutsch](README.de.md) +[Deutsch](README.de.md) | +[Français](README.fr.md) | +[हिन्दी](README.hi.md) | +[Português - Brasil](README.pt_br.md) + +Ultimate Python ## Motivation @@ -26,13 +31,13 @@ large-scale companies and an open-source contributor of repositories like [Celery](https://github.com/celery/celery) and [Full Stack Python](https://github.com/mattmakai/fullstackpython.com). I look forward to seeing more people learn Python and pursue their passions -through it. :mortar_board: +through it. 🎓 ## Goals Here are the primary goals of creating this guide: -:trophy: **Serve as a resource** for Python newcomers who prefer to learn hands-on. +🏆 **Serve as a resource** for Python newcomers who prefer to learn hands-on. This repository has a collection of standalone modules which can be run in an IDE like [PyCharm](https://www.jetbrains.com/pycharm/) and in the browser like [Replit](https://replit.com/languages/python3). Even a plain old terminal will work @@ -41,7 +46,7 @@ through what the programs are doing step-by-step. Users are encouraged to modify source code anywhere as long as the `main` routines are not deleted and [run successfully](runner.py) after each change. -:trophy: **Serve as a pure guide** for those who want to revisit core Python concepts. +🏆 **Serve as a pure guide** for those who want to revisit core Python concepts. Only [builtin libraries](https://docs.python.org/3/library/) are leveraged so that these concepts can be conveyed without the overhead of domain-specific concepts. As such, popular open-source libraries and frameworks (i.e. `sqlalchemy`, `requests`, @@ -66,83 +71,122 @@ There are two ways of running the modules: ## Table of contents -:books: = External resource, -:cake: = Beginner topic, -:exploding_head: = Advanced topic +📚 = External resource, +🍰 = Beginner topic, +🤯 = Advanced topic 1. **About Python** - - Overview: [What is Python](https://github.com/trekhleb/learn-python/blob/master/src/getting_started/what_is_python.md) (:books:, :cake:) - - Design philosophy: [The Zen of Python](https://www.python.org/dev/peps/pep-0020/) (:books:) - - Style guide: [Style Guide for Python Code](https://www.python.org/dev/peps/pep-0008/) (:books:, :exploding_head:) - - Data model: [Data model](https://docs.python.org/3/reference/datamodel.html) (:books:, :exploding_head:) - - Standard library: [The Python Standard Library](https://docs.python.org/3/library/) (:books:, :exploding_head:) - - Built-in functions: [Built-in Functions](https://docs.python.org/3/library/functions.html) (:books:) + - Overview: [What is Python](https://github.com/trekhleb/learn-python/blob/master/src/getting_started/what_is_python.md) ( 📚, 🍰 ) + - Design philosophy: [The Zen of Python](https://www.python.org/dev/peps/pep-0020/) ( 📚 ) + - Style guide: [Style Guide for Python Code](https://www.python.org/dev/peps/pep-0008/) ( 📚, 🤯 ) + - Data model: [Data model](https://docs.python.org/3/reference/datamodel.html) ( 📚, 🤯 ) + - Standard library: [The Python Standard Library](https://docs.python.org/3/library/) ( 📚, 🤯 ) + - Built-in functions: [Built-in Functions](https://docs.python.org/3/library/functions.html) ( 📚 ) 2. **Syntax** - - Variable: [Built-in literals](ultimatepython/syntax/variable.py) (:cake:) - - Expression: [Numeric operations](ultimatepython/syntax/expression.py) (:cake:) - - Conditional: [if | if-else | if-elif-else](ultimatepython/syntax/conditional.py) (:cake:) - - Loop: [for-loop | while-loop](ultimatepython/syntax/loop.py) (:cake:) - - Function: [def | lambda](ultimatepython/syntax/function.py) (:cake:) + - Variable: [Built-in literals](ultimatepython/syntax/variable.py) ( 🍰 ) + - Expression: [Numeric operations](ultimatepython/syntax/expression.py) ( 🍰 ) + - Bitwise: [Bitwise operators](ultimatepython/syntax/bitwise.py) ( 🍰 ), [One's/Two's Complement](https://www.geeksforgeeks.org/difference-between-1s-complement-representation-and-2s-complement-representation-technique/) ( 📚 ) + - Conditional: [if | if-else | if-elif-else](ultimatepython/syntax/conditional.py) ( 🍰 ) + - Loop: [for-loop | while-loop](ultimatepython/syntax/loop.py) ( 🍰 ) + - Function: [def | lambda](ultimatepython/syntax/function.py) ( 🍰 ) + - Walrus operator: [Assignment expressions :=](ultimatepython/syntax/walrus_operator.py) ( 🤯 ) + - Argument enforcement: [Positional-only / | Keyword-only *](ultimatepython/syntax/arg_enforcement.py) ( 🤯 ) 3. **Data Structures** - - List: [List operations](ultimatepython/data_structures/list.py) (:cake:) + - List: [List operations](ultimatepython/data_structures/list.py) ( 🍰 ) - Tuple: [Tuple operations](ultimatepython/data_structures/tuple.py) - Set: [Set operations](ultimatepython/data_structures/set.py) - - Dict: [Dictionary operations](ultimatepython/data_structures/dict.py) (:cake:) + - Dict: [Dictionary operations](ultimatepython/data_structures/dict.py) ( 🍰 ) + - Dict union: [Dictionary merge | and |=](ultimatepython/data_structures/dict_union.py) ( 🤯 ) - Comprehension: [list | tuple | set | dict](ultimatepython/data_structures/comprehension.py) - - String: [String operations](ultimatepython/data_structures/string.py) (:cake:) - - Deque: [deque](ultimatepython/data_structures/deque.py) (:exploding_head:) - - Time complexity: [cPython operations](https://wiki.python.org/moin/TimeComplexity) (:books:, :exploding_head:) + - String: [String operations](ultimatepython/data_structures/string.py) ( 🍰 ) + - Deque: [deque](ultimatepython/data_structures/deque.py) ( 🤯 ) + - Namedtuple: [namedtuple](ultimatepython/data_structures/namedtuple.py) ( 🤯 ) + - Defaultdict: [defaultdict](ultimatepython/data_structures/defaultdict.py) ( 🤯 ) + - Itertools: [Iterator tools](ultimatepython/data_structures/itertools.py) ( 🤯 ) + - Time complexity: [cPython operations](https://wiki.python.org/moin/TimeComplexity) ( 📚, 🤯 ) 4. **Classes** - - Basic class: [Basic definition](ultimatepython/classes/basic_class.py) (:cake:) + - Basic class: [Basic definition](ultimatepython/classes/basic_class.py) ( 🍰 ) + - Inheritance: [Inheritance](ultimatepython/classes/inheritance.py) ( 🍰 ) - Abstract class: [Abstract definition](ultimatepython/classes/abstract_class.py) - Exception class: [Exception definition](ultimatepython/classes/exception_class.py) - - Iterator class: [Iterator definition | yield](ultimatepython/classes/iterator_class.py) (:exploding_head:) + - Iterator class: [Iterator definition | yield](ultimatepython/classes/iterator_class.py) ( 🤯 ) + - Encapsulation: [Encapsulation definition](ultimatepython/classes/encapsulation.py) 5. **Advanced** - - Decorator: [Decorator definition | wraps](ultimatepython/advanced/decorator.py) (:exploding_head:) - - Context manager: [Context managers](ultimatepython/advanced/context_manager.py) (:exploding_head:) - - Method resolution order: [mro](ultimatepython/advanced/mro.py) (:exploding_head:) - - Mixin: [Mixin definition](ultimatepython/advanced/mixin.py) (:exploding_head:) - - Metaclass: [Metaclass definition](ultimatepython/advanced/meta_class.py) (:exploding_head:) - - Thread: [ThreadPoolExecutor](ultimatepython/advanced/thread.py) (:exploding_head:) - - Asyncio: [async | await](ultimatepython/advanced/async.py) (:exploding_head:) - - Weak reference: [weakref](ultimatepython/advanced/weak_ref.py) (:exploding_head:) - - Benchmark: [cProfile | pstats](ultimatepython/advanced/benchmark.py) (:exploding_head:) - - Mocking: [MagicMock | PropertyMock | patch](ultimatepython/advanced/mocking.py) (:exploding_head:) - - Regular expression: [search | findall | match | fullmatch](ultimatepython/advanced/regex.py) (:exploding_head:) - - Data format: [json | xml | csv](ultimatepython/advanced/data_format.py) (:exploding_head:) - - Datetime: [datetime | timezone](ultimatepython/advanced/date_time.py) (:exploding_head:) + - Decorator: [Decorator definition | wraps](ultimatepython/advanced/decorator.py) ( 🤯 ) + - File Handling: [File Handling](ultimatepython/advanced/file_handling.py) ( 🤯 ) + - Context manager: [Context managers](ultimatepython/advanced/context_manager.py) ( 🤯 ) + - Method resolution order: [mro](ultimatepython/advanced/mro.py) ( 🤯 ) + - Mixin: [Mixin definition](ultimatepython/advanced/mixin.py) ( 🤯 ) + - Metaclass: [Metaclass definition](ultimatepython/advanced/meta_class.py) ( 🤯 ) + - Thread: [ThreadPoolExecutor](ultimatepython/advanced/thread.py) ( 🤯 ) + - Asyncio: [async | await](ultimatepython/advanced/async.py) ( 🤯 ) + - Weak reference: [weakref](ultimatepython/advanced/weak_ref.py) ( 🤯 ) + - Benchmark: [cProfile | pstats](ultimatepython/advanced/benchmark.py) ( 🤯 ) + - Mocking: [MagicMock | PropertyMock | patch](ultimatepython/advanced/mocking.py) ( 🤯 ) + - Regular expression: [search | findall | match | fullmatch](ultimatepython/advanced/regex.py) ( 🤯 ) + - Data format: [json | xml | csv](ultimatepython/advanced/data_format.py) ( 🤯 ) + - Datetime: [datetime | timezone](ultimatepython/advanced/date_time.py) ( 🤯 ) + - Pattern matching: [match | case](ultimatepython/advanced/pattern_matching.py) ( 🤯 ) ## Additional resources -:necktie: = Interview resource, -:test_tube: = Code samples, -:brain: = Project ideas +👔 = Interview resource, +🧪 = Code samples, +🧠 = Project ideas ### GitHub repositories Keep learning by reading from other well-regarded resources. -- [TheAlgorithms/Python](https://github.com/TheAlgorithms/Python) (:necktie:, :test_tube:) -- [faif/python-patterns](https://github.com/faif/python-patterns) (:necktie:, :test_tube:) -- [geekcomputers/Python](https://github.com/geekcomputers/Python) (:test_tube:) -- [trekhleb/homemade-machine-learning](https://github.com/trekhleb/homemade-machine-learning) (:test_tube:) -- [karan/Projects](https://github.com/karan/Projects) (:brain:) -- [MunGell/awesome-for-beginners](https://github.com/MunGell/awesome-for-beginners) (:brain:) +- [TheAlgorithms/Python](https://github.com/TheAlgorithms/Python) ( 👔 , 🧪 ) +- [faif/python-patterns](https://github.com/faif/python-patterns) ( 👔 , 🧪 ) +- [geekcomputers/Python](https://github.com/geekcomputers/Python) ( 🧪 ) +- [trekhleb/homemade-machine-learning](https://github.com/trekhleb/homemade-machine-learning) ( 🧪 ) +- [karan/Projects](https://github.com/karan/Projects) ( 🧠 ) +- [MunGell/awesome-for-beginners](https://github.com/MunGell/awesome-for-beginners) ( 🧠 ) - [vinta/awesome-python](https://github.com/vinta/awesome-python) - [academic/awesome-datascience](https://github.com/academic/awesome-datascience) - [josephmisiti/awesome-machine-learning](https://github.com/josephmisiti/awesome-machine-learning) - [ZuzooVn/machine-learning-for-software-engineers](https://github.com/ZuzooVn/machine-learning-for-software-engineers) -- [30-seconds/30-seconds-of-python](https://github.com/30-seconds/30-seconds-of-python) (:test_tube:) +- [30-seconds/30-seconds-of-python](https://github.com/30-seconds/30-seconds-of-python) ( 🧪 ) - [ml-tooling/best-of-python](https://github.com/ml-tooling/best-of-python) +- [practical-tutorials/project-based-learning](https://github.com/practical-tutorials/project-based-learning#python) +- [freeCodeCamp/freeCodeCamp](https://github.com/freeCodeCamp/freeCodeCamp) ( 👔 ) +- [microsoft/ML-For-Beginners](https://github.com/microsoft/ML-For-Beginners) ( 🧪 ) +- [microsoft/Data-Science-For-Beginners](https://github.com/microsoft/Data-Science-For-Beginners) ( 🧪 ) +- [Avik-Jain/100-Days-Of-ML-Code](https://github.com/Avik-Jain/100-Days-Of-ML-Code) ( 🧪 ) + +### Author projects + +Projects I've built with Python that showcase what you can create after learning these concepts: + +- [huangsam/chowist](https://github.com/huangsam/chowist) ( 🧪 ) +- [huangsam/githooks](https://github.com/huangsam/githooks) ( 🧪 ) +- [huangsam/ragchain](https://github.com/huangsam/ragchain) ( 🧪 ) +- [huangsam/mailprune](https://github.com/huangsam/mailprune) ( 🧪 ) ### Interactive practice Keep practicing so that your coding skills don't get rusty. -- [leetcode.com](https://leetcode.com/) (:necktie:) -- [hackerrank.com](https://www.hackerrank.com/) (:necktie:) -- [kaggle.com](https://www.kaggle.com/) (:brain:) +- [codechef.com](https://www.codechef.com/) ( 👔 ) +- [codeforces.com](https://codeforces.com/) +- [codementor.io](https://www.codementor.io) ( 🧠 ) +- [coderbyte.com](https://www.coderbyte.com/) ( 👔 ) +- [codewars.com](https://www.codewars.com/) - [exercism.io](https://exercism.io/) +- [geeksforgeeks.org](https://www.geeksforgeeks.org/) ( 👔 ) +- [hackerearth.com](https://www.hackerearth.com/) +- [hackerrank.com](https://www.hackerrank.com/) ( 👔 ) +- [kaggle.com](https://www.kaggle.com/) ( 🧠 ) +- [labex.io](https://labex.io/exercises/python)( 🧪 ) +- [leetcode.com](https://leetcode.com/) ( 👔 ) - [projecteuler.net](https://projecteuler.net/) -- [DevProjects](https://www.codementor.io/projects/python) -- [codewars.com](https://www.codewars.com/) +- [replit.com](https://replit.com/) +- [w3schools.com](https://www.w3schools.com/python/) ( 🧪 ) +- [teclado.com](https://teclado.com/30-days-of-python/#prerequisites) ( 👔 ) +- [fullstakpython.org](https://fullstackpython.org/) ( 🧪 ) + +## Stargazers over time + +[![Stargazers over time](https://starchart.cc/huangsam/ultimate-python.svg?variant=adaptive)](https://starchart.cc/huangsam/ultimate-python) diff --git a/README.pt_br.md b/README.pt_br.md new file mode 100644 index 00000000..1a6b20bd --- /dev/null +++ b/README.pt_br.md @@ -0,0 +1,178 @@ +# Ultimate Python - O seu guia de estudos de Python definitivo + +[![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/huangsam/ultimate-python/ci.yml)](https://github.com/huangsam/ultimate-python/actions) +[![Code Coverage](https://img.shields.io/codecov/c/github/huangsam/ultimate-python)](https://codecov.io/gh/huangsam/ultimate-python) +[![Quality Gate Status](https://img.shields.io/sonar/quality_gate/huangsam_ultimate-python?server=https%3A%2F%2Fsonarcloud.io)](https://sonarcloud.io/dashboard?id=huangsam_ultimate-python) +[![License](https://img.shields.io/github/license/huangsam/ultimate-python)](https://github.com/huangsam/ultimate-python/blob/main/LICENSE) +[![r/Python](https://img.shields.io/badge/reddit-original_post-red)](https://www.reddit.com/r/Python/comments/inllmf/ultimate_python_study_guide/) + +Guia de estudo definitivo de Python para iniciantes e profissionais. 🐍 🐍 🐍 + +```python +print("Ultimate Python - O seu guia de estudos de Python definitivo") +``` + +[English](README.md) | +[한국어](README.ko.md) | +[繁体中文](README.zh_tw.md) | +[Español](README.es.md) | +[Deutsch](README.de.md) | +[Français](README.fr.md) | +[हिन्दी](README.hi.md) | +[Português - Brasil](README.pt_br.md) + +Ultimate Python - O seu guia de estudos de Python definitivo + +## Motivação + +Eu criei este repositório a fim de compartilhar o que eu aprendi sobre o [básico de Python](https://www.python.org/) nos último 5+ anos de uso como graduado universitário, um empregado em uma empresa de grande porte e um contribuidor de repositórios open-source como [Celery](https://github.com/celery/celery) e +[Full Stack Python](https://github.com/mattmakai/fullstackpython.com). +Eu estou ansiono para ver mais pessoas aprendendo Python e buscando suas paixões através disso. 🎓 + +## Objetivos + +Aqui estão os principais objetivos da criação deste guia: + +🏆 **Servir como um recurso** para iniciantes em Python que preferem aprender na prática. +Este repositório possui uma coleção de módulos autônomos que podem ser executados em um IDE como [PyCharm](https://www.jetbrains.com/pycharm/) e no navegador como [Replit](https://replit.com/languages/python3). Até mesmo um terminal simples funcionará com os exemplos. +A maioria das linhas possui comentários cuidadosamente elaborados que guiam o leitor passo a passo sobre o que os programas estão fazendo. Usuários são incentivados a modificar o código fonte em qualquer lugar, desde que as rotinas `main` não sejam excluídas e [sejam executadas com sucesso](runner.py) após cada alteração. + +🏆 **Servir como um guia prático** para aqueles que queiram revisitar os conceitos básicos de Python. +Apenas [blibliotecas internas](https://docs.python.org/3/library/) são utilizadas para que esses conceitos possam ser transmitidos sem a sobrecarga de conceitos específicos de domínio. +Dessa forma, bibliotecas e frameworks populares de código aberto (como por exemplo `sqlalchemy`, `requests`, +`pandas`) não são instalados. No entanto, ler o código fonte desses estruturas é inspirador e altamente recomendado se o seu objetivo é se tornar um verdadeiro [Pythonista](https://www.urbandictionary.com/define.php?term=pythonista). + +## Começando + +[![Run on Replit](https://replit.com/badge/github/huangsam/ultimate-python)](https://replit.com/github/huangsam/ultimate-python) + +Click no emblema acima para criar um ambiente de trabalho no navegador sem a necessidade de instalar Git e Python na sua máquina local. Se esses requisitos já forem atendidos (se você já tem isso instalado), sinta-se à vontade para clonar o repositório diretamente. + +Uma vez que o repositório esteja acessível você está pronto para aprender com os módulos independentes. Para aproveitar ao máximo cada módulo, leia o código do módulo e execute-o. + +Existem duas maneiras de rodar os módulos: + +1. Execute um módulo único: `python ultimatepython/syntax/variable.py` +2. Execute todos os módulos: `python runner.py` + +## Índice + +📚 = Recurso externo, +🍰 = Tópico para iniciantes, +🤯 = Tópico avançado + +1. **Sobre Python** + - Visão geral: [O que é Python](https://github.com/trekhleb/learn-python/blob/master/src/getting_started/what_is_python.md) ( 📚, 🍰 ) + - Filosofia de design: [O zen do Python](https://www.python.org/dev/peps/pep-0020/) ( 📚 ) + - Guia de estilo: [Guia de estilo para código Python](https://www.python.org/dev/peps/pep-0008/) ( 📚, 🤯 ) + - Modelo de dados: [Modelo de dados](https://docs.python.org/3/reference/datamodel.html) ( 📚, 🤯 ) + - Biblioteca padrão: [A Biblioteca padrão do Python](https://docs.python.org/3/library/) ( 📚, 🤯 ) + - Funções integradas: [Funções integradas](https://docs.python.org/3/library/functions.html) ( 📚 ) +2. **Sintaxe** + - Variável: [Literais integrados](ultimatepython/syntax/variable.py) ( 🍰 ) + - Expressão: [Operações numéricas](ultimatepython/syntax/expression.py) ( 🍰 ) + - Bitwise: [Operadores bitwise](ultimatepython/syntax/bitwise.py) ( 🍰 ), [Complemento de Um/Dois](https://www.geeksforgeeks.org/difference-between-1s-complement-representation-and-2s-complement-representation-technique/) ( 📚 ) + - Condicional: [if | if-else | if-elif-else](ultimatepython/syntax/conditional.py) ( 🍰 ) + - Loop/Laço: [for-loop | while-loop](ultimatepython/syntax/loop.py) ( 🍰 ) + - Função: [def | lambda](ultimatepython/syntax/function.py) ( 🍰 ) + - Operador morsa: [Expressões de atribuição :=](ultimatepython/syntax/walrus_operator.py) ( 🤯 ) + - Aplicação de argumentos: [Somente posicional / | Somente palavra-chave *](ultimatepython/syntax/arg_enforcement.py) ( 🤯 ) +3. **Estrutura de dados** + - Lista: [Operações de lista](ultimatepython/data_structures/list.py) ( 🍰 ) + - Tupla: [Operações de tuplas](ultimatepython/data_structures/tuple.py) + - Conjunto: [Operações de conjuntos](ultimatepython/data_structures/set.py) + - Dicionário: [Operações de dicionários](ultimatepython/data_structures/dict.py) ( 🍰 ) + - União de dicionários: [Fusão de dicionários | e |=](ultimatepython/data_structures/dict_union.py) ( 🤯 ) + - Comprehension: [list | tuple | set | dict](ultimatepython/data_structures/comprehension.py) + - String: [Operações de String](ultimatepython/data_structures/string.py) ( 🍰 ) + - Deque: [deque](ultimatepython/data_structures/deque.py) ( 🤯 ) + - Namedtuple: [namedtuple](ultimatepython/data_structures/namedtuple.py) ( 🤯 ) + - Defaultdict: [defaultdict](ultimatepython/data_structures/defaultdict.py) ( 🤯 ) + - Ferramentas de iteradores: [Ferramentas de iteradores](ultimatepython/data_structures/itertools.py) ( 🤯 ) + - Time complexity: [Operações de cPython](https://wiki.python.org/moin/TimeComplexity) ( 📚, 🤯 ) +4. **Classes** + - O básico de classes: [Definição de classe](ultimatepython/classes/basic_class.py) ( 🍰 ) + - Herança: [Herança](ultimatepython/classes/inheritance.py) ( 🍰 ) + - Classe abstrata: [Definição de classe abstrata](ultimatepython/classes/abstract_class.py) + - Classe de exceção: [Definição de Classe de exceção](ultimatepython/classes/exception_class.py) + - Classe Iterator: [Definição de classe Iterator | yield](ultimatepython/classes/iterator_class.py) ( 🤯 ) + - Encapsulamento: [Definição de encapsulamento](ultimatepython/classes/encapsulation.py) +5. **Avançado** + - Decorator: [Definição de decorator | wraps](ultimatepython/advanced/decorator.py) ( 🤯 ) + - Manuseio de arquivos: [Manuseio de arquivos](ultimatepython/advanced/file_handling.py) ( 🤯 ) + - Gerenciador de contexto: [Gerenciador de contexto](ultimatepython/advanced/context_manager.py) ( 🤯 ) + - Ordem de resolução do método: [mro](ultimatepython/advanced/mro.py) ( 🤯 ) + - Mixin: [Definição de mixin](ultimatepython/advanced/mixin.py) ( 🤯 ) + - Metaclass: [Definição de metaclass](ultimatepython/advanced/meta_class.py) ( 🤯 ) + - Thread: [ThreadPoolExecutor](ultimatepython/advanced/thread.py) ( 🤯 ) + - Asyncio: [async | await](ultimatepython/advanced/async.py) ( 🤯 ) + - Referência fraca: [weakref](ultimatepython/advanced/weak_ref.py) ( 🤯 ) + - Benchmark: [cProfile | pstats](ultimatepython/advanced/benchmark.py) ( 🤯 ) + - Mocking: [MagicMock | PropertyMock | patch](ultimatepython/advanced/mocking.py) ( 🤯 ) + - Expressões regulares (regexp): [search | findall | match | fullmatch](ultimatepython/advanced/regex.py) ( 🤯 ) + - Formato de dados: [json | xml | csv](ultimatepython/advanced/data_format.py) ( 🤯 ) + - Datetime: [datetime | timezone](ultimatepython/advanced/date_time.py) ( 🤯 ) + - Correspondência de padrões: [match | case](ultimatepython/advanced/pattern_matching.py) ( 🤯 ) + +## Recursos adicionais + +👔 = Recurso para entrevista, +🧪 = Exemplos de código, +🧠 = Ideias para projetos + +### Repositórios GitHub + +Continue aprendendo lendo outros recursos bem conceituados. + +- [TheAlgorithms/Python](https://github.com/TheAlgorithms/Python) ( 👔 , 🧪 ) +- [faif/python-patterns](https://github.com/faif/python-patterns) ( 👔 , 🧪 ) +- [geekcomputers/Python](https://github.com/geekcomputers/Python) ( 🧪 ) +- [trekhleb/homemade-machine-learning](https://github.com/trekhleb/homemade-machine-learning) ( 🧪 ) +- [karan/Projects](https://github.com/karan/Projects) ( 🧠 ) +- [MunGell/awesome-for-beginners](https://github.com/MunGell/awesome-for-beginners) ( 🧠 ) +- [vinta/awesome-python](https://github.com/vinta/awesome-python) +- [academic/awesome-datascience](https://github.com/academic/awesome-datascience) +- [josephmisiti/awesome-machine-learning](https://github.com/josephmisiti/awesome-machine-learning) +- [ZuzooVn/machine-learning-for-software-engineers](https://github.com/ZuzooVn/machine-learning-for-software-engineers) +- [30-seconds/30-seconds-of-python](https://github.com/30-seconds/30-seconds-of-python) ( 🧪 ) +- [ml-tooling/best-of-python](https://github.com/ml-tooling/best-of-python) +- [practical-tutorials/project-based-learning](https://github.com/practical-tutorials/project-based-learning#python) +- [freeCodeCamp/freeCodeCamp](https://github.com/freeCodeCamp/freeCodeCamp) ( 👔 ) +- [microsoft/ML-For-Beginners](https://github.com/microsoft/ML-For-Beginners) ( 🧪 ) +- [microsoft/Data-Science-For-Beginners](https://github.com/microsoft/Data-Science-For-Beginners) ( 🧪 ) +- [Avik-Jain/100-Days-Of-ML-Code](https://github.com/Avik-Jain/100-Days-Of-ML-Code) ( 🧪 ) + +### Projetos do autor + +Projetos que construí com Python que mostram o que você pode criar após aprender esses conceitos: + +- [huangsam/chowist](https://github.com/huangsam/chowist) ( 🧪 ) +- [huangsam/githooks](https://github.com/huangsam/githooks) ( 🧪 ) +- [huangsam/ragchain](https://github.com/huangsam/ragchain) ( 🧪 ) +- [huangsam/mailprune](https://github.com/huangsam/mailprune) ( 🧪 ) + +### Prática interativa + +Continue praticando para que suas habilidades de codificação não enferrujem. + +- [codechef.com](https://www.codechef.com/) ( 👔 ) +- [codeforces.com](https://codeforces.com/) +- [codementor.io](https://www.codementor.io) ( 🧠 ) +- [coderbyte.com](https://www.coderbyte.com/) ( 👔 ) +- [codewars.com](https://www.codewars.com/) +- [exercism.io](https://exercism.io/) +- [geeksforgeeks.org](https://www.geeksforgeeks.org/) ( 👔 ) +- [hackerearth.com](https://www.hackerearth.com/) +- [hackerrank.com](https://www.hackerrank.com/) ( 👔 ) +- [kaggle.com](https://www.kaggle.com/) ( 🧠 ) +- [labex.io](https://labex.io/exercises/python)( 🧪 ) +- [leetcode.com](https://leetcode.com/) ( 👔 ) +- [projecteuler.net](https://projecteuler.net/) +- [replit.com](https://replit.com/) +- [w3schools.com](https://www.w3schools.com/python/) ( 🧪 ) +- [teclado.com](https://teclado.com/30-days-of-python/#prerequisites) ( 👔 ) +- [fullstakpython.org](https://fullstackpython.org/) ( 🧪 ) + +## Astrônomos no tempo + +[![Stargazers over time](https://starchart.cc/huangsam/ultimate-python.svg?variant=adaptive)](https://starchart.cc/huangsam/ultimate-python) diff --git a/README.zh_tw.md b/README.zh_tw.md index da0f3901..caba49bb 100644 --- a/README.zh_tw.md +++ b/README.zh_tw.md @@ -1,12 +1,12 @@ # Ultimate Python 學習大綱 -[![CircleCI](https://img.shields.io/circleci/build/github/huangsam/ultimate-python)](https://circleci.com/gh/huangsam/ultimate-python) +[![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/huangsam/ultimate-python/ci.yml)](https://github.com/huangsam/ultimate-python/actions) [![Code Coverage](https://img.shields.io/codecov/c/github/huangsam/ultimate-python)](https://codecov.io/gh/huangsam/ultimate-python) [![Quality Gate Status](https://img.shields.io/sonar/quality_gate/huangsam_ultimate-python?server=https%3A%2F%2Fsonarcloud.io)](https://sonarcloud.io/dashboard?id=huangsam_ultimate-python) -[![License](https://img.shields.io/github/license/huangsam/ultimate-python)](https://github.com/huangsam/ultimate-python/blob/master/LICENSE) -[![r/Python](https://img.shields.io/reddit/subreddit-subscribers/Python)](https://www.reddit.com/r/Python/comments/inllmf/ultimate_python_study_guide/) +[![License](https://img.shields.io/github/license/huangsam/ultimate-python)](https://github.com/huangsam/ultimate-python/blob/main/LICENSE) +[![r/Python](https://img.shields.io/badge/reddit-original_post-red)](https://www.reddit.com/r/Python/comments/inllmf/ultimate_python_study_guide/) -Ultimate Python 學習大綱 - 適用於新手和專業人士。:snake: :snake: :snake: +Ultimate Python 學習大綱 - 適用於新手和專業人士。🐍 🐍 🐍 ```python print("Ultimate Python 學習大綱") @@ -16,28 +16,33 @@ print("Ultimate Python 學習大綱") [한국어](README.ko.md) | [繁体中文](README.zh_tw.md) | [Español](README.es.md) | -[Deutsch](README.de.md) +[Deutsch](README.de.md) | +[Français](README.fr.md) | +[हिन्दी](README.hi.md) | +[Português - Brasil](README.pt_br.md) + +Ultimate Python ## 動力 我為了分享過去五年作為一個學生,大公司員工,以及開源(例如 Celery 和 Full Stack Python)貢獻者所習得的知識而創 -建了這個代碼倉庫。我期待更多人能抱持熱忱並開始一段與Python的美好旅程。:mortar_board: +建了這個代碼倉庫。我期待更多人能抱持熱忱並開始一段與Python的美好旅程。🎓 ## 目標 這是創建本指南的主要目標: -:trophy: **為喜歡動手學習的Python新手提供資源。** 本存儲庫集合了不同題目的獨立模組範例,而每個模組可以獨立在普通 +🏆 **為喜歡動手學習的Python新手提供資源。** 本存儲庫集合了不同題目的獨立模組範例,而每個模組可以獨立在普通 終端機(Terminal),IDE(如PyCharm)或者瀏覽器(如Repl.it)中運行。範例中的註解都經過精心編寫,引導讀者逐步了解程 式流程。在不刪除主例程(main)並在修改後成功運行大前題下,我鼓勵讀者修改源代碼作練習。 -:trophy: **為想重溫Python核心概念的程式員提供指南。** 本存儲庫主要借助內置庫(builtin libraries)作重溫工具, +🏆 **為想重溫Python核心概念的程式員提供指南。** 本存儲庫主要借助內置庫(builtin libraries)作重溫工具, 故不需額外安裝開源庫(如`sqlalchemy`,`requests`,`pandas`)。但是,如果您的目標是成為一個真正的Python 達人(Pythonista),那麼我會鼓勵您閱讀這些源代碼,而激發靈感。 ## 學習之旅 -[![Run on Repl.it](https://repl.it/badge/github/huangsam/ultimate-python)](https://repl.it/github/huangsam/ultimate-python) +[![Run on Replit](https://replit.com/badge/github/huangsam/ultimate-python)](https://replit.com/github/huangsam/ultimate-python) 單擊上面的徽章就可在瀏覽器中啟動工作環境,而無需在電腦上額外安裝Git和Python。當你完成啟動,請複製這存儲庫。 當你可以開啟你所複製存儲庫後,您就準備好Python學習之旅!善用每個模組,請細讀註解並嘗試運行模組代碼。 @@ -49,83 +54,118 @@ print("Ultimate Python 學習大綱") ## 目錄 -:books: = 外部資源, -:cake: = 入門題目, -:exploding_head: = 進階題目 +📚 = 外部資源, +🍰 = 入門題目, +🤯 = 進階題目 1. **關於 Python** - - 概述:[什麼是 Python](https://github.com/trekhleb/learn-python/blob/master/src/getting_started/what_is_python.md) (:books:, :cake:) - - 設計理念:[Python之格言](https://www.python.org/dev/peps/pep-0020/) (:books:) - - 樣式指南:[Python代碼樣式指南](https://www.python.org/dev/peps/pep-0008/) (:books:, :exploding_head:) - - 數據模型:[數據模型](https://docs.python.org/3/reference/datamodel.html) (:books:, :exploding_head:) - - 標準庫:[Python標準庫](https://docs.python.org/3/library/) (:books:, :exploding_head:) - - 內置函式:[內置函式](https://docs.python.org/3/library/functions.html) (:books:) + - 概述:[什麼是 Python](https://github.com/trekhleb/learn-python/blob/master/src/getting_started/what_is_python.md) ( 📚, 🍰 ) + - 設計理念:[Python之格言](https://www.python.org/dev/peps/pep-0020/) ( 📚 ) + - 樣式指南:[Python代碼樣式指南](https://www.python.org/dev/peps/pep-0008/) ( 📚, 🤯 ) + - 數據模型:[數據模型](https://docs.python.org/3/reference/datamodel.html) ( 📚, 🤯 ) + - 標準庫:[Python標準庫](https://docs.python.org/3/library/) ( 📚, 🤯 ) + - 內置函式:[內置函式](https://docs.python.org/3/library/functions.html) ( 📚 ) 2. **語法** - - 變數:[內置值](ultimatepython/syntax/variable.py) (:cake:) - - 運算式:[數值運算](ultimatepython/syntax/expression.py) (:cake:) - - 條件運算式:[if | if-else | if-elif-else](ultimatepython/syntax/conditional.py) (:cake:) - - 迴圈:[for迴圈 | while迴圈](ultimatepython/syntax/loop.py) (:cake:) - - 定義函式:[def | lambda](ultimatepython/syntax/function.py) (:cake:) + - 變數:[內置值](ultimatepython/syntax/variable.py) ( 🍰 ) + - 運算式:[數值運算](ultimatepython/syntax/expression.py) ( 🍰 ) + - 按位: [中的位元運算符](ultimatepython/syntax/bitwise.py) ( 🍰 ), [一個的補語/補碼](https://www.geeksforgeeks.org/difference-between-1s-complement-representation-and-2s-complement-representation-technique/) ( 📚 ) + - 條件運算式:[if | if-else | if-elif-else](ultimatepython/syntax/conditional.py) ( 🍰 ) + - 迴圈:[for迴圈 | while迴圈](ultimatepython/syntax/loop.py) ( 🍰 ) + - 定義函式:[def | lambda](ultimatepython/syntax/function.py) ( 🍰 ) + - 海象運算子:[賦值表達式 :=](ultimatepython/syntax/walrus_operator.py) ( 🤯 ) + - 參數強制:[僅位置 / | 僅關鍵字 *](ultimatepython/syntax/arg_enforcement.py) ( 🤯 ) 3. **資料結構** - - 列表:[列表操作](ultimatepython/data_structures/list.py) (:cake:) + - 列表:[列表操作](ultimatepython/data_structures/list.py) ( 🍰 ) - 元組:[元組操作](ultimatepython/data_structures/tuple.py) - 集合:[集合操作](ultimatepython/data_structures/set.py) - - 字典:[字典操作](ultimatepython/data_structures/dict.py) (:cake:) + - 字典:[字典操作](ultimatepython/data_structures/dict.py) ( 🍰 ) + - 字典聯合:[字典合併 | 和 |=](ultimatepython/data_structures/dict_union.py) ( 🤯 ) - 綜合:[list | tuple | set | dict](ultimatepython/data_structures/comprehension.py) - - 字串:[字串操作](ultimatepython/data_structures/string.py) (:cake:) - - 雙端隊列:[deque](ultimatepython/data_structures/deque.py) (:exploding_head:) - - 時間複雜度:[cPython操作](https://wiki.python.org/moin/TimeComplexity) (:books:, :exploding_head:) + - 字串:[字串操作](ultimatepython/data_structures/string.py) ( 🍰 ) + - 雙端隊列:[deque](ultimatepython/data_structures/deque.py) ( 🤯 ) + - Namedtuple: [namedtuple](ultimatepython/data_structures/namedtuple.py) ( 🤯 ) + - Defaultdict: [defaultdict](ultimatepython/data_structures/defaultdict.py) ( 🤯 ) + - 迭代器工具:[迭代器工具](ultimatepython/data_structures/itertools.py) ( 🤯 ) + - 時間複雜度:[cPython操作](https://wiki.python.org/moin/TimeComplexity) ( 📚, 🤯 ) 4. **類別** - - 基本類別:[基本定義](ultimatepython/classes/basic_class.py) (:cake:) + - 基本類別:[基本定義](ultimatepython/classes/basic_class.py) ( 🍰 ) - 抽象類別:[抽象定義](ultimatepython/classes/abstract_class.py) - 異常類別:[異常定義](ultimatepython/classes/exception_class.py) - - 迭代類別:[迭代器定義](ultimatepython/classes/iterator_class.py) (:exploding_head:) + - 迭代類別:[迭代器定義](ultimatepython/classes/iterator_class.py) ( 🤯 ) + - 封裝: [封裝定義](ultimatepython/classes/encapsulation.py) 5. **進階技巧** - - 裝飾器:[Decorator definition | wraps](ultimatepython/advanced/decorator.py) (:exploding_head:) - - 資源管理器:[Context managers](ultimatepython/advanced/context_manager.py) (:exploding_head:) - - 方法解析順序:[mro](ultimatepython/advanced/mro.py) (:exploding_head:) - - Mixin:[Mixin定義](ultimatepython/advanced/mixin.py) (:exploding_head:) - - 元類:[Metaclass定義](ultimatepython/advanced/meta_class.py) (:exploding_head:) - - 執行緒:[ThreadPoolExecutor](ultimatepython/advanced/thread.py) (:exploding_head:) - - 異步:[async | await](ultimatepython/advanced/async.py) (:exploding_head:) - - 弱引用:[weakref](ultimatepython/advanced/weak_ref.py) (:exploding_head:) - - 基準:[cProfile | pstats](ultimatepython/advanced/benchmark.py) (:exploding_head:) - - 模擬:[MagicMock | PropertyMock | patch](ultimatepython/advanced/mocking.py) (:exploding_head:) - - 正規表示式:[search | findall | match | fullmatch](ultimatepython/advanced/regex.py) (:exploding_head:) - - 數據格式:[json | xml | csv](ultimatepython/advanced/data_format.py) (:exploding_head:) - - 日期時間: [datetime | timezone](ultimatepython/advanced/date_time.py) (:exploding_head:) + - 裝飾器:[Decorator definition | wraps](ultimatepython/advanced/decorator.py) ( 🤯 ) + - 文件處理: [File Handling](ultimatepython/advanced/file_handling.py) ( 🤯 ) + - 資源管理器:[Context managers](ultimatepython/advanced/context_manager.py) ( 🤯 ) + - 方法解析順序:[mro](ultimatepython/advanced/mro.py) ( 🤯 ) + - Mixin:[Mixin定義](ultimatepython/advanced/mixin.py) ( 🤯 ) + - 元類:[Metaclass定義](ultimatepython/advanced/meta_class.py) ( 🤯 ) + - 執行緒:[ThreadPoolExecutor](ultimatepython/advanced/thread.py) ( 🤯 ) + - 異步:[async | await](ultimatepython/advanced/async.py) ( 🤯 ) + - 弱引用:[weakref](ultimatepython/advanced/weak_ref.py) ( 🤯 ) + - 基準:[cProfile | pstats](ultimatepython/advanced/benchmark.py) ( 🤯 ) + - 模擬:[MagicMock | PropertyMock | patch](ultimatepython/advanced/mocking.py) ( 🤯 ) + - 正規表示式:[search | findall | match | fullmatch](ultimatepython/advanced/regex.py) ( 🤯 ) + - 數據格式:[json | xml | csv](ultimatepython/advanced/data_format.py) ( 🤯 ) + - 日期時間: [datetime | timezone](ultimatepython/advanced/date_time.py) ( 🤯 ) + - 模式匹配:[match | case](ultimatepython/advanced/pattern_matching.py) ( 🤯 ) ## 額外資源 -:necktie: = 面試資源, -:test_tube: = 代碼範例, -:brain: = 項目構想 +👔 = 面試資源, +🧪 = 代碼範例, +🧠 = 項目構想 ### GitHub儲存庫 通過閱讀其他備受尊重的資源來繼續學習。 -- [TheAlgorithms/Python](https://github.com/TheAlgorithms/Python) (:necktie:, :test_tube:) -- [faif/python-patterns](https://github.com/faif/python-patterns) (:necktie:, :test_tube:) -- [geekcomputers/Python](https://github.com/geekcomputers/Python) (:test_tube:) -- [trekhleb/homemade-machine-learning](https://github.com/trekhleb/homemade-machine-learning) (:test_tube:) -- [karan/Projects](https://github.com/karan/Projects) (:brain:) -- [MunGell/awesome-for-beginners](https://github.com/MunGell/awesome-for-beginners) (:brain:) +- [TheAlgorithms/Python](https://github.com/TheAlgorithms/Python) ( 👔, 🧪 ) +- [faif/python-patterns](https://github.com/faif/python-patterns) ( 👔, 🧪 ) +- [geekcomputers/Python](https://github.com/geekcomputers/Python) ( 🧪 ) +- [trekhleb/homemade-machine-learning](https://github.com/trekhleb/homemade-machine-learning) ( 🧪 ) +- [karan/Projects](https://github.com/karan/Projects) ( 🧠 ) +- [MunGell/awesome-for-beginners](https://github.com/MunGell/awesome-for-beginners) ( 🧠 ) - [vinta/awesome-python](https://github.com/vinta/awesome-python) - [academic/awesome-datascience](https://github.com/academic/awesome-datascience) - [josephmisiti/awesome-machine-learning](https://github.com/josephmisiti/awesome-machine-learning) - [ZuzooVn/machine-learning-for-software-engineers](https://github.com/ZuzooVn/machine-learning-for-software-engineers) -- [30-seconds/30-seconds-of-python](https://github.com/30-seconds/30-seconds-of-python) (:test_tube:) +- [30-seconds/30-seconds-of-python](https://github.com/30-seconds/30-seconds-of-python) ( 🧪 ) - [ml-tooling/best-of-python](https://github.com/ml-tooling/best-of-python) +- [practical-tutorials/project-based-learning](https://github.com/practical-tutorials/project-based-learning#python) +- [freeCodeCamp/freeCodeCamp](https://github.com/freeCodeCamp/freeCodeCamp) ( 👔 ) + +### 作者的專案 + +我用 Python 構建的專案,展示學習這些概念後可以創造的內容: + +- [huangsam/chowist](https://github.com/huangsam/chowist) ( 🧪 ) +- [huangsam/githooks](https://github.com/huangsam/githooks) ( 🧪 ) +- [huangsam/ragchain](https://github.com/huangsam/ragchain) ( 🧪 ) +- [huangsam/mailprune](https://github.com/huangsam/mailprune) ( 🧪 ) ### 互動練習 繼續練習才能使您的編碼技能不會生疏。 -- [leetcode.com](https://leetcode.com/) (:necktie:) -- [hackerrank.com](https://www.hackerrank.com/) (:necktie:) -- [kaggle.com](https://www.kaggle.com/) (:brain:) +- [codechef.com](https://www.codechef.com/) ( 👔 ) +- [codeforces.com](https://codeforces.com/) +- [codementor.io](https://www.codementor.io) ( 🧠 ) +- [coderbyte.com](https://www.coderbyte.com/) ( 👔 ) +- [codewars.com](https://www.codewars.com/) - [exercism.io](https://exercism.io/) +- [geeksforgeeks.org](https://www.geeksforgeeks.org/) ( 👔 ) +- [hackerearth.com](https://www.hackerearth.com/) +- [hackerrank.com](https://www.hackerrank.com/) ( 👔 ) +- [kaggle.com](https://www.kaggle.com/) ( 🧠 ) +- [labex.io](https://labex.io/exercises/python)( 🧪 ) +- [leetcode.com](https://leetcode.com/) ( 👔 ) - [projecteuler.net](https://projecteuler.net/) -- [DevProjects](https://www.codementor.io/projects/python) -- [codewars.com](https://www.codewars.com/) +- [replit.com](https://replit.com/) +- [w3schools.com](https://www.w3schools.com/python/) ( 🧪 ) +- [teclado.com](https://teclado.com/30-days-of-python/#prerequisites) ( 👔 ) +- [fullstakpython.org](https://fullstackpython.org/) ( 🧪 ) + +## 歷代觀星者 + +[![Stargazers over time](https://starchart.cc/huangsam/ultimate-python.svg?variant=adaptive)](https://starchart.cc/huangsam/ultimate-python) diff --git a/codecov.yml b/codecov.yml new file mode 100644 index 00000000..1ba81633 --- /dev/null +++ b/codecov.yml @@ -0,0 +1,10 @@ +# https://docs.codecov.com/docs/common-recipe-list +# https://docs.codecov.com/docs/commit-status +coverage: + status: + project: + default: + target: 90% + patch: + default: + target: 90% diff --git a/images/ultimatepython.webp b/images/ultimatepython.webp new file mode 100644 index 00000000..c055f065 Binary files /dev/null and b/images/ultimatepython.webp differ diff --git a/pre-commit.sh b/pre-commit.sh new file mode 100755 index 00000000..a9006951 --- /dev/null +++ b/pre-commit.sh @@ -0,0 +1,59 @@ +#!/bin/bash +# pre-commit.sh: Run the same checks as CI (see .github/workflows/ci.yml) +# Usage: +# ./pre-commit.sh # Run checks +# ./pre-commit.sh install # Install as .git/hooks/pre-commit + +set -euo pipefail + +if [[ "${1:-}" == "install" ]]; then + hook_path=".git/hooks/pre-commit" + cp -- "$0" "$hook_path" + chmod +x "$hook_path" + echo "Installed pre-commit hook to $hook_path" + exit 0 +fi + +# 1. Find the project root +PROJECT_ROOT="$(git rev-parse --show-toplevel)" + +# 2. Define standard virtual environment names +VENV_NAMES=(".venv" "venv") + +# 3. Locate the virtual environment directory +VENV_DIR="" +for name in "${VENV_NAMES[@]}"; do + CANDIDATE="$PROJECT_ROOT/$name" + if [ -d "$CANDIDATE" ]; then + VENV_DIR="$CANDIDATE" + break + fi +done + +# 4. Check if a virtual environment was found +if [ -z "$VENV_DIR" ]; then + echo "Error: Virtual environment not found. Please create one (e.g., 'python3 -m venv .venv') and run the hook again." + exit 1 +fi + +# 5. Define the full path to the Python interpreter within the found VENV +PYTHON_EXEC="$VENV_DIR/bin/python" + +# 6. Check if the interpreter exists +if [ ! -x "$PYTHON_EXEC" ]; then + echo "Error: Python executable not found at $PYTHON_EXEC" + exit 1 +fi + +# --- Use the specific Python executable for all commands --- + +# Run all examples +"$PYTHON_EXEC" runner.py + +# Lint and format checks (ruff and isort are installed in the venv) +"$PYTHON_EXEC" -m ruff check +"$PYTHON_EXEC" -m isort --check --diff . + +# Coverage +"$PYTHON_EXEC" -m coverage run runner.py +"$PYTHON_EXEC" -m coverage report --fail-under=80 diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 00000000..914e24f8 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,28 @@ +[tool.ruff] +line-length = 160 + +[tool.isort] +multi_line_output = 3 +include_trailing_comma = true +force_grid_wrap = 0 +use_parentheses = true +ensure_newline_before_comments = true +line_length = 160 + +[tool.coverage.run] +branch = true + +[tool.coverage.report] +exclude_lines = [ + "skip: (if|else)", + "def __repr__", + "raise NotImplementedError", + "if __name__ == .__main__.:", + "any\\(" +] +fail_under = 80 +omit = [ + "venv/**", + "runner.py", + "**/__init__.py" +] diff --git a/requirements.txt b/requirements.txt index a8a5633d..3f45511b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,4 @@ -coverage==7.2.1 -flake8==6.0.0 -isort==5.12.0 +coverage==7.13.0 +isort==7.0.0 +ruff==0.14.10 +mypy==1.19.1 diff --git a/runner.py b/runner.py index afcfabb1..5b684ba5 100644 --- a/runner.py +++ b/runner.py @@ -13,17 +13,17 @@ _RUNNER_MAIN = "main" -def success_text(text): +def success_text(text: str) -> str: """Get success text.""" return f"{_STYLE_SUCCESS}{bold_text(text)}{_STYLE_END}" -def bold_text(text): +def bold_text(text: str) -> str: """Get bold text.""" return f"{_STYLE_BOLD}{text}{_STYLE_END}" -def main(): +def main() -> None: print(bold_text(f"Start {root_name} runner")) for item in walk_packages(root_path, f"{root_name}."): diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index db4d247a..00000000 --- a/setup.cfg +++ /dev/null @@ -1,20 +0,0 @@ -[coverage:run] -branch = True - -[coverage:report] -exclude_lines = - skip: (if|else) - def __repr__ - raise NotImplementedError - if __name__ == .__main__.: - any\( -fail_under = 80 -omit = - venv/** - runner.py - **/__init__.py - -[flake8] -max-line-length = 160 -exclude = - venv diff --git a/setup.py b/setup.py deleted file mode 100644 index 4a1adffe..00000000 --- a/setup.py +++ /dev/null @@ -1,16 +0,0 @@ -from setuptools import find_packages, setup - -setup( - name="ultimate-python", - version="1.0.0", - packages=find_packages(), - description="Ultimate Python study guide", - classifiers=[ - "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.7", - "Programming Language :: Python :: 3.8", - "Programming Language :: Python :: 3.9", - "Programming Language :: Python :: 3.10", - "Programming Language :: Python :: 3.11", - ], -) diff --git a/ultimatepython/advanced/async.py b/ultimatepython/advanced/async.py index d7efbc59..0265c9e2 100644 --- a/ultimatepython/advanced/async.py +++ b/ultimatepython/advanced/async.py @@ -1,18 +1,25 @@ """ -Concurrent programming with an event loop is a relatively new concept in -Python 3.x. This module aims to highlight how it could be used in the -context of a scheduler which runs a fire-and-forget operation for starting -jobs. In the real world, it takes time for a scheduler to start a job (i.e. -hit an API endpoint, ask the operating system for resources) so we assume -that starting a job has some intrinsic delay. +Concurrent programming with asyncio, introduced in Python 3.4, provides +an event loop for handling asynchronous operations. This module demonstrates +basic asyncio patterns including coroutines, tasks, concurrent execution +with gather, and task cancellation. It uses the context of a scheduler +which runs fire-and-forget operations for starting jobs, assuming that +job startup has some intrinsic delay. + +This module also covers advanced asyncio patterns including task groups +for structured concurrency (Python 3.11+), semaphores for limiting +concurrency, timeouts, exception handling in concurrent tasks, event +loop management, and task shielding to protect critical operations from +cancellation. """ + import asyncio from dataclasses import dataclass from datetime import datetime from uuid import uuid4 # Module-level constants -_DELAY_SMALL = .001 +_DELAY_SMALL = 0.001 _DELAY_LARGE = 3600 @@ -30,12 +37,12 @@ def _is_valid_record(record): return record.queued_at < record.started_at -def _current_time(): +def _current_time() -> datetime: """Return current time that is timezone-naive.""" return datetime.now() -async def start_job(job_id, delay): +async def start_job(job_id: str, delay: float) -> JobRecord: """Start job ID after a certain amount of delay.""" queue_time = _current_time() await asyncio.sleep(delay) @@ -43,8 +50,15 @@ async def start_job(job_id, delay): return JobRecord(job_id, queue_time, start_time) -async def schedule_jobs(): - """Schedule jobs concurrently.""" +async def failing_job(job_id: str) -> None: + """A job that sometimes fails.""" + if int(job_id[-1]) % 3 == 0: # Fail every 3rd job + raise ValueError(f"Job {job_id} failed!") + await asyncio.sleep(_DELAY_SMALL) + + +async def basic_async_patterns() -> None: + """Basic async patterns demonstration.""" # Start a job which also represents a coroutine single_job = start_job(uuid4().hex, _DELAY_SMALL) assert asyncio.iscoroutine(single_job) @@ -76,8 +90,111 @@ async def schedule_jobs(): assert all(_is_valid_record(record) for record in batch_records) -def main(): - asyncio.run(schedule_jobs()) +async def advanced_async_patterns() -> None: + """Demonstrate advanced asyncio patterns.""" + + # Task Groups - structured concurrency (Python 3.11+) + async def task_group_example(): + try: + async with asyncio.TaskGroup() as tg: + # Start multiple tasks in a group + for i in range(5): + tg.create_task(start_job(f"task_{i}", _DELAY_SMALL)) + except Exception: + # TaskGroup propagates exceptions from child tasks + pass + + # All tasks in the group complete or fail together + assert True # TaskGroup structure is valid + + await task_group_example() + + # Semaphores for limiting concurrency + semaphore = asyncio.Semaphore(3) # Allow max 3 concurrent operations + + async def limited_concurrency_job(job_id: str): + async with semaphore: + # Only 3 jobs can execute this section at once + await asyncio.sleep(_DELAY_SMALL) + return f"completed_{job_id}" + + # Start 10 jobs but only 3 can run concurrently + concurrent_jobs = [limited_concurrency_job(f"sem_{i}") for i in range(10)] + concurrent_results = await asyncio.gather(*concurrent_jobs) + assert len(concurrent_results) == 10 + assert all("completed_" in result for result in concurrent_results) + + # Exception handling with gather + mixed_jobs = [ + failing_job("job_1"), # succeeds + failing_job("job_2"), # succeeds + failing_job("job_3"), # fails + failing_job("job_4"), # succeeds + ] + + # Return exceptions instead of raising them + results = await asyncio.gather(*mixed_jobs, return_exceptions=True) + assert len(results) == 4 + # Check that we got a mix of results and exceptions + exceptions_found = sum(1 for r in results if isinstance(r, Exception)) + successes_found = sum(1 for r in results if not isinstance(r, Exception)) + assert exceptions_found == 1 # One job failed + assert successes_found == 3 # Three jobs succeeded + + # Timeouts and cancellation + async def slow_job(): + await asyncio.sleep(1.0) # Takes 1 second + return "slow_result" + + try: + # Timeout after 0.1 seconds + result = await asyncio.wait_for(slow_job(), timeout=0.1) + except asyncio.TimeoutError: + result = None + assert result is None # Should timeout + + # Event loop management + loop = asyncio.get_running_loop() + assert isinstance(loop, asyncio.AbstractEventLoop) + + # Schedule callback on the event loop + callback_result = None + + def sync_callback(): + nonlocal callback_result + callback_result = "callback_executed" + + # Schedule callback to run soon + loop.call_soon(sync_callback) + await asyncio.sleep(0) # Let the event loop process callbacks + assert callback_result == "callback_executed" + + # Shielding tasks from cancellation + async def important_task(): + await asyncio.sleep(_DELAY_SMALL) + return "important_result" + + task = asyncio.create_task(important_task()) + shielded_task = asyncio.shield(task) + + # Even if we cancel the shield, the underlying task continues + shielded_task.cancel() + try: + await shielded_task + except asyncio.CancelledError: + pass + + # The original task should still complete + await task # Wait for the original task + assert task.result() == "important_result" + + +def main() -> None: + # Run basic patterns + asyncio.run(basic_async_patterns()) + + # Run advanced patterns + asyncio.run(advanced_async_patterns()) if __name__ == "__main__": diff --git a/ultimatepython/advanced/benchmark.py b/ultimatepython/advanced/benchmark.py index 386f95bd..0c8a8e58 100644 --- a/ultimatepython/advanced/benchmark.py +++ b/ultimatepython/advanced/benchmark.py @@ -5,13 +5,14 @@ and their code intuition to optimize programs further. This module uses cProfile to compare the performance of two functions with each other. """ + import cProfile import io import pstats import time # Module-level constants -_SLEEP_DURATION = .001 +_SLEEP_DURATION = 0.001 def finish_slower(): @@ -54,8 +55,7 @@ def main(): # large projects. Consider profiling in isolation when analyzing complex # classes and functions ps.print_stats() - time_sleep_called = any("60" in line and "time.sleep" in line - for line in buffer.getvalue().split("\n")) + time_sleep_called = any("60" in line and "time.sleep" in line for line in buffer.getvalue().split("\n")) assert time_sleep_called is True diff --git a/ultimatepython/advanced/context_manager.py b/ultimatepython/advanced/context_manager.py index 4467fb35..09285431 100644 --- a/ultimatepython/advanced/context_manager.py +++ b/ultimatepython/advanced/context_manager.py @@ -5,8 +5,10 @@ we simulate how a context manager can handle open and close operations of a file-like object called StringIO. """ + from contextlib import contextmanager from io import StringIO +from typing import Generator # Simple directory with file contents _FILESYSTEM = { @@ -17,7 +19,7 @@ @contextmanager -def file(filename): +def file(filename: str) -> Generator[StringIO, None, None]: """File context manager. This is the function variant of the context manager. Context managers @@ -41,19 +43,19 @@ class FileHandler: class or simply write a function. """ - def __init__(self, filename): + def __init__(self, filename: str) -> None: self.io_buffer = StringIO(_FILESYSTEM[filename]) - def __enter__(self): + def __enter__(self) -> StringIO: """Pass the buffer to the context block.""" return self.io_buffer - def __exit__(self, *args): + def __exit__(self, *args) -> None: """Close the buffer unconditionally.""" self.io_buffer.close() -def main(): +def main() -> None: # An example of a function-based context manager with file("a.txt") as txt_buffer: assert txt_buffer.read() == "Hello World" diff --git a/ultimatepython/advanced/data_format.py b/ultimatepython/advanced/data_format.py index bfd0800c..33133062 100644 --- a/ultimatepython/advanced/data_format.py +++ b/ultimatepython/advanced/data_format.py @@ -3,6 +3,7 @@ converting data to serialized objects for further analysis. This module shows how to parse and process these data formats: JSON, XML and CSV. """ + import json from csv import DictReader from dataclasses import dataclass, fields @@ -59,6 +60,7 @@ class Note: associated with them. To streamline the creation and comparison of these records, we define an in-memory model of what it is. """ + author: str title: str body: str @@ -84,12 +86,7 @@ def main(): # Let's use `ElementTree.parse` to parse note data from a XML file # https://docs.python.org/3/library/xml.html tree = ETree.parse(StringIO(_XML_DATA)) - xml_notes = [ - Note.from_data({ - field: note_el.findtext(field) - for field in Note.fields() - }) for note_el in tree.getroot() - ] + xml_notes = [Note.from_data({field: note_el.findtext(field) for field in Note.fields()}) for note_el in tree.getroot()] assert all(isinstance(note, Note) for note in xml_notes) # Let's use `csv.DictReader` to parse note data from a CSV file diff --git a/ultimatepython/advanced/date_time.py b/ultimatepython/advanced/date_time.py index dd65e11b..7b46bbdd 100644 --- a/ultimatepython/advanced/date_time.py +++ b/ultimatepython/advanced/date_time.py @@ -22,10 +22,11 @@ UTC timezone and show how it can be used to make the default `datetime` object more powerful. """ + from datetime import datetime, timezone -def convert_dt_to_utc_epoch(dt): +def convert_dt_to_utc_epoch(dt: datetime) -> float: """Convert datetime to UTC epoch seconds. Note that the timestamp method assumes that an offset-naive @@ -35,27 +36,27 @@ def convert_dt_to_utc_epoch(dt): return dt.timestamp() -def convert_utc_epoch_to_dt(epoch): +def convert_utc_epoch_to_dt(epoch: float) -> datetime: """Convert UTC epoch seconds to datetime.""" return datetime.fromtimestamp(epoch, tz=timezone.utc) -def convert_dt_timezone(dt, tz): +def convert_dt_timezone(dt: datetime, tz: timezone) -> datetime: """Convert datetime timezone.""" return dt.astimezone(tz=tz) -def get_utc_now_as_dt(): +def get_utc_now_as_dt() -> datetime: """Get current UTC time as datetime.""" return datetime.now(tz=timezone.utc) -def get_utc_now_as_epoch(): +def get_utc_now_as_epoch() -> float: """Get current UTC time as epoch seconds.""" return convert_dt_to_utc_epoch(get_utc_now_as_dt()) -def main(): +def main() -> None: # Create offset-naive datetime naive_dt = datetime.now() assert naive_dt.tzinfo is None diff --git a/ultimatepython/advanced/decorator.py b/ultimatepython/advanced/decorator.py index c7e173d3..e4561c9b 100644 --- a/ultimatepython/advanced/decorator.py +++ b/ultimatepython/advanced/decorator.py @@ -4,13 +4,15 @@ be decorated to work with a collection of strings. Note that the decorator handles nested collections with the use of recursion. """ + from functools import wraps +from typing import Any, Callable # Module-level constants _MASKING = "*" -def run_with_stringy(fn): +def run_with_stringy(fn: Callable[[str], str]) -> Callable[[Any], Any]: """Run a string function with a string or a collection of strings. We define a custom decorator that allows us to convert a function whose @@ -39,11 +41,11 @@ def run_with_stringy(fn): """ @wraps(fn) - def wrapper(obj): + def wrapper(obj: Any) -> Any: """Apply wrapped function to a string or a collection. This looks like a policy-based engine which runs a `return` statement - if a particular set of rules is true. Otherwise it aborts. This is + if a particular set of rules is true. Otherwise, it aborts. This is an example of the Strategy design pattern. https://en.wikipedia.org/wiki/Strategy_pattern @@ -64,14 +66,14 @@ def wrapper(obj): @run_with_stringy -def hide_content(content): +def hide_content(content: str) -> str: """Hide half of the string content.""" start_point = len(content) // 2 num_of_asterisks = len(content) // 2 + len(content) % 2 return content[:start_point] + _MASKING * num_of_asterisks -def _is_hidden(obj): +def _is_hidden(obj: Any) -> bool: """Check whether string or collection is hidden.""" if isinstance(obj, str): return _MASKING in obj @@ -80,7 +82,7 @@ def _is_hidden(obj): return all(_is_hidden(value) for value in obj) -def main(): +def main() -> None: # There is so much plain-text data out in the open insecure_data = [ {"username": "johndoe", "country": "USA"}, # User information diff --git a/ultimatepython/advanced/file_handling.py b/ultimatepython/advanced/file_handling.py new file mode 100644 index 00000000..e4908e20 --- /dev/null +++ b/ultimatepython/advanced/file_handling.py @@ -0,0 +1,121 @@ +""" +File handling is a fundamental concept in Python that involves +opening, reading, writing, and appending to files. This module +demonstrates both traditional and modern approaches using pathlib. + +Traditional approach: The builtin 'open' function works with string +paths and different modes like reading ('r'), writing ('w'), and +appending ('a'). + +Modern approach: pathlib.Path provides an object-oriented interface +for working with filesystem paths, offering cleaner syntax and +cross-platform support. pathlib is preferred for new code as it +replaces older os.path operations with an intuitive API. +""" + +import os +from pathlib import Path + +_TARGET_FILE = "sample.txt" + + +def read_file(filename: str) -> str: + """Read content from existing file.""" + with open(filename, "r") as file: + content = file.read() + return content + + +def write_file(filename: str, content: str) -> str: + """Write content to new file.""" + with open(filename, "w") as file: + file.write(content) + return f"Content written to '{filename}'." + + +def append_file(filename: str, content: str) -> str: + """Append content to existing file.""" + with open(filename, "a") as file: + file.write(content) + return f"Content appended to '{filename}'." + + +def delete_file(filename: str) -> str: + """Delete content of existing file.""" + os.remove(filename) + return f"'{filename}' has been deleted." + + +def write_file_pathlib(filename: str, content: str) -> str: + """Write content using pathlib.Path.""" + path = Path(filename) + path.write_text(content) + return f"Content written to '{filename}' using pathlib." + + +def read_file_pathlib(filename: str) -> str: + """Read content using pathlib.Path.""" + path = Path(filename) + return path.read_text() + + +def append_file_pathlib(filename: str, content: str) -> str: + """Append content using pathlib.Path.""" + path = Path(filename) + current = path.read_text() + path.write_text(current + content) + return f"Content appended to '{filename}' using pathlib." + + +def delete_file_pathlib(filename: str) -> str: + """Delete file using pathlib.Path.""" + path = Path(filename) + path.unlink() + return f"'{filename}' has been deleted using pathlib." + + +def main() -> None: + # Test traditional file operations + result = write_file(_TARGET_FILE, "This is a test.") + assert result == f"Content written to '{_TARGET_FILE}'." + + content = read_file(_TARGET_FILE) + assert content == "This is a test." + + append_result = append_file(_TARGET_FILE, "\nThis is an appended line.") + assert append_result == f"Content appended to '{_TARGET_FILE}'." + + content = read_file(_TARGET_FILE) + assert content == "This is a test.\nThis is an appended line." + + delete_result = delete_file(_TARGET_FILE) + assert delete_result == f"'{_TARGET_FILE}' has been deleted." + + # Test pathlib operations + pathlib_file = "pathlib_sample.txt" + result = write_file_pathlib(pathlib_file, "Pathlib is modern.") + assert result == f"Content written to '{pathlib_file}' using pathlib." + + content = read_file_pathlib(pathlib_file) + assert content == "Pathlib is modern." + + append_result = append_file_pathlib(pathlib_file, "\nIt's object-oriented.") + assert append_result == f"Content appended to '{pathlib_file}' using pathlib." + + content = read_file_pathlib(pathlib_file) + assert content == "Pathlib is modern.\nIt's object-oriented." + + # Test path operations with pathlib + path = Path(pathlib_file) + assert path.exists() + assert path.is_file() + assert path.suffix == ".txt" + assert path.stem == "pathlib_sample" + + delete_result = delete_file_pathlib(pathlib_file) + assert delete_result == f"'{pathlib_file}' has been deleted using pathlib." + assert not path.exists() + + +if __name__ == "__main__": + main() diff --git a/ultimatepython/advanced/meta_class.py b/ultimatepython/advanced/meta_class.py index eea77ae1..51fe51ba 100644 --- a/ultimatepython/advanced/meta_class.py +++ b/ultimatepython/advanced/meta_class.py @@ -3,6 +3,7 @@ This module shows how a metaclass can add database attributes and tables to "logic-free" model classes for the developer. """ + from abc import ABC @@ -32,7 +33,7 @@ class ModelMeta(type): """ # Model table registry - tables = {} + tables: dict[str, "ModelTable"] = {} def __new__(mcs, name, bases, attrs): """Factory for modifying the defined class at runtime. @@ -66,17 +67,13 @@ def __new__(mcs, name, bases, attrs): kls.model_fields.update(base.model_fields) # Fill model fields from itself - kls.model_fields.update({ - field_name: field_obj - for field_name, field_obj in attrs.items() - if isinstance(field_obj, BaseField) - }) + kls.model_fields.update({field_name: field_obj for field_name, field_obj in attrs.items() if isinstance(field_obj, BaseField)}) # Register a real table (a table with valid `model_name`) to # the metaclass `table` registry. After all the tables are # registered, the registry can be sent to a database adapter # which uses each table to create a properly defined schema - # for the database of choice (i.e. PostgreSQL, MySQL) + # for the database of choice (i.e. PostgresSQL, MySQL) if kls.model_name: kls.model_table = ModelTable(kls.model_name, kls.model_fields) ModelMeta.tables[kls.model_name] = kls.model_table @@ -121,12 +118,14 @@ class BaseModel(metaclass=ModelMeta): In short, think of a metaclass as the creator of classes. This is very similar to how classes are the creator of instances. """ + __abstract__ = True # This is NOT a real table row_id = IntegerField() class UserModel(BaseModel): """User model.""" + __table_name__ = "user_rocks" # This is a custom table name username = CharField() password = CharField() @@ -136,6 +135,7 @@ class UserModel(BaseModel): class AddressModel(BaseModel): """Address model.""" + user_id = IntegerField() address = CharField() state = CharField() @@ -168,8 +168,7 @@ def main(): # Every model is created by `ModelMeta` assert isinstance(BaseModel, ModelMeta) - assert all(isinstance(model, ModelMeta) - for model in BaseModel.__subclasses__()) + assert all(isinstance(model, ModelMeta) for model in BaseModel.__subclasses__()) # And `ModelMeta` is created by `type` assert isinstance(ModelMeta, type) diff --git a/ultimatepython/advanced/mixin.py b/ultimatepython/advanced/mixin.py index 9063fa03..0f7b1174 100644 --- a/ultimatepython/advanced/mixin.py +++ b/ultimatepython/advanced/mixin.py @@ -5,6 +5,7 @@ mixins to illustrate how mixins can make our lives easier when defining concrete classes. """ + from abc import ABC, abstractmethod from dataclasses import dataclass @@ -16,6 +17,7 @@ class Request: Assumes only GET requests for simplicity so there is no method attribute associated with this class. """ + url: str user: str @@ -26,7 +28,7 @@ class RequestHandler(ABC): In the real world, a URL is expected to handle different kinds of HTTP methods. To support this, we would define a `View` class with a method that dispatches the request payload to the appropriate HTTP handler. - Afterwards, we would register the class to a URL router. Check out + Afterward, we would register the class to a URL router. Check out the source code in Django and Flask to see how that works: https://github.com/django/django @@ -48,6 +50,7 @@ class TemplateHandlerMixin(RequestHandler): class helps if downstream developers typically implement request handlers that retrieve template content. """ + template_suffix = ".template" def handle(self, request): @@ -118,8 +121,7 @@ def get_template_name(self, request_url): return request_url[1:] def is_valid_template(self, template_name): - return (super().is_valid_template(template_name) - and template_name in self.template_dir) + return super().is_valid_template(template_name) and template_name in self.template_dir def render_template(self, template_name): return self.template_dir[template_name] @@ -143,8 +145,7 @@ def is_valid_user(self, request_user): def main(): # Handle requests with simple template handler - simple_dir = {"welcome.template": "

Hello world

", - "about.template": "

About me

"} + simple_dir = {"welcome.template": "

Hello world

", "about.template": "

About me

"} simple_handler = TemplateFolderHandler(simple_dir) welcome_from_nobody = Request("/welcome.template", "nobody") about_from_nobody = Request("/about.template", "nobody") @@ -155,8 +156,7 @@ def main(): # Handle requests with admin template handler admin_users = {"john", "jane"} - admin_dir = {"fqdn.template": "

server.example.com

", - "salary.template": "

123456789.00

"} + admin_dir = {"fqdn.template": "

server.example.com

", "salary.template": "

123456789.00

"} admin_handler = AdminTemplateHandler(admin_users, admin_dir) fqdn_from_john = Request("/fqdn.template", "john") salary_from_jane = Request("/salary.template", "jane") diff --git a/ultimatepython/advanced/mocking.py b/ultimatepython/advanced/mocking.py index 46fd2f71..8cef4e41 100644 --- a/ultimatepython/advanced/mocking.py +++ b/ultimatepython/advanced/mocking.py @@ -4,6 +4,7 @@ properly. This module shows how to use mocking to modify an application server so that it is easier to test. """ + from collections import Counter from unittest.mock import MagicMock, PropertyMock, patch diff --git a/ultimatepython/advanced/mro.py b/ultimatepython/advanced/mro.py index 0d140d2e..46f85c5b 100644 --- a/ultimatepython/advanced/mro.py +++ b/ultimatepython/advanced/mro.py @@ -1,5 +1,5 @@ """ -MRO stands for method resolution order and it's used by class definitions +MRO stands for method resolution order, and it's used by class definitions to determine which method will be run by a class instance. This module shows how the MRO is useful for the classic diamond problem where classes B and C depend on class A, and class D depends on classes B and C. @@ -49,12 +49,7 @@ def ping(self): def ping_pong(self): """Run `ping` and `pong` in different ways.""" - return [ - self.ping(), - super().ping(), - self.pong(), - super().pong() - ] + return [self.ping(), super().ping(), self.pong(), super().pong()] class IndecisivePlayer(NeutralPlayer, PongPlayer): @@ -78,18 +73,16 @@ def ping_pong(self): self.ping(), super().ping(), self.pong(), - super(PongPlayer, self).pong() # bypass MRO to `BasePlayer` + super(PongPlayer, self).pong(), # bypass MRO to `BasePlayer` ] def main(): # `ConfusedPlayer` methods are resolved from child to parent like this - assert ConfusedPlayer.mro() == [ - ConfusedPlayer, PongPlayer, NeutralPlayer, BasePlayer, object] + assert ConfusedPlayer.mro() == [ConfusedPlayer, PongPlayer, NeutralPlayer, BasePlayer, object] # `IndecisivePlayer` methods are resolved from child to parent like this - assert IndecisivePlayer.mro() == [ - IndecisivePlayer, NeutralPlayer, PongPlayer, BasePlayer, object] + assert IndecisivePlayer.mro() == [IndecisivePlayer, NeutralPlayer, PongPlayer, BasePlayer, object] # Show `ConfusedPlayer` method resolution in action assert ConfusedPlayer().ping_pong() == ["pINg", "ping", "PONG", "PONG"] @@ -102,7 +95,7 @@ def main(): # Creating a new class `ConfusedPlayer` and `IndecisivePlayer` # results in a `TypeError` because both classes do not have # matching MRO outputs. This means that they cannot be reconciled - # as one class. Hence `MissingPlayer` will not be created + # as one class. Hence, `MissingPlayer` will not be created type("MissingPlayer", (ConfusedPlayer, IndecisivePlayer), {}) except TypeError: class_creation_failed = True diff --git a/ultimatepython/advanced/pattern_matching.py b/ultimatepython/advanced/pattern_matching.py new file mode 100644 index 00000000..73f8119e --- /dev/null +++ b/ultimatepython/advanced/pattern_matching.py @@ -0,0 +1,335 @@ +""" +Structural pattern matching allows you to match complex data structures +against patterns and extract values in a clean, readable way. This feature +is similar to switch-case statements in other languages but much more powerful. + +Pattern matching was introduced in Python 3.10 through PEP 634, PEP 635, +and PEP 636. It uses the 'match' and 'case' keywords. +""" + + +def classify_number(value) -> str: + """Classify a number using pattern matching with literals. + + This demonstrates matching against specific literal values. + """ + match value: + case 0: + return "zero" + case 1: + return "one" + case 2: + return "two" + case _: + # The underscore _ is a wildcard that matches anything + return "other" + + +def classify_http_status(status) -> str: + """Classify HTTP status codes using pattern matching. + + This shows how pattern matching can make code more readable + than a series of if-elif-else statements. + """ + match status: + case 200: + return "OK" + case 201: + return "Created" + case 400: + return "Bad Request" + case 401: + return "Unauthorized" + case 404: + return "Not Found" + case 500: + return "Internal Server Error" + case _: + return "Unknown Status" + + +def process_point(point) -> str: + """Process a point tuple using pattern matching with sequences. + + This demonstrates pattern matching against tuple structures + and extracting values from them. + """ + match point: + case (0, 0): + return "Origin" + case (0, y): + # Match any point on the y-axis, capture y coordinate + return f"Y-axis at y={y}" + case (x, 0): + # Match any point on the x-axis, capture x coordinate + return f"X-axis at x={x}" + case (x, y): + # Match any other point, capture both coordinates + return f"Point at ({x}, {y})" + case _: + return "Not a valid 2D point" + + +def analyze_sequence(data) -> str: + """Analyze sequences using pattern matching. + + This shows how to match lists with specific structures + and extract elements. + """ + match data: + case []: + return "Empty list" + case [x]: + # Match a list with exactly one element + return f"Single element: {x}" + case [x, y]: + # Match a list with exactly two elements + return f"Pair: {x}, {y}" + case [first, *rest]: + # Match a list with at least one element + # The *rest captures remaining elements + return f"First: {first}, Rest: {rest}" + case _: + return "Not a list" # pragma: no cover + + +def process_command(command) -> str: + """Process commands using pattern matching with guards. + + Guards are if conditions that provide additional filtering + after a pattern match. + """ + match command: + case ["quit"]: + return "Quitting" + case ["go", direction] if direction in ["north", "south", "east", "west"]: + # Guard clause: only match if direction is valid + return f"Going {direction}" + case ["go", direction]: + # This matches any direction that failed the guard above + return f"Invalid direction: {direction}" + case ["take", item]: + return f"Taking {item}" + case ["take", item, quantity] if quantity > 0: + return f"Taking {quantity} {item}" + case ["take", item, quantity]: + return f"Invalid quantity: {quantity}" + case _: + return "Unknown command" + + +class Point: + """A simple 2D point class for pattern matching examples.""" + + def __init__(self, x, y): + self.x = x + self.y = y + + +class Circle: + """A circle with center and radius for pattern matching examples.""" + + def __init__(self, center, radius): + self.center = center + self.radius = radius + + +def describe_shape(shape) -> str: + """Describe shapes using pattern matching with class patterns. + + This demonstrates matching against class instances and + extracting their attributes. + """ + match shape: + case Point(x=0, y=0): + # Match a Point at the origin + return "Point at origin" + case Point(x=0, y=y): + # Match a Point on the y-axis + return f"Point on Y-axis at {y}" + case Point(x=x, y=0): + # Match a Point on the x-axis + return f"Point on X-axis at {x}" + case Point(x=x, y=y) if x == y: + # Match a Point on the diagonal line y=x + return f"Point on diagonal at ({x}, {y})" + case Point(x=x, y=y): + # Match any other Point + return f"Point at ({x}, {y})" + case Circle(center=Point(x=0, y=0), radius=r): + # Match a Circle centered at origin + return f"Circle at origin with radius {r}" + case Circle(center=Point(x=x, y=y), radius=r): + # Match any other Circle + return f"Circle at ({x}, {y}) with radius {r}" + case _: + return "Unknown shape" + + +def analyze_nested(data) -> str: + """Analyze nested structures using pattern matching.""" + match data: + case [["pair", x, y], ["pair", a, b]]: + # Match nested structure + return f"Two pairs: ({x},{y}) and ({a},{b})" + case [["single", val]]: + return f"Single value: {val}" + case _: + return "Unknown structure" + + +def check_value(val) -> str: + """Check value using OR patterns.""" + match val: + case 0 | 1 | 2: + # Match any of these values + return "small" + case 3 | 4 | 5: + return "medium" + case _: + return "large" + + +def process_range(data) -> str: + """Process range data with AS patterns.""" + match data: + case [x, y] as pair if x < y: + # Capture the entire matched value with 'as' + return f"Valid range: {pair}" + case [x, y]: + return f"Invalid range: [{x}, {y}]" + case _: + return "Not a pair" + + +def process_json_data(data) -> str: + """Process JSON-like dictionary data with pattern matching. + + This shows how to match against dictionary structures. + """ + match data: + case {"type": "user", "name": name, "age": age}: + return f"User {name} is {age} years old" + case {"type": "user", "name": name}: + # Match user without age + return f"User {name} with unknown age" + case {"type": "product", "name": name, "price": price} if price > 0: + return f"Product {name} costs ${price}" + case {"type": "product", "name": name, "price": price}: + return f"Product {name} has invalid price: {price}" + case {"type": type_name}: + # Match any dict with a type key + return f"Unknown type: {type_name}" + case _: + return "Invalid data" + + +def main() -> None: + # Test literal pattern matching + assert classify_number(0) == "zero" + assert classify_number(1) == "one" + assert classify_number(2) == "two" + assert classify_number(5) == "other" + assert classify_number(100) == "other" + + # Test HTTP status classification + assert classify_http_status(200) == "OK" + assert classify_http_status(404) == "Not Found" + assert classify_http_status(999) == "Unknown Status" + assert classify_http_status(201) == "Created" + assert classify_http_status(400) == "Bad Request" + assert classify_http_status(401) == "Unauthorized" + assert classify_http_status(500) == "Internal Server Error" + + # Test sequence pattern matching with tuples + assert process_point((0, 0)) == "Origin" + assert process_point((0, 5)) == "Y-axis at y=5" + assert process_point((3, 0)) == "X-axis at x=3" + assert process_point((4, 7)) == "Point at (4, 7)" + assert process_point("invalid") == "Not a valid 2D point" + + # Test sequence pattern matching with lists + assert analyze_sequence([]) == "Empty list" + assert analyze_sequence([42]) == "Single element: 42" + assert analyze_sequence([1, 2]) == "Pair: 1, 2" + assert analyze_sequence([1, 2, 3, 4]) == "First: 1, Rest: [2, 3, 4]" + assert analyze_sequence("not a list") == "Not a list" + + # Test pattern matching with guards + assert process_command(["quit"]) == "Quitting" + assert process_command(["go", "north"]) == "Going north" + assert process_command(["go", "west"]) == "Going west" + assert process_command(["go", "up"]) == "Invalid direction: up" + assert process_command(["take", "key"]) == "Taking key" + assert process_command(["take", "coin", 5]) == "Taking 5 coin" + assert process_command(["take", "coin", 0]) == "Invalid quantity: 0" + assert process_command(["take", "coin", -1]) == "Invalid quantity: -1" + assert process_command(["jump"]) == "Unknown command" + + # Test class pattern matching + p1 = Point(0, 0) + assert describe_shape(p1) == "Point at origin" + + p2 = Point(0, 5) + assert describe_shape(p2) == "Point on Y-axis at 5" + + p3 = Point(3, 0) + assert describe_shape(p3) == "Point on X-axis at 3" + + p4 = Point(5, 5) + assert describe_shape(p4) == "Point on diagonal at (5, 5)" + + p5 = Point(3, 7) + assert describe_shape(p5) == "Point at (3, 7)" + + c1 = Circle(Point(0, 0), 10) + assert describe_shape(c1) == "Circle at origin with radius 10" + + c2 = Circle(Point(5, 5), 3) + assert describe_shape(c2) == "Circle at (5, 5) with radius 3" + + # Test unknown shape + assert describe_shape("unknown") == "Unknown shape" + + # Test dictionary pattern matching + user1 = {"type": "user", "name": "Alice", "age": 30} + assert process_json_data(user1) == "User Alice is 30 years old" + + user2 = {"type": "user", "name": "Bob"} + assert process_json_data(user2) == "User Bob with unknown age" + + product1 = {"type": "product", "name": "Laptop", "price": 999} + assert process_json_data(product1) == "Product Laptop costs $999" + + product2 = {"type": "product", "name": "Free Sample", "price": 0} + assert process_json_data(product2) == "Product Free Sample has invalid price: 0" + + unknown = {"type": "order"} + assert process_json_data(unknown) == "Unknown type: order" + + invalid = {"data": "something"} + assert process_json_data(invalid) == "Invalid data" + + # Pattern matching with OR patterns + assert check_value(0) == "small" + assert check_value(2) == "small" + assert check_value(3) == "medium" + assert check_value(10) == "large" + + # Pattern matching with AS patterns (walrus-like capture) + assert process_range([1, 5]) == "Valid range: [1, 5]" + assert process_range([5, 1]) == "Invalid range: [5, 1]" + assert process_range("not a pair") == "Not a pair" + + # Nested pattern matching + assert analyze_nested([["pair", 1, 2], ["pair", 3, 4]]) == "Two pairs: (1,2) and (3,4)" + assert analyze_nested([["single", 42]]) == "Single value: 42" + assert analyze_nested("invalid") == "Unknown structure" + + # Pattern matching is particularly useful for parsing and handling + # structured data like API responses, configuration files, or + # abstract syntax trees in compilers/interpreters + + +if __name__ == "__main__": + main() diff --git a/ultimatepython/advanced/regex.py b/ultimatepython/advanced/regex.py index 28584c3c..365ad861 100644 --- a/ultimatepython/advanced/regex.py +++ b/ultimatepython/advanced/regex.py @@ -4,6 +4,7 @@ This module shows a few examples of how to use the `re` package to search predefined text snippets stored in module-level constants. """ + import re # Module-level constants diff --git a/ultimatepython/advanced/thread.py b/ultimatepython/advanced/thread.py index c4352b66..61522e79 100644 --- a/ultimatepython/advanced/thread.py +++ b/ultimatepython/advanced/thread.py @@ -20,21 +20,23 @@ https://realpython.com/python-gil/ https://wiki.python.org/moin/GlobalInterpreterLock """ + import time from concurrent.futures import ThreadPoolExecutor, as_completed from datetime import datetime +from typing import Callable, Iterable # Module-level constants _MULTIPLY_DELAY = 0.01 # delay is long enough for threads to be faster -def multiply_by_two(item): +def multiply_by_two(item: int) -> int: """This multiplication has a small delay.""" time.sleep(_MULTIPLY_DELAY) return item * 2 -def run_thread_workers(work, data): +def run_thread_workers(work: Callable[[int], int], data: Iterable[int]) -> set[int]: """Run thread workers that invoke work on each data element. The inspiration for this function comes directly from an example @@ -42,7 +44,7 @@ def run_thread_workers(work, data): https://docs.python.org/3/library/concurrent.futures.html """ - results = set() + results: set[int] = set() # We can use a with statement to ensure workers are cleaned up promptly with ThreadPoolExecutor() as executor: @@ -54,7 +56,7 @@ def run_thread_workers(work, data): return results -def main(): +def main() -> None: original_data = {num for num in range(5)} expected_data = {(item * 2) for item in original_data} diff --git a/ultimatepython/advanced/weak_ref.py b/ultimatepython/advanced/weak_ref.py index b5bffedb..689969bb 100644 --- a/ultimatepython/advanced/weak_ref.py +++ b/ultimatepython/advanced/weak_ref.py @@ -4,6 +4,7 @@ up-to-date as it explicitly sets up and implicitly tears down servers as the program enters and leaves a function scope. """ + import weakref from uuid import uuid4 @@ -52,7 +53,7 @@ def setup_and_teardown_servers(registry): """Explicitly setup and implicitly teardown servers.""" app_servers = {} - # Let's create all of the servers and store them properly + # Let's create all the servers and store them properly for app in _CLOUD_APPS: app_servers[app] = set() for component in _CLOUD_APP_COMPONENTS: @@ -67,18 +68,16 @@ def setup_and_teardown_servers(registry): assert ( registry.server_count == len(_CLOUD_APPS) * len(_CLOUD_APP_COMPONENTS) - == len([(app, server) - for app, servers in app_servers.items() - for server in servers]) + == len([(app, server) for app, servers in app_servers.items() for server in servers]) ) - # What's really interesting is that servers go away when we leave the + # What's fascinating is that servers go away when we leave the # scope of this function. In this function, each server is created and # strongly referenced by the `app_servers` variable. When we leave this # function, the `app_servers` variable no longer exists which brings # the reference count for each server from 1 to 0. A reference count of # 0 for each server triggers the garbage collector to run the cleanup - # process for all of the servers in this function scope + # process for all the servers in this function scope def main(): diff --git a/ultimatepython/classes/abstract_class.py b/ultimatepython/classes/abstract_class.py index 7da2b364..eef63d2e 100644 --- a/ultimatepython/classes/abstract_class.py +++ b/ultimatepython/classes/abstract_class.py @@ -9,6 +9,7 @@ https://www.python.org/dev/peps/pep-3119/ """ + from abc import ABC, abstractmethod @@ -19,20 +20,20 @@ class Employee(ABC): can work and relax is different from another type of employee. """ - def __init__(self, name, title): + def __init__(self, name: str, title: str) -> None: self.name = name self.title = title - def __str__(self): + def __str__(self) -> str: return self.name @abstractmethod - def do_work(self): + def do_work(self) -> str: """Do something for work.""" raise NotImplementedError @abstractmethod - def do_relax(self): + def do_relax(self) -> str: """Do something to relax.""" raise NotImplementedError @@ -48,14 +49,14 @@ class Engineer(Employee): is something that a manager prefers not to do. """ - def __init__(self, name, title, skill): + def __init__(self, name: str, title: str, skill: str) -> None: super().__init__(name, title) self.skill = skill - def do_work(self): + def do_work(self) -> str: return f"{self} is coding in {self.skill}" - def do_relax(self): + def do_relax(self) -> str: return f"{self} is watching YouTube" def do_refactor(self): @@ -72,22 +73,22 @@ class is concrete. Notice that a manager has direct reports and engineer. """ - def __init__(self, name, title, direct_reports): + def __init__(self, name: str, title: str, direct_reports: list) -> None: super().__init__(name, title) self.direct_reports = direct_reports - def do_work(self): + def do_work(self) -> str: return f"{self} is meeting up with {len(self.direct_reports)} reports" - def do_relax(self): + def do_relax(self) -> str: return f"{self} is taking a trip to the Bahamas" - def do_hire(self): + def do_hire(self) -> str: """Do the hard work of hiring employees, unlike engineers.""" return f"{self} is hiring employees" -def main(): +def main() -> None: # Declare two engineers engineer_john = Engineer("John Doe", "Software Engineer", "Android") engineer_jane = Engineer("Jane Doe", "Software Engineer", "iOS") diff --git a/ultimatepython/classes/basic_class.py b/ultimatepython/classes/basic_class.py index c28521e1..9c9216e4 100644 --- a/ultimatepython/classes/basic_class.py +++ b/ultimatepython/classes/basic_class.py @@ -3,6 +3,7 @@ combined as one logical entity. This module defines a basic car class, creates a car instance and uses it for demonstration purposes. """ + from inspect import isfunction, ismethod, signature @@ -14,27 +15,27 @@ class Car: class definition. """ - def __init__(self, make, model, year, miles): + def __init__(self, make: str, model: str, year: int, miles: float) -> None: """Constructor logic.""" self.make = make self.model = model self.year = year self.miles = miles - def __repr__(self): + def __repr__(self) -> str: """Formal representation for developers.""" return f"" - def __str__(self): + def __str__(self) -> str: """Informal representation for users.""" return f"{self.make} {self.model} ({self.year})" - def drive(self, rate_in_mph): + def drive(self, rate_in_mph: int) -> str: """Drive car at a certain rate in MPH.""" return f"{self} is driving at {rate_in_mph} MPH" -def main(): +def main() -> None: # Create a car with the provided class constructor car = Car("Bumble", "Bee", 2000, 200000.0) diff --git a/ultimatepython/classes/encapsulation.py b/ultimatepython/classes/encapsulation.py new file mode 100644 index 00000000..568738e3 --- /dev/null +++ b/ultimatepython/classes/encapsulation.py @@ -0,0 +1,131 @@ +""" +Encapsulation is a feature of OOP that allows you to hide the +implementation details of a class from its users. +Encapsulation allows us to limit the access of certain attributes +within a class. This prevents users from directly accessing and modifying such +attributes from outside the class. Instead, users must use methods to access and +modify attributes. +""" + +import secrets + +# Module-level constant +_INVALID_AMOUNT_MESSAGE = "Invalid amount." +_INSUFFICIENT_BALANCE_MESSAGE = "Insufficient balance." + + +class BankAccount: + def __init__(self, account_holder_name: str) -> None: + """ + In Python, a class attribute can be made private by prefixing it with two underscores. + This makes it inaccessible to users outside the class. + By default, class attributes are public. Therefore, they can be accessed and modified + outside the class. + + Here, account_number and balance are private while account_holder_name is public. + """ + self.account_holder_name = account_holder_name + """ + The account number is generated automatically using the randbelow function from + the random module when a new instance of the class is created. + The balance is set to 0 by default. + """ + self.__account_number = secrets.randbelow(10**10) # generate a random account number of 10 digits. + self.__balance = 0 + + def deposit(self, balance: int) -> None: + """ + The deposit function is used to add new balance to the account. + The provided balance is added to the existing balance. + """ + self.__balance += int(balance) + + def withdraw(self, balance: int) -> None: + """ + The withdrawal method is used to deduct the balance from the account. + In case there is insufficient balance, or the input is invalid, + a value error is raised. + """ + if balance <= 0: + raise ValueError(_INVALID_AMOUNT_MESSAGE) + if balance > self.__balance: + raise ValueError(_INSUFFICIENT_BALANCE_MESSAGE) + + self.__balance -= balance + + def get_balance(self) -> int: + """ + This function returns the available balance in the account. + """ + return self.__balance + + def get_account_number(self) -> int: + """ + The account number is generated randomly when a new instance of the class is created. + Since the attribute is also private, it cannot be accessed directly from outside the class. + The get_account_number method allows you to access the account number outside the class. + But since we do not define a setter method for this variable, we cannot modify it outside the class. + Therefore, the account number generated while creating an object of the BankAccount class cannot be changed + but can only be read using this function. + """ + return self.__account_number + + def __set_account_number(self, number: int) -> None: + """ + This is a private method. Similar to private variables, + private methods also cannot be accessed outside the class. + """ + self.__account_number = number + + def remove_account_details(self) -> None: + """ + This method is used to reset the account details. + Here, the __set_account_number function is private. + This, it cannot be called from outside the class. + However, the remove_account_details calls the function from + inside the class and as it is a public method, it can be called from + outside the class. + """ + self.__balance = 0 + self.__set_account_number(0) + self.account_holder_name = "" + + +def main() -> None: + # Account names constants. + user1 = "John Doe" + user2 = "Jane Doe" + + # Account instances. + account1 = BankAccount(user1) + account2 = BankAccount(user2) + + assert account1.account_holder_name == user1 + assert account2.account_holder_name == user2 + + # Deposit amount and check if the balance is updated. + account1.deposit(100) + assert account1.get_balance() == 100 + + # Withdraw amount and check if the balance is updated. + account1.withdraw(50) + assert account1.get_balance() == 50 + + # validating invalid amounts. + error_inputs = [-10, 0, 150] + for input in error_inputs: + try: + account1.withdraw(input) + except ValueError as e: + assert str(e) in {_INSUFFICIENT_BALANCE_MESSAGE, _INVALID_AMOUNT_MESSAGE} + + # Remove account details and assert values. + account1.remove_account_details() + + assert account1.get_balance() == 0 + assert account1.get_account_number() == 0 + assert account1.account_holder_name == "" + + +if __name__ == "__main__": + main() diff --git a/ultimatepython/classes/exception_class.py b/ultimatepython/classes/exception_class.py index b70ad2b7..560926d7 100644 --- a/ultimatepython/classes/exception_class.py +++ b/ultimatepython/classes/exception_class.py @@ -39,7 +39,7 @@ class DivisionError(CustomError): """ -def divide_positive_numbers(dividend, divisor): +def divide_positive_numbers(dividend: int, divisor: int) -> int: """Divide a positive number by another positive number. Writing a program in this style is considered defensive programming. @@ -54,7 +54,7 @@ def divide_positive_numbers(dividend, divisor): return dividend // divisor -def main(): +def main() -> None: # Exception classes are no different from concrete classes in that # they all have inheritance baked in assert issubclass(DivisionError, CustomError) diff --git a/ultimatepython/classes/inheritance.py b/ultimatepython/classes/inheritance.py new file mode 100644 index 00000000..166d40a9 --- /dev/null +++ b/ultimatepython/classes/inheritance.py @@ -0,0 +1,141 @@ +""" +Inheritance is a way to reuse code and data from a parent class. This +allows us to avoid repeating ourselves and to build upon existing +functionality. This module defines a basic vehicle class, creates a car +class that inherits from vehicle, then creates a truck class that +inherits from car and use it for demonstration purposes. +""" + +from inspect import isfunction, ismethod + + +class Vehicle: + """Basic definition of a vehicle. + + We begin with a simple mental model of what a vehicle is. It has + a make, model, year, and miles. That way, we can start exploring + the core concepts that are associated with a class definition. + """ + + def __init__(self, make: str, model: str, year: int, miles: float) -> None: + """Construct a vehicle with make, model, year, and miles.""" + self.make = make + self.model = model + self.year = year + self.miles = miles + + def __repr__(self) -> str: + """Return the formal representation of a vehicle.""" + return f"" + + def __str__(self) -> str: + """Return the informal representation of a vehicle.""" + return f"{self.make} {self.model} ({self.year})" + + def drive(self, rate_in_mph: int) -> str: + """Drive a vehicle at a certain rate in MPH.""" + return f"{self} is driving at {rate_in_mph} MPH" + + +class Car(Vehicle): + """Definition of a car. + + We inherit from the vehicle class to reuse the code and data that + we have already defined. In addition, we add a new attribute called + `wheels` to the car class. This is an example of extending the + functionality of a parent class. In __init__, we call the parent + constructor with the `super` function. This is a way to invoke the + parent constructor without having to explicitly name the parent + class. We also override the method `__repr__` to have a different + output than the vehicle. + """ + + def __init__(self, make: str, model: str, year: int, miles: float) -> None: + """Construct a car with make, model, year, miles, and wheels.""" + super().__init__(make, model, year, miles) + self.wheels = 4 + + def __repr__(self) -> str: + """Return the formal representation of a car.""" + return f"" + + +class Truck(Vehicle): + """Definition of a truck. + + We inherit from vehicle just like we did with the car class. In this case we + will also override the method `drive` to have a different output than the + car and the vehicle. + """ + + def __init__(self, make: str, model: str, year: int, miles: float) -> None: + """Construct a truck with make, model, year, miles, and wheels.""" + super().__init__(make, model, year, miles) + self.wheels = 6 + + def __repr__(self) -> str: + """Return the formal representation of a truck.""" + return f"" + + def drive(self, rate_in_mph: int) -> str: + """Drive a truck at a certain rate in MPH.""" + return f"{self} is driving a truck at {rate_in_mph} MPH" + + +def main() -> None: + # Create a vehicle with the provided class constructor + vehicle = Vehicle("Mistery Machine", "Van", 1969, 100000.0) + + # Formal representation + assert repr(vehicle) == "" + + # Informal representation + assert str(vehicle) == "Mistery Machine Van (1969)" + + # Call a method on the class constructor + assert vehicle.drive(50) == "Mistery Machine Van (1969) is driving at 50 MPH" + + # Check the type of the method drive + assert ismethod(vehicle.drive) and not isfunction(vehicle.drive) + + # Now we create a car with the provided class constructor + car = Car("DeLorean", "DMC-12", 1982, 220000.0) + + # The informal representation is similar to the vehicle + assert str(car) == "DeLorean DMC-12 (1982)" + + # But the formal representation is different because we included + # the wheels attribute + assert repr(car) == "" + + # And we can check the type of the method drive like we did with + # the vehicle + assert ismethod(car.drive) and not isfunction(car.drive) + + # If we call the method drive, we can see that we did not + # write any code for the car class, but we can still use it + # because it is inherited from the vehicle class and the + # behavior is the same as the vehicle + assert car.drive(50) == "DeLorean DMC-12 (1982) is driving at 50 MPH" + + # Now we create a truck with the provided class constructor + truck = Truck("Optimus Prime", "Truck", 1984, 1000000.0) + + # Like car and vehicle, the informal representation is similar + assert str(truck) == "Optimus Prime Truck (1984)" + + # And the formal representation is different from the vehicle + # because we included the wheels attribute + assert repr(truck) == "" + + # And we can check the type of the method drive like we did with + # the vehicle + assert ismethod(truck.drive) and not isfunction(truck.drive) + + # For the last part, we can see that the method drive is different + # for the truck + assert truck.drive(50) == "Optimus Prime Truck (1984) is driving a truck at 50 MPH" + + +if __name__ == "__main__": + main() diff --git a/ultimatepython/classes/iterator_class.py b/ultimatepython/classes/iterator_class.py index 64c84101..9ee96e0d 100644 --- a/ultimatepython/classes/iterator_class.py +++ b/ultimatepython/classes/iterator_class.py @@ -32,7 +32,7 @@ class Employee: https://en.wikipedia.org/wiki/Design_Patterns """ - def __init__(self, name, title, direct_reports): + def __init__(self, name: str, title: str, direct_reports: list) -> None: self.name = name self.title = title self.direct_reports = direct_reports @@ -65,21 +65,21 @@ class EmployeeIterator: https://en.wikipedia.org/wiki/Iterator_pattern """ - def __init__(self, employee): + def __init__(self, employee: Employee) -> None: """Constructor logic.""" self.employees_to_visit = [employee] - self.employees_visited = set() + self.employees_visited: set[str] = set() - def __iter__(self): + def __iter__(self) -> "EmployeeIterator": """Iterator is self by convention.""" return self - def __next__(self): + def __next__(self) -> Employee: """Return the next employee available. The logic may seem complex, but it's actually a common algorithm used in traversing a relationship graph. It is called depth-first - search and it can be found on Wikipedia: + search, and it can be found on Wikipedia: https://en.wikipedia.org/wiki/Depth-first_search """ @@ -94,7 +94,7 @@ def __next__(self): return employee -def employee_generator(top_employee): +def employee_generator(top_employee: Employee): """Employee generator. It is essentially the same logic as above except constructed as a @@ -126,12 +126,9 @@ def employee_generator(top_employee): yield employee -def main(): +def main() -> None: # Manager with two direct reports - manager = Employee("Max Doe", "Engineering Manager", [ - Employee("John Doe", "Software Engineer", []), - Employee("Jane Doe", "Software Engineer", []) - ]) + manager = Employee("Max Doe", "Engineering Manager", [Employee("John Doe", "Software Engineer", []), Employee("Jane Doe", "Software Engineer", [])]) # We should provide the same three employees in the same order regardless # of whether we use the iterator class or the generator function diff --git a/ultimatepython/data_structures/comprehension.py b/ultimatepython/data_structures/comprehension.py index d533c838..daae75ff 100644 --- a/ultimatepython/data_structures/comprehension.py +++ b/ultimatepython/data_structures/comprehension.py @@ -4,13 +4,13 @@ """ -def main(): +def main() -> None: # One interesting fact about data structures is that we can build # them with comprehensions. Let's explain how the first one works: # we just want to create zeros so our expression is set to `0` # since no computing is required; because `0` is a constant value, # we can set the item that we compute with to `_`; and we want to - # create five zeros so we set the iterator as `range(5)` + # create five zeros, so we set the iterator as `range(5)` assert [0 for _ in range(5)] == [0] * 5 == [0, 0, 0, 0, 0] # For the next comprehension operations, let's see what we can do @@ -29,10 +29,7 @@ def main(): # Dictionary comprehension can map each word to its length dict_comp = {word: len(word) for word in words} assert len(dict_comp) == len(words) - assert dict_comp == {"cat": 3, - "mice": 4, - "horse": 5, - "bat": 3} + assert dict_comp == {"cat": 3, "mice": 4, "horse": 5, "bat": 3} # Comprehensions can also be used with inline conditionals to # get filtered values from the original list. In this example, diff --git a/ultimatepython/data_structures/defaultdict.py b/ultimatepython/data_structures/defaultdict.py new file mode 100644 index 00000000..944d5387 --- /dev/null +++ b/ultimatepython/data_structures/defaultdict.py @@ -0,0 +1,57 @@ +""" +This module demonstrates the use of defaultdict, which is a dictionary that is +possible to set up a default value in its creation. +""" + +from collections import defaultdict + +# Module-level constants +_GPA_MIN = 0.0 +_GPA_MAX = 4.0 +_EPS = 0.000001 + + +def main() -> None: + # Let's create a defaultdict with student keys and GPA values. The first + # parameter is called default_factory, and it is the initialization value for + # first use of a key. It can be a common type or a function + student_gpa = defaultdict(float, [("john", 3.5), ("bob", 2.8), ("mary", 3.2)]) + + # There are three student records in this dictionary + assert len(student_gpa) == 3 + + # Each student has a name key and a GPA value + assert len(student_gpa.keys()) == len(student_gpa.values()) + + # We can get the names in isolation. Note that in Python 3.7 and + # above, dictionary entries are sorted in the order that they were + # defined or inserted + student_names = [] + for student in student_gpa.keys(): + student_names.append(student) + assert student_names == ["john", "bob", "mary"] + + # We can get the GPA for a specific student + assert abs(student_gpa["john"] < 3.5) < _EPS + + # And the defaultdict allow us to get the GPA of a student that is not in + # the data structure yet, returning a default value for float that is 0.0 + assert student_gpa["jane"] == _GPA_MIN + + # And now there are four student records in this dictionary + assert len(student_gpa) == 4 + + # You can set the default value in default_factory attribute + def set_default_to_gpa_max(): + return _GPA_MAX + + student_gpa.default_factory = set_default_to_gpa_max + + assert student_gpa["rika"] == _GPA_MAX + + # And now there are five student records in this dictionary + assert len(student_gpa) == 5 + + +if __name__ == "__main__": + main() diff --git a/ultimatepython/data_structures/deque.py b/ultimatepython/data_structures/deque.py index a5016654..e1a8abf4 100644 --- a/ultimatepython/data_structures/deque.py +++ b/ultimatepython/data_structures/deque.py @@ -1,13 +1,14 @@ """ -A deque is similar to all of the other sequential data structures but +A deque is similar to all the other sequential data structures but has some implementation details that are different from other sequences like a list. This module highlights those differences and shows how a deque can be used as a LIFO stack and a FIFO queue. """ + from collections import deque -def main(): +def main() -> None: # A list is identical to a vector where a new array is created when # there are too many elements in the old array, and the old array # elements are moved over to the new array one-by-one. The time @@ -19,7 +20,7 @@ def main(): # Check out the source code for a list and a deque here: # https://github.com/python/cpython/blob/3.8/Objects/listobject.c # https://github.com/python/cpython/blob/3.8/Modules/_collectionsmodule.c - dq = deque() + dq: deque[int] = deque() for i in range(1, 5): # Similar to adding a new node to the right of the linked list diff --git a/ultimatepython/data_structures/dict.py b/ultimatepython/data_structures/dict.py index 34855400..5ce62ac2 100644 --- a/ultimatepython/data_structures/dict.py +++ b/ultimatepython/data_structures/dict.py @@ -4,17 +4,16 @@ structure. """ +import math + # Module-level constants _GPA_MIN = 0.0 _GPA_MAX = 4.0 -def main(): +def main() -> None: # Let's create a dictionary with student keys and GPA values - student_gpa = {"john": 3.5, - "jane": _GPA_MAX, - "bob": 2.8, - "mary": 3.2} + student_gpa = {"john": 3.5, "jane": _GPA_MAX, "bob": 2.8, "mary": 3.2} # There are four student records in this dictionary assert len(student_gpa) == 4 @@ -42,7 +41,7 @@ def main(): assert gpa_values == [3.5, _GPA_MAX, 2.8, 3.2] # We can get the GPA for a specific student - assert student_gpa["john"] == 3.5 + assert math.isclose(student_gpa["john"], 3.5) # If the key does not always exist inside a dictionary, we # can check for its existence by using `in` diff --git a/ultimatepython/data_structures/dict_union.py b/ultimatepython/data_structures/dict_union.py new file mode 100644 index 00000000..5f52c59b --- /dev/null +++ b/ultimatepython/data_structures/dict_union.py @@ -0,0 +1,174 @@ +""" +Dictionary union operators allow you to merge dictionaries using +the | (union) and |= (in-place union) operators. These operators +provide a clean and intuitive syntax for combining dictionaries. + +This feature was introduced in Python 3.9 through PEP 584. Before +this, you had to use methods like dict.update() or {**dict1, **dict2} +syntax to merge dictionaries. +""" + + +def main() -> None: + # Traditional dictionary merging before Python 3.9 + # Method 1: Using dict.update() (modifies the original) + dict1_old = {"a": 1, "b": 2} + dict2_old = {"c": 3, "d": 4} + dict1_old.update(dict2_old) + assert dict1_old == {"a": 1, "b": 2, "c": 3, "d": 4} + + # Method 2: Using dictionary unpacking (creates a new dict) + dict3_old = {"a": 1, "b": 2} + dict4_old = {"c": 3, "d": 4} + merged_old = {**dict3_old, **dict4_old} + assert merged_old == {"a": 1, "b": 2, "c": 3, "d": 4} + + # With Python 3.9+, we can use the | operator for union + # This creates a new dictionary without modifying the originals + dict1 = {"a": 1, "b": 2} + dict2 = {"c": 3, "d": 4} + merged = dict1 | dict2 + assert merged == {"a": 1, "b": 2, "c": 3, "d": 4} + + # The original dictionaries remain unchanged + assert dict1 == {"a": 1, "b": 2} + assert dict2 == {"c": 3, "d": 4} + + # When there are overlapping keys, the right operand's values take precedence + # This is the same behavior as dict.update() and {**d1, **d2} + dict3 = {"a": 1, "b": 2, "c": 3} + dict4 = {"b": 20, "c": 30, "d": 4} + merged2 = dict3 | dict4 + # Keys 'b' and 'c' from dict4 override those from dict3 + assert merged2 == {"a": 1, "b": 20, "c": 30, "d": 4} + + # The order matters! Left operand is the base, right operand overwrites + merged3 = dict4 | dict3 + # Now keys 'b' and 'c' from dict3 override those from dict4 + assert merged3 == {"b": 2, "c": 3, "d": 4, "a": 1} + + # The |= operator performs in-place union (augmented assignment) + # This is equivalent to dict.update() but with cleaner syntax + dict5 = {"a": 1, "b": 2} + dict6 = {"c": 3, "d": 4} + dict5 |= dict6 + # dict5 is modified in place + assert dict5 == {"a": 1, "b": 2, "c": 3, "d": 4} + # dict6 remains unchanged + assert dict6 == {"c": 3, "d": 4} + + # The |= operator also handles overlapping keys + dict7 = {"a": 1, "b": 2, "c": 3} + dict8 = {"b": 20, "d": 4} + dict7 |= dict8 + # 'b' from dict8 overwrites 'b' in dict7 + assert dict7 == {"a": 1, "b": 20, "c": 3, "d": 4} + + # You can chain multiple | operations + dict9 = {"a": 1} + dict10 = {"b": 2} + dict11 = {"c": 3} + dict12 = {"d": 4} + combined = dict9 | dict10 | dict11 | dict12 + assert combined == {"a": 1, "b": 2, "c": 3, "d": 4} + + # When chaining with overlapping keys, rightmost values win + dict13 = {"a": 1, "x": 10} + dict14 = {"b": 2, "x": 20} + dict15 = {"c": 3, "x": 30} + combined2 = dict13 | dict14 | dict15 + # 'x' ends up with value 30 from the rightmost dictionary + assert combined2 == {"a": 1, "b": 2, "c": 3, "x": 30} + + # The union operator works with empty dictionaries + empty: dict[str, int] = {} + dict16 = {"a": 1, "b": 2} + assert empty | dict16 == {"a": 1, "b": 2} + assert dict16 | empty == {"a": 1, "b": 2} + assert empty | empty == {} + + # The union operator can be used with dict() constructor results + dict17 = dict(a=1, b=2) + dict18 = dict(c=3, d=4) + merged4 = dict17 | dict18 + assert merged4 == {"a": 1, "b": 2, "c": 3, "d": 4} + + # You can mix different value types in merged dictionaries + dict19 = {"name": "Alice", "age": 30} + dict20 = {"city": "NYC", "scores": [85, 90, 95]} + dict21 = {"active": True} + person = dict19 | dict20 | dict21 + assert person == {"name": "Alice", "age": 30, "city": "NYC", "scores": [85, 90, 95], "active": True} + + # Practical use case: Configuration merging + # Start with default configuration + default_config = {"timeout": 30, "retries": 3, "debug": False, "log_level": "INFO"} + + # User provides custom configuration (partial) + user_config = {"timeout": 60, "debug": True} + + # Merge configurations, user settings override defaults + final_config = default_config | user_config + assert final_config == { + "timeout": 60, # Overridden by user + "retries": 3, # From default + "debug": True, # Overridden by user + "log_level": "INFO", # From default + } + + # Practical use case: Building objects incrementally + # Start with base attributes + base = {"id": 1, "type": "user"} + + # Add authentication info + with_auth = base | {"username": "john", "email": "john@example.com"} + + # Add profile info + with_profile = with_auth | {"bio": "Developer", "location": "USA"} + + assert with_profile == {"id": 1, "type": "user", "username": "john", "email": "john@example.com", "bio": "Developer", "location": "USA"} + + # Practical use case: Updating records with |= + user_record = {"id": 100, "name": "Jane", "status": "active", "login_count": 5} + + # Apply update from an external source + update = {"status": "inactive", "login_count": 6, "last_login": "2024-01-15"} + user_record |= update + + assert user_record == {"id": 100, "name": "Jane", "status": "inactive", "login_count": 6, "last_login": "2024-01-15"} + + # The union operators only work with dictionaries + # Attempting to use them with non-dict types raises TypeError + dict22 = {"a": 1} + error_raised = False + try: + # This will fail because list is not a dict + dict22 | [("b", 2)] # type: ignore [operator] + except TypeError: + error_raised = True + assert error_raised is True + + # However, you can use dict() to convert compatible types first + dict23 = {"a": 1} + dict24 = dict([("b", 2), ("c", 3)]) # Convert list of tuples to dict + merged5 = dict23 | dict24 + assert merged5 == {"a": 1, "b": 2, "c": 3} + + # Comparison with the older approaches shows the clarity improvement: + + # OLD: Using update() - modifies original, no expression result + old1 = {"a": 1} + old1.update({"b": 2}) + assert old1 == {"a": 1, "b": 2} + + # OLD: Using unpacking - verbose for multiple merges + old2 = {**{"a": 1}, **{"b": 2}, **{"c": 3}} + assert old2 == {"a": 1, "b": 2, "c": 3} + + # NEW: Using union operator - clean and chainable + new1 = {"a": 1} | {"b": 2} | {"c": 3} + assert new1 == {"a": 1, "b": 2, "c": 3} + + +if __name__ == "__main__": + main() diff --git a/ultimatepython/data_structures/heap.py b/ultimatepython/data_structures/heap.py new file mode 100644 index 00000000..b6c83259 --- /dev/null +++ b/ultimatepython/data_structures/heap.py @@ -0,0 +1,62 @@ +import heapq + + +def main() -> None: + # Define the list of numbers + nums = [3, 1, 4, 1, 5] + + # Creating a min-heap + min_heap: list[int] = [] + for num in nums: + heapq.heappush(min_heap, num) + assert min_heap[0] == 1 # The root of the heap is the smallest element + + # Pop the smallest element + smallest = heapq.heappop(min_heap) + assert smallest == 1 + + # Adding a new element + heapq.heappush(min_heap, 5) + assert min_heap[0] == 1 # The root remains the smallest element + + # Creating a max-heap + max_heap: list[int] = [] + for num in nums: + heapq.heappush(max_heap, -num) # Negate numbers for a max-heap + assert -max_heap[0] == 5 # The root of the heap is the largest element + + # Pop the largest element + largest = -heapq.heappop(max_heap) + assert largest == 5 + + # Converting a list to a heap in-place + data = [3, 1, 4, 1, 5] + heapq.heapify(data) + assert data[0] == 1 # The root is the smallest element + + # Extending a heap + more_data = [2, 6, 5] + for item in more_data: + heapq.heappush(data, item) + assert data[0] == 1 # The root is still the smallest element + + # Using heap for sorting + sorted_data = [heapq.heappop(data) for _ in range(len(data))] + assert sorted_data == [1, 1, 2, 3, 4, 5, 5, 6] + + # Getting the n smallest or largest elements from a list + n_smallest = heapq.nsmallest(3, nums) # Get the 3 smallest elements + assert n_smallest == [1, 1, 3] + + n_largest = heapq.nlargest(3, nums) # Get the 3 largest elements + assert n_largest == [5, 4, 3] + + # Merging multiple sorted lists into a single sorted list using a heap + list1 = [1, 3, 5, 7] + list2 = [2, 4, 6, 8] + merged_list = list(heapq.merge(list1, list2)) + assert merged_list == [1, 2, 3, 4, 5, 6, 7, 8] + + +if __name__ == "__main__": + main() diff --git a/ultimatepython/data_structures/itertools.py b/ultimatepython/data_structures/itertools.py new file mode 100644 index 00000000..77ea8de7 --- /dev/null +++ b/ultimatepython/data_structures/itertools.py @@ -0,0 +1,68 @@ +""" +Itertools provides a collection of tools for handling iterators. This +module demonstrates how to use itertools functions to efficiently work +with sequences, combine iterables, and create infinite iterators. +""" + +import itertools + + +def main() -> None: + # chain() combines multiple iterables into a single iterator + letters = ["a", "b", "c"] + numbers = [1, 2, 3] + combined = list(itertools.chain(letters, numbers)) + assert combined == ["a", "b", "c", 1, 2, 3] + + # cycle() creates an infinite iterator that cycles through the elements + # We'll use islice to take only the first few elements + cycled = list(itertools.islice(itertools.cycle(["A", "B"]), 6)) + assert cycled == ["A", "B", "A", "B", "A", "B"] + + # repeat() creates an iterator that repeats a value infinitely + repeated = list(itertools.islice(itertools.repeat("hello"), 4)) + assert repeated == ["hello", "hello", "hello", "hello"] + + # count() creates an infinite iterator that counts up from a start value + counted = list(itertools.islice(itertools.count(10), 5)) + assert counted == [10, 11, 12, 13, 14] + + # islice() allows slicing of iterators (similar to list slicing) + data = itertools.count() # infinite count from 0 + sliced = list(itertools.islice(data, 2, 8, 2)) # start=2, stop=8, step=2 + assert sliced == [2, 4, 6] + + # tee() creates multiple independent iterators from one + original = iter([1, 2, 3, 4, 5]) + iter1, iter2 = itertools.tee(original, 2) + list1 = list(iter1) + list2 = list(iter2) + assert list1 == [1, 2, 3, 4, 5] + assert list2 == [1, 2, 3, 4, 5] + + # groupby() groups consecutive equal elements + group_data = [1, 1, 2, 2, 2, 3, 1, 1] + groups = [(key, list(group)) for key, group in itertools.groupby(group_data)] + assert groups == [(1, [1, 1]), (2, [2, 2, 2]), (3, [3]), (1, [1, 1])] + + # product() creates cartesian product of input iterables + colors = ["red", "blue"] + sizes = ["S", "M"] + combinations = list(itertools.product(colors, sizes)) + assert combinations == [("red", "S"), ("red", "M"), ("blue", "S"), ("blue", "M")] + + # permutations() generates all possible orderings + perms = list(itertools.permutations([1, 2, 3], 2)) # length 2 permutations + assert len(perms) == 6 # 3! / (3-2)! = 6 + assert (1, 2) in perms + assert (2, 1) in perms + + # combinations() generates combinations (order doesn't matter) + combos = list(itertools.combinations([1, 2, 3, 4], 2)) + assert len(combos) == 6 # C(4,2) = 6 + assert (1, 2) in combos + assert (2, 1) not in combos # order doesn't matter + + +if __name__ == "__main__": + main() diff --git a/ultimatepython/data_structures/list.py b/ultimatepython/data_structures/list.py index 608f1519..54245da4 100644 --- a/ultimatepython/data_structures/list.py +++ b/ultimatepython/data_structures/list.py @@ -5,7 +5,7 @@ """ -def main(): +def main() -> None: # This is a list of strings where # "a" is a string at index 0 and # "e" is a string at index 4 @@ -79,7 +79,7 @@ def main(): assert len(matrix) == len(row) # Notice that lists have variable length and can be modified to have - # more elements. Lists can also be modified to have less elements + # more elements. Lists can also be modified to have fewer elements lengthy = [] for i in range(5): lengthy.append(i) # add 0..4 to the back @@ -87,6 +87,18 @@ def main(): lengthy.pop() # pop out the 4 from the back assert lengthy == [0, 1, 2, 3] + # Let's sort this list in ascending order + numbers = [5, 4, 3, 2, 1] + numbers.sort() + assert numbers == [1, 2, 3, 4, 5] + + # Let's check if these lists are empty + assert len(numbers) == 5 + empty_list: list[object] = [] + assert len(empty_list) == 0 + assert not empty_list + assert len([None]) == 1 + if __name__ == "__main__": main() diff --git a/ultimatepython/data_structures/namedtuple.py b/ultimatepython/data_structures/namedtuple.py new file mode 100644 index 00000000..dec56c8a --- /dev/null +++ b/ultimatepython/data_structures/namedtuple.py @@ -0,0 +1,71 @@ +""" +This module demonstrates the use of named tuples, which are a data structure +with named fields, similar to a class but lightweight and immutable. Named +tuples are created using the namedtuple function from the collections module. +""" + +from collections import namedtuple + + +def main() -> None: + # Named Tuple Attributes: + # - namedtuple: Callable from collections to define a named tuple + # - Point: A named tuple type with fields "x" and "y" + Point = namedtuple("Point", ["x", "y"]) # type: Any + + # Named Tuple Fields: + # - x and y: Fields of the named tuple Point representing coordinates + # - point1 and point2: Instances of the Point named tuple + point1 = Point(x=1, y=2) + point2 = Point(x=3, y=4) + assert isinstance(point1, Point) is True + assert isinstance(point2, Point) is True + + # Named Tuple Operations: + # - Accessing fields using dot notation + # - Named tuples are immutable + # - Named tuples support tuple operations + # - Converting named tuples to dictionaries and vice versa + # - Additional methods and attributes + assert point1.x == 1 + assert point1.y == 2 + assert point2.x == 3 + assert point2.y == 4 + + # Attempt to change the "x" field of point1 (raises an error) + access_immutable_error = False + try: + # Direct assignment to a namedtuple field is not allowed (immutable). + # Use setattr to demonstrate an attempted write at runtime while + # keeping static analyzers from treating it as a real attribute write. + setattr(point1, "x", 5) # will raise AttributeError on namedtuple + except AttributeError: + access_immutable_error = True + assert access_immutable_error is True + + # One can access Point data by indexes + assert point1[0] + point2[0] == 4 + assert point1[0] + point2[1] == 5 + assert point1[1] + point2[0] == 5 + assert point1[1] + point2[1] == 6 + + point_dict = point1._asdict() + assert point_dict == {"x": 1, "y": 2} + + # It is possible to initialize a Point without explicit parameters + point3 = Point(10, 20) + assert point3.x == 10 + assert point3.y == 20 + assert Point._fields == ("x", "y") + + # It is also possible to create a new point out of an existing one + point4 = point1._replace(x=5) + assert point4.x == 5 + assert point4.y == 2 + + # Note that point4 is not the same as point1 + assert id(point4) != id(point1) + + +if __name__ == "__main__": + main() diff --git a/ultimatepython/data_structures/set.py b/ultimatepython/data_structures/set.py index ba4286a8..3b6d94ba 100644 --- a/ultimatepython/data_structures/set.py +++ b/ultimatepython/data_structures/set.py @@ -5,7 +5,7 @@ """ -def main(): +def main() -> None: # Let's define one `set` for starters simple_set = {0, 1, 2} diff --git a/ultimatepython/data_structures/string.py b/ultimatepython/data_structures/string.py index a58ebae1..d2be2469 100644 --- a/ultimatepython/data_structures/string.py +++ b/ultimatepython/data_structures/string.py @@ -8,7 +8,7 @@ _DELIMITER = " | " -def main(): +def main() -> None: # Strings are some of the most robust data structures around content = "Ultimate Python study guide" diff --git a/ultimatepython/data_structures/tuple.py b/ultimatepython/data_structures/tuple.py index 3dc2da1d..784f6ada 100644 --- a/ultimatepython/data_structures/tuple.py +++ b/ultimatepython/data_structures/tuple.py @@ -5,7 +5,7 @@ """ -def main(): +def main() -> None: # This is a tuple of integers immutable = (1, 2, 3, 4) diff --git a/ultimatepython/syntax/arg_enforcement.py b/ultimatepython/syntax/arg_enforcement.py new file mode 100644 index 00000000..65d5ca8c --- /dev/null +++ b/ultimatepython/syntax/arg_enforcement.py @@ -0,0 +1,243 @@ +""" +Positional-only and keyword-only parameters allow you to enforce how +arguments are passed to a function. This feature helps prevent misuse +of function APIs and makes code more maintainable. + +- Positional-only parameters (/) were introduced in Python 3.8 (PEP 570) +- Keyword-only parameters (*) were introduced in Python 3.0 (PEP 3102) + +These features give you fine-grained control over your function signatures. +""" + + +def traditional_function(a, b, c): + """A traditional function where all parameters can be passed either way. + + This function accepts arguments positionally or by keyword name. + While flexible, this can lead to API instability if parameter names change. + """ + return a + b + c + + +def positional_only(a, b, /): + """Function with positional-only parameters. + + The / symbol marks that parameters before it MUST be passed positionally. + This is useful when parameter names are not meaningful or when you want + to reserve the right to change parameter names without breaking callers. + + Parameters before / cannot be passed as keyword arguments. + """ + return a + b + + +def keyword_only(*, x, y): + """Function with keyword-only parameters. + + The * symbol marks that parameters after it MUST be passed by keyword. + This is useful for improving readability at call sites and preventing + accidental argument order mistakes. + + Parameters after * cannot be passed positionally. + """ + return x * y + + +def mixed_parameters(pos_only, /, pos_or_kw, *, kw_only): + """Function that combines all parameter types. + + - pos_only: Must be passed positionally (before /) + - pos_or_kw: Can be passed either way (between / and *) + - kw_only: Must be passed by keyword (after *) + + This gives maximum control over the function interface. + """ + return f"{pos_only}-{pos_or_kw}-{kw_only}" + + +def positional_with_defaults(a, b=10, /): + """Positional-only parameters can have default values. + + Default values work the same way as in traditional functions, + but the parameters still must be passed positionally if provided. + """ + return a + b + + +def keyword_with_defaults(*, x=5, y=3): + """Keyword-only parameters can have default values. + + When providing arguments, you must use the keyword names. + """ + return x**y + + +def complex_signature(a, b, /, c, d=10, *, e, f=20): + """A function demonstrating a complex but valid signature. + + - a, b: positional-only + - c: positional-or-keyword (no default) + - d: positional-or-keyword (with default) + - e: keyword-only (no default) + - f: keyword-only (with default) + """ + return a + b + c + d + e + f + + +def main() -> None: + # Traditional function: can be called either way + assert traditional_function(1, 2, 3) == 6 + assert traditional_function(a=1, b=2, c=3) == 6 + assert traditional_function(1, b=2, c=3) == 6 + + # Positional-only function: must use positional arguments + assert positional_only(5, 3) == 8 + + # Trying to use keyword arguments with positional-only parameters + # will raise a TypeError + positional_error = False + try: + # This will fail because 'a' and 'b' are positional-only + positional_only(a=5, b=3) # type: ignore [call-arg] + except TypeError: + positional_error = True + assert positional_error is True + + # You also can't mix positional and keyword for positional-only params + positional_error2 = False + try: + # This will fail because 'b' is positional-only + positional_only(5, b=3) # type: ignore [call-arg] + except TypeError: + positional_error2 = True + assert positional_error2 is True + + # Keyword-only function: must use keyword arguments + assert keyword_only(x=4, y=5) == 20 + + # Trying to use positional arguments with keyword-only parameters + # will raise a TypeError + keyword_error = False + try: + # This will fail because 'x' and 'y' are keyword-only + keyword_only(4, 5) # type: ignore [misc] + except TypeError: + keyword_error = True + assert keyword_error is True + + # Mixed parameters demonstrate all three types + result = mixed_parameters("first", "second", kw_only="third") + assert result == "first-second-third" + + # The middle parameter can be passed either way + result2 = mixed_parameters("first", pos_or_kw="second", kw_only="third") + assert result2 == "first-second-third" + + # But positional-only must be positional + mixed_error = False + try: + mixed_parameters(pos_only="first", pos_or_kw="second", kw_only="third") # type: ignore [call-arg] + except TypeError: + mixed_error = True + assert mixed_error is True + + # And keyword-only must be keyword + mixed_error2 = False + try: + mixed_parameters("first", "second", "third") # type: ignore [misc] + except TypeError: + mixed_error2 = True + assert mixed_error2 is True + + # Positional-only with defaults + assert positional_with_defaults(5) == 15 # Uses default b=10 + assert positional_with_defaults(5, 20) == 25 # Overrides b with 20 + + # Even with defaults, must use positional syntax + positional_default_error = False + try: + positional_with_defaults(a=5, b=20) # type: ignore [call-arg] + except TypeError: + positional_default_error = True + assert positional_default_error is True + + # Keyword-only with defaults + assert keyword_with_defaults() == 125 # Uses defaults: 5^3 + assert keyword_with_defaults(x=2) == 8 # 2^3 + assert keyword_with_defaults(y=2) == 25 # 5^2 + assert keyword_with_defaults(x=3, y=4) == 81 # 3^4 + + # Must still use keyword syntax even when providing defaults + keyword_default_error = False + try: + keyword_with_defaults(2, 3) # type: ignore [misc] + except TypeError: + keyword_default_error = True + assert keyword_default_error is True + + # Complex signature: demonstrating all parameter types + # Minimal call with required params only + result3 = complex_signature(1, 2, 3, e=4) + assert result3 == 40 # 1+2+3+10(default)+4+20(default) + + # Providing all parameters + result4 = complex_signature(1, 2, 3, 4, e=5, f=6) + assert result4 == 21 # 1+2+3+4+5+6 + + # Middle parameter 'c' can be passed by keyword + result5 = complex_signature(1, 2, c=3, e=4) + assert result5 == 40 + + # Parameter 'd' can also be passed by keyword + result6 = complex_signature(1, 2, 3, d=15, e=4) + assert result6 == 45 # 1+2+3+15+4+20 + + # But 'a' and 'b' must be positional + complex_error = False + try: + complex_signature(a=1, b=2, c=3, e=4) # type: ignore [call-arg] + except TypeError: + complex_error = True + assert complex_error is True + + # And 'e' must be keyword (even though 'f' has a default) + complex_error2 = False + try: + complex_signature(1, 2, 3, 10, 4) # type: ignore [misc] + except TypeError: + complex_error2 = True + assert complex_error2 is True + + # Practical use case: Positional-only is great for functions where + # parameter names are not meaningful or may change + def distance(x1, y1, x2, y2, /): + """Calculate distance between two points. + + The parameter names here are somewhat arbitrary (could be p1_x, etc.) + so we make them positional-only to give us flexibility to rename them + without breaking existing code. + """ + return ((x2 - x1) ** 2 + (y2 - y1) ** 2) ** 0.5 + + assert abs(distance(0, 0, 3, 4) - 5.0) < 0.01 + + # Practical use case: Keyword-only is great for boolean flags or + # optional parameters where the intent should be clear at call site + def create_user(username, *, admin=False, active=True, send_email=False): + """Create a user with clear intent for optional parameters. + + Making admin, active, and send_email keyword-only ensures that + callers must specify exactly what they're setting, improving + readability and preventing accidental mistakes. + """ + return {"username": username, "admin": admin, "active": active, "send_email": send_email} + + # Clear intent at call site + user = create_user("john_doe", admin=True, send_email=True) + assert user["admin"] is True + assert user["active"] is True # Used default + assert user["send_email"] is True + + +if __name__ == "__main__": + main() diff --git a/ultimatepython/syntax/bitwise.py b/ultimatepython/syntax/bitwise.py new file mode 100644 index 00000000..b26f25b8 --- /dev/null +++ b/ultimatepython/syntax/bitwise.py @@ -0,0 +1,50 @@ +""" +Bitwise operators in Python allow you to manipulate individual bits of integers. +This module demonstrates the use of bitwise operators and their behavior. +""" + + +def main() -> None: + # Define some integer values for demonstration + a = 5 # Binary: 0101 + b = 3 # Binary: 0011 + + # Bitwise AND (&) operator compares each bit of two integers and returns 1 + # if both bits are 1, otherwise returns 0 + result_and = a & b # Binary: 0001 (Decimal: 1) + assert result_and == 1 + + # Bitwise OR (|) operator compares each bit of two integers and returns 1 + # if at least one bit is 1, otherwise returns 0 + result_or = a | b # Binary: 0111 (Decimal: 7) + assert result_or == 7 + + # Bitwise XOR (^) operator compares each bit of two integers and returns 1 + # if the bits are different (one is 1 and the other is 0), otherwise returns 0 + result_xor = a ^ b # Binary: 0110 (Decimal: 6) + assert result_xor == 6 + + # Bitwise NOT (~) operator inverts all bits of an integer + # It returns the one's complement of the integer + result_not_a = ~a # Binary: 11111010 (Decimal: -6) + assert result_not_a == -6 + + # Bitwise left shift (<<) operator shifts the bits of an integer to the left by + # a specified number of positions, filling with zeros + result_left_shift = a << 2 # Binary: 010100 (Decimal: 20) + assert result_left_shift == 20 + + # Bitwise right shift (>>) operator shifts the bits of an integer to the right + # by a specified number of positions, filling with zeros for positive numbers + # and with ones for negative numbers + result_right_shift = a >> 1 # Binary: 0010 (Decimal: 2) + assert result_right_shift == 2 + + # Note that bitwise shifts have lower precedence than arithmetic operations + # https://docs.python.org/3/reference/expressions.html + result_right_shift_with_addition = a >> 1 + 1 # Equivalent to a >> (1 + 1) + assert result_right_shift_with_addition == 1 # Binary: 0001 (Decimal: 1) + + +if __name__ == "__main__": + main() diff --git a/ultimatepython/syntax/conditional.py b/ultimatepython/syntax/conditional.py index aafa2ba2..197c5ec5 100644 --- a/ultimatepython/syntax/conditional.py +++ b/ultimatepython/syntax/conditional.py @@ -4,7 +4,7 @@ """ -def main(): +def main() -> None: x = 1 x_add_two = x + 2 @@ -30,7 +30,7 @@ def main(): assert ran_3 is True # The `else` statement also runs once all other `if` and `elif` conditions - # fail. Notice that multiple lines get skipped, and that all of the + # fail. Notice that multiple lines get skipped, and that all the # conditions could have been compressed to `x_add_two != 3` for # simplicity. In this case, less logic results in more clarity if x_add_two == 1: @@ -50,6 +50,17 @@ def main(): ran_5 = True if x_add_two == 3 else False assert ran_5 is True + # Python is one of the few programming languages that allows chained + # comparisons. This is useful for checking if a variable is within + # a range of values. You can see that in this example, the expression + # `0 < x_add_two < 2` is equivalent to `x_add_two > 0 and x_add_two < 2` + ran_6 = False + if 0 < x_add_two < 2: + ran_6 = False # skip: if + else: + ran_6 = True # run + assert ran_6 is True + if __name__ == "__main__": main() diff --git a/ultimatepython/syntax/expression.py b/ultimatepython/syntax/expression.py index b0fd0d13..9822af09 100644 --- a/ultimatepython/syntax/expression.py +++ b/ultimatepython/syntax/expression.py @@ -3,8 +3,10 @@ on existing integers. """ +import math -def main(): + +def main() -> None: # This is a simple integer x = 1 @@ -19,7 +21,7 @@ def main(): # Division is tricky because Python 3.x returns 0.5 of type `float` # whereas Python 2.x returns 0 of type `int`. If this line fails, it # is a sign that the wrong version of Python was used - assert x / 2 == 0.5 + assert math.isclose(x / 2, 0.5) # If an integer division is desired, then an extra slash must be # added to the expression. In Python 2.x and Python 3.x, the behavior @@ -29,7 +31,7 @@ def main(): # Powers of an integer can be leveraged too. If more features are # needed, then leverage the builtin `math` library or a third-party # library. Otherwise, we have to build our own math library - assert x * 2 ** 3 == 8 + assert x * 2**3 == 8 if __name__ == "__main__": diff --git a/ultimatepython/syntax/function.py b/ultimatepython/syntax/function.py index 141c9b46..0ab84c9d 100644 --- a/ultimatepython/syntax/function.py +++ b/ultimatepython/syntax/function.py @@ -5,8 +5,10 @@ in an interesting way. """ +from typing import Any, Callable -def add(x, y): + +def add(x: Any, y: Any) -> Any: """Add two objects together to produce a new object. Two differences between `add` and `main` are that: @@ -17,7 +19,7 @@ def add(x, y): return x + y -def sum_until(fn, n): +def sum_until(fn: Callable[[int], int], n: int) -> int: """Sum function results from 0 until n - 1. This expects a function to be provided as its first input and an integer @@ -33,7 +35,18 @@ def sum_until(fn, n): return total -def main(): +def without_parameters() -> object: + """A function that does not accept parameters and does not return a value. + + The return type is annotated as `object` to allow callers that assert + on the returned value (e.g. `assert without_parameters() is None`) without + triggering static checker complaints about a function annotated as + returning None being used as a value. + """ + return None + + +def main() -> None: # The `add` function can be used for numbers as expected add_result_int = add(1, 2) assert add_result_int == 3 @@ -52,7 +65,11 @@ def main(): # We can see the `sum_until` docstring by accessing the `__doc__` magic # attribute! Remember this - everything in Python is an object - assert "includes this docstring!" in sum_until.__doc__ + # `__doc__` may be None in some environments, coalesce to an empty string + assert "includes this docstring!" in (sum_until.__doc__ or "") + + # Call a function without parameters + assert without_parameters() is None if __name__ == "__main__": diff --git a/ultimatepython/syntax/loop.py b/ultimatepython/syntax/loop.py index 844135da..c7747695 100644 --- a/ultimatepython/syntax/loop.py +++ b/ultimatepython/syntax/loop.py @@ -11,7 +11,7 @@ """ -def main(): +def main() -> None: # This is a `for` loop that iterates on values 0..4 and adds each # value to `total`. It leverages the `range` iterator. Providing # a single integer implies that the start point is 0, the end point @@ -35,8 +35,8 @@ def main(): assert fact == 120 # This is a simple `while` loop, similar to a `for` loop except that the - # counter is declared outside of the loop and its state is explicitly - # managed inside of the loop. The loop will continue until the counter + # counter is declared outside the loop and its state is explicitly + # managed inside the loop. The loop will continue until the counter # exceeds 8 i = 0 while i < 8: diff --git a/ultimatepython/syntax/variable.py b/ultimatepython/syntax/variable.py index 442d67b9..36cb3df7 100644 --- a/ultimatepython/syntax/variable.py +++ b/ultimatepython/syntax/variable.py @@ -4,8 +4,10 @@ about the state of each defined variable. """ +import math -def main(): + +def main() -> None: # Here are the main literal types to be aware of a = 1 b = 2.0 @@ -46,8 +48,15 @@ def main(): # We can use underscores (literal `_`) to separate digit groups in # integer literals assert 10_000 == 10000 - assert 0x01_0f_2c == 69_420 - assert 3.456_290e-1 == 0.3_456_290 + assert 0x01_0F_2C == 69_420 + assert math.isclose(3.456_290e-1, 0.3_456_290) + + # There is also a special literal called None. This literal is used to + # point that a particular variable or object is not created + e = None + e_type = type(e) + assert e_type is type(None) + assert isinstance(e, object) and isinstance(e_type, object) if __name__ == "__main__": diff --git a/ultimatepython/syntax/walrus_operator.py b/ultimatepython/syntax/walrus_operator.py new file mode 100644 index 00000000..733e3c01 --- /dev/null +++ b/ultimatepython/syntax/walrus_operator.py @@ -0,0 +1,121 @@ +""" +The walrus operator, also known as the assignment expression operator, +allows you to assign values to variables as part of an expression. This +feature was introduced in Python 3.8 through PEP 572. + +The walrus operator uses the := syntax and is particularly useful in +reducing redundancy when you need to compute a value and then use it +in a condition or comprehension. +""" + + +def main() -> None: + # Traditional approach: compute a value and check it separately + # Let's say we want to check if a string has more than 5 characters + text = "Hello, Python!" + length = len(text) + if length > 5: + assert length == 14 + + # With the walrus operator, we can assign and check in one expression. + # This is cleaner and avoids repeating the computation or storing + # intermediate variables unnecessarily + text2 = "Ultimate" + if (length2 := len(text2)) > 5: + # The walrus operator assigned len(text2) to length2 AND returned it + # for the comparison, all in the same line + assert length2 == 8 + + # The walrus operator is especially powerful in while loops. Here's a + # traditional approach that requires reading input twice + numbers_old = [] + n = int("5") # Simulating user input + while n != 0: + numbers_old.append(n) + n = int("0") # Simulating next input + assert numbers_old == [5] + + # With the walrus operator, we can assign and check in the loop condition. + # This is more concise and avoids the duplication of the input reading logic + numbers_new = [] + inputs = ["3", "7", "0"] # Simulating a sequence of inputs + index = 0 + + # Note: In a real scenario, you'd read from input() instead of a list + def get_next_input(): + nonlocal index + if index < len(inputs): + result = int(inputs[index]) + index += 1 + return result + return 0 + + while (num := get_next_input()) != 0: + # The walrus operator assigns get_next_input() to num and checks if it's not 0 + numbers_new.append(num) + assert numbers_new == [3, 7] + + # Ensure the function returns 0 when no more inputs + assert get_next_input() == 0 + + # The walrus operator shines in list comprehensions when you need to + # compute a value once and reuse it. Without walrus, you'd either: + # 1. Compute the value multiple times (inefficient) + # 2. Use a for loop instead of comprehension (less elegant) + data = ["apple", "banana", "cherry", "date"] + + # Traditional approach: computing len() twice per item is wasteful + long_words_old = [word for word in data if len(word) > 5 and len(word) < 7] + assert long_words_old == ["banana", "cherry"] + + # With walrus operator: compute len() once and reuse the result + # The walrus operator assigns len(word) to word_len, which we can + # then use multiple times in the same comprehension + long_words_new = [word for word in data if 5 < (word_len := len(word)) < 7] + assert long_words_new == ["banana", "cherry"] + + # The walrus operator can be used in comprehensions to filter and transform + # data simultaneously. Here we square numbers but only keep those where + # the square is less than 50 + numbers = [3, 5, 7, 9, 11] + + # Without walrus: we'd need to compute the square twice or use a for loop + squares_old = [n * n for n in numbers if n * n < 50] + assert squares_old == [9, 25, 49] + + # With walrus: compute the square once, store it, and use it + # This is both more efficient and clearer about the intent + squares_new = [square for n in numbers if (square := n * n) < 50] + assert squares_new == [9, 25, 49] + + # The walrus operator works in set comprehensions too + # Let's find unique word lengths greater than 4 + words = ["hi", "hello", "world", "python", "code"] + + # With walrus operator in a set comprehension + long_lengths = {word_len for word in words if (word_len := len(word)) > 4} + assert long_lengths == {5, 6} + + # And in dictionary comprehensions as well + # Create a dict of words to their lengths, but only for words > 4 chars + word_length_map = {word: word_len for word in words if (word_len := len(word)) > 4} + assert word_length_map == {"hello": 5, "world": 5, "python": 6} + + # Important note: The walrus operator creates variables in the enclosing scope. + # This means variables assigned with := inside a comprehension are accessible + # outside of it (unlike traditional loop variables in comprehensions) + [result for x in [1, 2, 3] if (result := x * 2) > 2] + # The variable 'result' is now accessible here, with its last assigned value + assert result == 6 + + # The walrus operator can be nested, though this can reduce readability + # Use nesting sparingly and only when it genuinely improves the code + values = [1, 2, 3, 4, 5] + if (total := sum(doubled := [x * 2 for x in values])) > 15: + # Here 'doubled' is assigned inside the expression for 'total' + assert doubled == [2, 4, 6, 8, 10] + assert total == 30 + + +if __name__ == "__main__": + main()