Skip to content

Latest commit

 

History

History
136 lines (99 loc) · 6.49 KB

README.org

File metadata and controls

136 lines (99 loc) · 6.49 KB

Python Pracitce

The purpose of this repository is for me to have a place where I’m practicing Python.

System Installation

On Macos, I use the brew ecosystem. I need some dependencies installed:

brew install python
If I’m going to play with Python, I should probably install it.
brew install uv
a Rust based package manager for Python.
brew install python-lsp-server
wire this into Eglot for LSP functionality.
  • uv venv
  • uv pip install virtualenv

Emacs and Python

I added the following to my Emacs configuration:

(use-package python
  :straight (:type built-in)
  :hook (python-mode . jf/python-mode-configurator)
  :config
  (defun jf/python-mode-configurator ()
    (eldoc-mode t)
    (eglot-ensure)
    (python-docstring-mode t)
    (setq-default python-indent-offset 4)
    ;; I’m loving an 80 column fill…Why?  Because on my small computer I can
    ;; have 4 windows laid out in a quadrant and see all of the code/text.
    (setq-local fill-column 80)))

;; The treesit package of Emacs 29+ behaves a bit different.
(add-hook 'python-ts-mode-hook #'jf/python-mode-configurator)

;; A Python syntax validator/linter.
(use-package flymake-ruff
  :straight t
  :hook (eglot-managed-mode . flymake-ruff-load))

;; To provide some syntax highlighting of docstrings, and more.
(use-package python-docstring
  :straight t)

;; To create narrowable groups
(dolist (python '(python-mode python-ts-mode))
(add-to-list 'consult-imenu-config
  `(,python
     :toplevel "Method"
     :types ((?f "Field" font-lock-variable-name-face)
              (?c "Class" font-lock-type-face)
              (?m "Method" font-lock-function-name-face)
              (?v "Variable" font-lock-variable-name-face)
              ))))

I started reading Brandon Rhodes’ Python Patterns; a dear friend with whom I have dinner and beers every Thursday evening.

With python-mode enabled, I typed C-c C-c and Emacs prompted me to start a Python process by typing C-c C-p. I started the process, and went back to my Python code, then typed C-c C-c and the print statements were echoed to that Python process. Super helpful for introspection.

I’m also considering installing Crandel/tempel-collection: Collection tempel templates; there’s some templates for Python. I’ve already found the occasional line ending in : is a bit jarring; it’s one of those “I definitely want a linter running to remind me of this missing value.”

Exploring LSP Options

I’ve been back and forth on which LSP package to use. I started with python-lsp-server, I was a bit overwhelmed looking at https://gist.github.com/doolio/8c1768ebf33c483e6d26e5205896217f. So I explored lsp-pyright, but as someone who favors the simplicity of eglot, I went back to python-lsp-server.

  • =uv pip install “python-lsp-server[all]”=
  • uv pip install pylsp-rope

Documentation

I installed local documentation for Python 3.12 and Django 5.0 via both the devdocs package and dash-docs package. Having long used devdocs, I’m currently comparing it’s features and usability with dash-docs.

I’ve also installed the info pages for Python, providing yet another way to explore the documentation.

Last, I installed the sphinx-doc package; this provides the sphinx-doc command (bound to C-c M-d). Calling that command within a method will pre-populate the docstring with parameter and return value information. I find this useful, given that I’m learning a new syntax for documentation.

The Practice Files

I have individual practice files, with comments around connecting Python concepts to Ruby counterparts.

exceptions.py
A simple reference of the exception handling construction of Python.
introspection.py
Exploring named parameters and object introspection.
iterator.py
Exploring some of the iterators; though there are more reflections below.
object-instantiation.py
Looking at default values for object’s fields/properties.
static-method.py
Exploring the @staticmethod directive while also reviewing The Abstract Factory Pattern.

In addition to the Python files, I have written further discussion regarding other topics; see below.

Iterator

As I read The Iterator Pattern, I’m mapping these concepts to Ruby.

Below we map the symbols of elements with an atomic weight greater than 5.

dictionary = {'H': 1.008, 'He': 4.003, 'Li': 6.94}
list(symbol for symbol, weight in dictionary.items() if weight > 5)

# Analogous to the above
[symbol for symbol, weight in d.items() if weight > 5]
dictionary = { H: 1.008, He: 4.003, Li: 6.94 }
dictionary.each_with_object([]) { |(symbol, weight), array| array << symbol.to_s if weight > 5 }

Both return an Array of one element; namely ["Li"]. The syntax of Python takes a bit of adjustment, in part because I’m accustomed to Ruby’s idioms and syntax.

Stepping back a bit, the syntax of Python requires less conceptualization. The three symbols: [, symbol, and for provide early indicators that I’m “Making an array of the “symbol” variable defined in the for loop.

The same applies with starting a dictionary.

Put another way, while I’m familiar with Ruby’s various iterator functions and their blocks, Python front-loads the “What is this object?” Ruby says “Noun, verb, object” and Python says “Object, verb from noun.”

Though setting the results into a local variable can also provide guidance on what the “map” is. And that named variable is declared before the mapping.