diff --git a/notes-en/counter.md b/notes-en/counter.md
index 85511a6..5bb56f6 100644
--- a/notes-en/counter.md
+++ b/notes-en/counter.md
@@ -1,6 +1,6 @@
# Everything about Counter
-I think, `collections.Counter` is the most magic and powerful container in Python. In a nutshell, this is [multiset](https://en.wikipedia.org/wiki/Multiset) realization. Let's have a look what `Counter` can do.
+I think, `collections.Counter` is the most magic and powerful container in Python. In a nutshell, this is [multiset](https://en.wikipedia.org/wiki/Multiset) realization. Let's have a look at what `Counter` can do.
## Basic usage
@@ -25,7 +25,7 @@ Ok, now let's dive into Counter features.
## Init
-`Counter` is a child of `dict`, and all elements, so you can initialize it from sequence as in "Basic usage" section or by any way how you initialize `dict`.
+`Counter` is a child of `dict`, and all elements, so you can initialize it from a sequence as in "Basic usage" section or by any way how you initialize `dict`.
```python
Counter()
@@ -86,7 +86,7 @@ list(c.values())
# [2, 3]
```
-However, `.update()` method smarter and can get anything what you can pass in `init`. Also it merges values.
+However, `.update()` method smarter and can get anything that you can pass in `init`. Also, it merges values.
```python
c = Counter({'first': 1})
@@ -115,7 +115,7 @@ c2 - c1
# Counter({'common': 1, 'second': 4})
```
-As you can see, arithmetic operations drops negative values.
+As you can see, arithmetic operations drop negative values.
```python
Counter(a=-2) - Counter(a=-1)
@@ -155,7 +155,7 @@ Counter(a=-1) | Counter(b=-2)
# Counter()
```
-## A little bi more about non-positive values
+## A little bit more about non-positive values
From source code:
@@ -206,7 +206,7 @@ c.most_common(2)
`Counter` is:
-* Dictionary with default value,
+* Dictionary with a default value,
* Supports set and arithmetic operations,
* Can count elements in sequence very fast,
* Can return N or all elements sorted by value,
diff --git a/notes-en/pep-with-if.md b/notes-en/pep-with-if.md
deleted file mode 100644
index 53f4235..0000000
--- a/notes-en/pep-with-if.md
+++ /dev/null
@@ -1,56 +0,0 @@
-# Condition for context manager
-
-Use context manager only if condition is True. Otherwise execute context
-without context manager.
-
-## Syntax
-
-```python
-with manager [as alias] if condition:
- ...
-```
-
-## Example
-
-For example, we have function for getting users from database.
-1. If session is passed to function then use it, but don't close.
-2. If there is no session passed then create new session and close it after all.
-
-```python
-def get_users(session=None):
- with get_session() as session if session is None:
- # do something
- ...
-```
-
-Let's look possible solutions without this syntax.
-
-Bad solution:
-
-```python
-def get_users(session=None):
- if session is not None:
- # do something
- ...
- else:
- with get_session() as session:
- # do the same
- ...
-```
-
-DRY solution:
-
-```python
-def _get_users(session):
- # do something
- ...
-
-def get_users(session=None):
- if session is not None:
- return _get_users(session)
- with get_session(session) as session:
- return _get_users(session)
-```
-
-However if function gets many arguments then we should pass them all to new
-function in both calls.
diff --git a/notes-en/python-iterators.md b/notes-en/python-iterators.md
index 602a56f..a3dbd4f 100644
--- a/notes-en/python-iterators.md
+++ b/notes-en/python-iterators.md
@@ -2,14 +2,14 @@
## How to create your own iterator or iterable?
-In Python we have two complementary terms: iterator and iterable.
+In Python, we have two complementary terms: iterator and iterable.
An **iterable** is an object that has an `__iter__` method which returns an iterator, or which defines a `__getitem__` method that can take sequential indexes starting from zero (and raises an IndexError when the indexes are no longer valid). So, you get the iterator from the iterable object. By default `__iter__` always returns `self`.
An **iterator** is an object with a `__next__` method.
-## How to get iterator from iterable?
+## How to get an iterator from iterable?
You can get iterator from any iterable via `iter` function:
@@ -64,7 +64,7 @@ Out[25]: {1, 2, 3}
## What about `range`?
-`range` is not iterator. It is iterable:
+`range` is not an iterator. It is iterable:
```python
In [17]: r = range(10)
diff --git a/notes-en/python-packaging.md b/notes-en/python-packaging.md
index 8eb22a5..42af445 100644
--- a/notes-en/python-packaging.md
+++ b/notes-en/python-packaging.md
@@ -1,25 +1,23 @@
# Python packaging for your team
-**IMPORTANT:** This is personal opinion of the author. Also you can find in this article some mistakes. Feel free to contribute.
+I love [decoupling](https://en.wikipedia.org/wiki/Coupling_(computer_programming)). This makes the project maintaining easier. We have 2 main ways to do it:
-I love [decoupling](https://en.wikipedia.org/wiki/Coupling_(computer_programming)). This makes project maintaining easier. We have 2 main ways do it:
-
-1. [Git submodules](https://git-scm.com/book/en/v2/Git-Tools-Submodules). This is good conception but sometimes very confusable. Also you must commit updates in parent project for each submodule changing.
-2. Packaging. I think this solution is better because you already use many packages in your project. You can easily package your project and explain this conception to any junior.
+1. [Git submodules](https://git-scm.com/book/en/v2/Git-Tools-Submodules). This is a good conception but sometimes very confusable. Also, you must commit updates in parent project for each submodule changing.
+2. Packaging. I think this solution is better because you already use many packages in your project. You can easily package your project and explain this concept to any junior.
This article about creating [python package](https://packaging.python.org/) without pain.
## Setuptools
-Most python packages which you are using contain [setup.py](https://packaging.python.org/tutorials/packaging-projects/#creating-setup-py) file in it's root directory. This file describes package name, version, requirements (required third party packages), package content and some optional information. Just call `setuptools.setup(...)` with this info as kwargs. It's enough for package distribution. If you have setup.py then you already can distribute it. For example, upload into [pypi.org](https://pypi.org/).
+Most python packages which you are using contain [setup.py](https://packaging.python.org/tutorials/packaging-projects/#creating-setup-py) file in its root directory. This file describes package name, version, requirements (required third-party packages), package content and some optional information. Just call `setuptools.setup(...)` with this info as kwargs. It's enough for package distribution. If you have setup.py then you already can distribute it. For example, upload into [pypi.org](https://pypi.org/).
## Pip and virtualenv
[Pip](https://pip.pypa.io/en/stable/) -- de facto standard approach for installing python packages in your system. Simple and well known.
-By default, pip installs all packages for all users in the system and requires root privileges for it. [Don't sudo pip](https://pages.charlesreid1.com/dont-sudo-pip/). Use virtualenv to install packages into isolated environments. Besides security troubles some packages may have incompatible required versions of some mutual package.
+By default, pip installs all packages for all users in the system and requires root privileges for it. [Don't sudo pip](https://pages.charlesreid1.com/dont-sudo-pip/). Use virtualenv to install packages into isolated environments. Besides security troubles, some packages may have incompatible required versions of some mutual package.
Also I recommend to use [pipsi](https://github.com/mitsuhiko/pipsi) for some global entry points like [isort](https://github.com/timothycrosley/isort). Yeah, pipsi uses virtualenv.
@@ -43,7 +41,7 @@ Django>=1.11
...
```
-Also pip supports constraints.txt with same syntax for pinning versions for optional dependencies:
+Also, pip supports constraints.txt with the same syntax for pinning versions for optional dependencies:
```
djangorestframework>=3.5
@@ -55,7 +53,7 @@ To install these dependencies just pass them into pip:
pip install -r requirements.txt -c constraints.txt
```
-Requirements.txt is very useful when you don't want create setup.py for your internal projects.
+Requirements.txt is very useful when you don't want to create setup.py for your internal projects.
## Pip-tools
@@ -63,58 +61,58 @@ Requirements.txt is very useful when you don't want create setup.py for your int
In most commercial projects you have at least 2 environments:
1. Development. Here you can get last available packages versions, develop and test project with it.
-2. Production. Here you are able to create same environment as where you're testing this code. And this requirements must not be updated while you're not testing and improving your code for changes in new versions. Also other developers are able to get same environment as you, because it's already tested and this approach is saving their time.
+2. Production. Here you are able to create the same environment as where you're testing this code. And these requirements must not be updated while you're not testing and improving your code for changes in new versions. Also, other developers are able to get the same environment as you, because it's already tested and this approach is saving their time.
[Pip-tools](https://github.com/jazzband/pip-tools) provide some tools for this conception.
## Pipfile and pipenv
-Pip developers decided to [improve requirements.txt](https://github.com/pypa/pip/issues/1795) for grouping dependencies and enabling native support for version locking. As a result they have created [Pipfile specification](https://github.com/pypa/pipfile) and [pipenv](https://docs.pipenv.org/) -- tool for working with it. Pipenv can lock versions in [Pipfile.lock], manage virtual environments, install and resolve dependencies. So cool, but for distributable packages you must duplicate main dependencies into setup.py.
+Pip developers decided to [improve requirements.txt](https://github.com/pypa/pip/issues/1795) for grouping dependencies and enabling native support for version locking. As a result, they have created [Pipfile specification](https://github.com/pypa/pipfile) and [pipenv](https://docs.pipenv.org/) -- a tool for working with it. Pipenv can lock versions in [Pipfile.lock], manage virtual environments, install and resolve dependencies. So cool, but for distributable packages, you must duplicate main dependencies into setup.py.
## Poetry
-[Poetry](https://github.com/sdispater/poetry) -- beautiful alternative to setuptools and pip. You can just place all package info and all requirements into [pyproject.toml](https://poetry.eustace.io/docs/pyproject/). That's all. Beautiful. But poetry have some problems:
+[Poetry](https://github.com/sdispater/poetry) -- beautiful alternative to setuptools and pip. You can just place all package info and all requirements into [pyproject.toml](https://poetry.eustace.io/docs/pyproject/). That's all. Beautiful. But poetry has some problems:
-1. It's not compatible with setuptools. As a result, your users can't install your project without poetry. Everybody have setuptools, but many users doesn't know about poetry. You can use it for your internal projects, but poetry can't install dependencies from file or repository without `pyproject.toml` generating. Yeah, if you fork and improve some project, you must make [sdist](https://docs.python.org/3/distutils/sourcedist.html) for any changes and bump version for all projects that depend on it. Or manually convert project's `setup.py` to `pyproject.toml`.
-2. Poetry [doesn't creates virtual environment](https://poetry.eustace.io/docs/basic-usage/#poetry-and-virtualenvs) if you already into virualenv. So, poetry doesn't create environment if you install poetry via pipsi. Pipenv as opposed to poetry always create virtual environment for project and [can choose right python version](https://docs.pipenv.org/advanced/#automatic-python-installation).
+1. It's not compatible with setuptools. As a result, your users can't install your project without poetry. Everybody have setuptools, but many users don't know about poetry. You can use it for your internal projects, but poetry can't install dependencies from file or repository without `pyproject.toml` generating. Yeah, if you fork and improve some project, you must make [sdist](https://docs.python.org/3/distutils/sourcedist.html) for any changes and bump version for all projects that depend on it. Or manually convert project's `setup.py` to `pyproject.toml`.
+2. Poetry [doesn't creates a virtual environment](https://poetry.eustace.io/docs/basic-usage/#poetry-and-virtualenvs) if you already into virualenv. So, poetry doesn't create an environment if you install poetry via pipsi. Pipenv, as opposed to poetry, always creates a virtual environment for a project and [can choose the right python version](https://docs.pipenv.org/advanced/#automatic-python-installation).
3. Poetry use [version specifiers](https://poetry.eustace.io/docs/versions/#version-constraints) incompatible with [PEP-440](https://www.python.org/dev/peps/pep-0440/#version-specifiers). This makes me sad.
-For backward compatibility you can generate setup.py and requirements.txt from pyproject.toml via [poetry-setup](https://github.com/orsinium/poetry-setup).
+For backward compatibility, you can generate setup.py and requirements.txt from pyproject.toml via [poetry-setup](https://github.com/orsinium/poetry-setup).
## Flit
-If pyproject.toml is cool, why only poetry use it? Not only. [Flit](https://github.com/takluyver/flit) supports pyproject.toml too. This is very simple tool with only 4 commands:
+If pyproject.toml is cool, why only poetry use it? Not only. [Flit](https://github.com/takluyver/flit) supports pyproject.toml too. This is a very simple tool with only 4 commands:
1. **init** -- interactively create pyproject.toml.
2. **build** -- make sdist or wheel.
-3. **publish** -- upload package into PyPI (or other repository).
-4. **install** -- install local package into current environment.
+3. **publish** -- upload package into PyPI (or another repository).
+4. **install** -- install a local package into the current environment.
-That's all. And enough in common cases. Flit uses pip for packages installation. And flit listed in [alternatives by PyPA](https://packaging.python.org/key_projects/?#flit). As in poetry you need manage virtual environments by other tools. But this package has a significant disadvantage: flit can't lock dependencies.
+That's all. And enough in common cases. Flit uses pip for packages installation. And flit listed in [alternatives by PyPA](https://packaging.python.org/key_projects/?#flit). As in poetry, you need to manage virtual environments by other tools. But this package has a significant disadvantage: flit can't lock dependencies.
-## Let's make best packaging for your team!
+## Let's make the best packaging for your team!
All solutions below have some problems. Let's fix it!
### Poetry based packaging
-1. Always create virtual environment for each project. I recommend to use [pew](https://github.com/berdario/pew) or [virtualenvwrapper](https://virtualenvwrapper.readthedocs.io/en/latest/) for better experience.
-2. Use [pyenv](https://github.com/pyenv/pyenv) or [pythonz](https://github.com/saghul/pythonz) for python versions managing. Also I'm recommend try to use [pypy](https://pypy.org/) for some your small and well tested projects. It's really fast.
-3. Sometimes you want depend some setuptools-based projects on some package. Use [poetry-setup](https://github.com/orsinium/poetry-setup) for compatibility with it.
+1. Always create a virtual environment for each project. I recommend to use [pew](https://github.com/berdario/pew) or [virtualenvwrapper](https://virtualenvwrapper.readthedocs.io/en/latest/) for better experience.
+2. Use [pyenv](https://github.com/pyenv/pyenv) or [pythonz](https://github.com/saghul/pythonz) for python versions managing. Also, I recommend try to use [pypy](https://pypy.org/) for some of your small and well-tested projects. It's really fast.
+3. Sometimes you want to depend on some setuptools-based projects on some package. Use [poetry-setup](https://github.com/orsinium/poetry-setup) for compatibility with it.
### Pipfile or requirements.txt based packaging
-As we remember, with pipenv we need duplicate all requirements in old format for setup.py. Let's improve it! I'm create [install-requires](https://github.com/orsinium/install-requires) project that can help you convert requirements between formats. But which format should you choose?
+As we remember, with pipenv we need to duplicate all requirements in old format for setup.py. Let's improve it! I've created [install-requires](https://github.com/orsinium/install-requires) project that can help you convert requirements between formats. But which format should you choose?
-1. `requirements.txt`. This is most popular requirements format for projects. Anyone can use it as they want.
-2. `Pipfile.lock`. Pipenv have better requirements lock than pip-tools, and you should use it for better security. But if you want to create package from project, then you plan use this package into other projects. So, if this project depends on more than one package with locked requirements, pipenv can't resolve these dependencies. For example, one package lock `Django==1.9` version, but other uses `Django==1.11`. Do not use it for distributable packages: PyPA recommends to [place not locked versions into install_requires](https://packaging.python.org/discussions/install-requires-vs-requirements/).
-3. `Pipfile`. This is our choose. Modern format with some problems, but also with many features. And, most importantly, simple and comfortable. I'm recommend use it for internal python packages in your company.
+1. `requirements.txt`. This is the most popular requirements format for projects. Anyone can use it as they want.
+2. `Pipfile.lock`. Pipenv has better requirements lock than pip-tools, and you should use it for better security. But if you want to create a package from a project, then you plan to use this package into other projects. So, if this project depends on more than one package with locked requirements, pipenv can't resolve these dependencies. For example, one package lock `Django==1.9` version, but other uses `Django==1.11`. Do not use it for distributable packages: PyPA recommends to [place not locked versions into install_requires](https://packaging.python.org/discussions/install-requires-vs-requirements/).
+3. `Pipfile`. This is our choice. Modern format with some problems, but also with many features. And, most importantly, simple and comfortable. I recommend using it for internal python packages in your company.
Install-requires repository contains [example](https://github.com/orsinium/install-requires/blob/master/example/setup.py) how you can convert requirements from Pipfile to setup.py compatible format on the fly.
@@ -125,10 +123,10 @@ Many developers (me too) love poetry because it uses beautiful project metadata
Setuptools supports requirements from VCS, file or archive via [dependency_links parameter](https://setuptools.readthedocs.io/en/latest/setuptools.html#dependencies-that-aren-t-in-pypi). And requirements grouping via [extras_require](https://setuptools.readthedocs.io/en/latest/setuptools.html#declaring-extras-optional-features-with-their-own-dependencies).
-So, what's wrong with setuptools? I think, this tool have some problems:
+So, what's wrong with setuptools? I think this tool has some problems:
-1. No native virtualenv and python version managing. And poetry can't do it too. But we have pew, virtualenvwrapper, pyenv, pythonz and many other useful tools. This is UNIX-way.
-2. No dependencies locking. Poetry, pipenv and pip (`pip freeze`) can lock dependencies from it's own files. Setuptools can't. This is because setuptools for packages, not projects.
+1. No native virtualenv and python version managing. And poetry can't do it too. But we have pew, virtualenvwrapper, pyenv, pythonz, and many other useful tools. This is UNIX-way.
+2. No dependencies locking. Poetry, pipenv, and pip (`pip freeze`) can lock dependencies from its own files. Setuptools can't. This is because of setuptools for packages, not projects.
3. Setup.cfg is good, but [pyproject.toml better](https://github.com/pypa/packaging-problems/issues/29#issuecomment-375845650). Setuptools [will support pyproject.toml](https://github.com/pypa/setuptools/issues/1160) and deprecate setup.py and setup.cfg. Also [pip will support it too](https://pip.pypa.io/en/stable/reference/pip/?highlight=pyproject.toml%20#build-system-interface). And it's cool!
@@ -145,9 +143,8 @@ So, what's wrong with setuptools? I think, this tool have some problems:
1. [install_requires vs requirements files](https://packaging.python.org/discussions/install-requires-vs-requirements/).
-## Further reading (rus)
+## Further reading (RUS)
1. [About poetry](https://t.me/itgram_channel/152).
1. [About PyPy and python dev environment](https://t.me/itgram_channel/97).
1. [About toml format](https://t.me/itgram_channel/113).
-