Thursday, May 29, 2008

Back to Python

I haven't used Python in a while. I'm logging my re-familiarization on the REPL and Doc Strings.

REPL

I write my code in emacs and run it on the REPL instead of just doing ./my_code.py. I use execfile to load my code:
$ ls -l my_code.py 
-rwx------ 1 user user 3305 May 29 10:17 my_code.py
$ python 
Python 2.4.3 (#1, Dec 11 2006, 11:38:52) 
[GCC 4.1.1 20061130 (Red Hat 4.1.1-43)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> execfile("my_code.py")
>>> call_a_function_defined_in_my_code()
>>>
In emacs M-x py-shell will get you a local Python REPL and you can C-x o in a split screen between the REPL and your code (for mouse free development). I like to use tramp to edit remote files. To accommodate this style with the py-shell I just ssh from ansi-term and start the REPL as above.

Doc Strings

I tend to include a lot of comments when I define functions. My typical function looks like this:
# -------------------------------------------------------
def my_function():
    """
    Function:                my_function

    Description:             1-3 line description of 
                             the function... with an 
                             extra line here... 

    Parameters:
       [in] string $url      The URL for x
       [in] array $arr       An associative array of y
       [in] int $num         The amount of z
       (in) boolean $flag    An optional flag to do k
                             (Default: false)
       (in) string $name     An optional name
                             (Default: "Larry")

    Return Values:           
       interger              -1 if an error occured
                             0 if authentication failed
                             1 on sucess

    Remarks:                 
       None                  
    """
    # ---------------------------------------------------
    # first line here
I can view this with Python's __doc__ attribute:
>>> print my_function.__doc__

    Function:                my_function

    Description:             1-3 line description of 
                             the function... with an 
                             extra line here... 

    Parameters:
       [in] string $url      The URL for x
       [in] array $arr       An associative array of y
       [in] int $num         The amount of z
       (in) boolean $flag    An optional flag to do k
                             (Default: false)
       (in) string $name     An optional name
                             (Default: "Larry")

    Return Values:           
       interger              -1 if an error occured
                             0 if authentication failed
                             1 on sucess

    Remarks:                 
       None                  
    
>>>
The following elisp allows me to M-x function-template to easily place the above template in a python-mode buffer.
(defvar py-indent-offset 4
  "*Indentation increment in Python mode")

(defun function-template ()
  "creates a template for a function in:  PHP, Perl or Python"
  (interactive)
  (if (eq major-mode 'python-mode)
      (progn 
 (line line-length-default)
 (insert-string "def my_function():\n")))
  (save-excursion 
    (let ((pos (point)))
      (if (eq major-mode 'python-mode)
   (progn 
     (insert-string "\"\"\"\n")
     (insert-string "Function:                my_function\n\n"))
 (progn
   (line-no-comment line-length-default))
   (insert-string "Function:                Class::MyFunction\n\n"))
      (insert-string "Description:             1-3 line description of \n")
      (insert-string "                         the function... with an \n")
      (insert-string "                         extra line here... \n\n")
      ; (insert-string "Type:                    public\n\n")
      (insert-string "Parameters:\n")
      (insert-string "   [in] string $url      The URL for x\n")
      (insert-string "   [in] array $arr       An associative array of y\n")
      (insert-string "   [in] int $num         The amount of z\n")
      (insert-string "   (in) boolean $flag    An optional flag to do k\n")
      (insert-string "                         (Default: false)\n")
      (insert-string "   (in) string $name     An optional name\n")
      (insert-string "                         (Default: \"Larry\")\n")
      (insert-string "\n")
      (insert-string "Return Values:           \n")
      (insert-string "   interger              -1 if an error occured\n")
      (insert-string "                         0 if authentication failed\n")
      (insert-string "                         1 on sucess\n")
      (insert-string "\n")
      (insert-string "Remarks:                 \n")
      (insert-string "   None                  \n")
      (if (eq major-mode 'python-mode)
   (progn
     (insert-string "\"\"\"\n")
     (line (- line-length-default py-indent-offset))
     (insert-string "# first line here\n")
     (indent-rigidly pos (point) py-indent-offset))
 (progn
   (line-no-comment line-length-default)
   (comment-region pos (point))))
      (if (eq major-mode 'php-mode)
   (progn 
     (insert-string "\nfunction MyFunction() {\n")
     (insert-string "\n}\n\n")))
      (if (eq major-mode 'perl-mode)
   (progn 
     (insert-string "\nsub MyFunction {\n")
     (insert-string "  my ($param1, $param2, ..., $paramn) = @_;\n\n")
     (insert-string "\n}\n\n")))
      (if (not (eq major-mode 'python-mode))
   (indent-region pos (point) nil)))))
I've attempted to incorporate my style into conformance with the Python Style Guide and borrowed a little from Tim Peters' improved Emacs Python mode suggestion.

No comments: