Skip to content

maskegger/python-practice

 
 

Repository files navigation

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.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Emacs Lisp 62.7%
  • Python 37.3%