[Python-ideas] Simple class initialization

Chris Rebert pyideas at rebertia.com
Sun Apr 17 00:53:50 CEST 2011


On Sat, Apr 16, 2011 at 4:50 AM, Adam Matan <adam at matan.name> wrote:
> 0. Abstract
> ===========
> A class initialization often begins with a long list of explicit variable
> declaration statements at the __init__() method. This repetitively copies
> arguments into local data attributes.
> This article suggests some semi-automatic techniques to shorten and clarify
> this code section. Comments and responses are highly appreciated.
<snip>
> 4. Solutions
> ============
> 4.1 Decorator
> -------------
<snip>
>         class Process:
>             @initializer
>             def __init__(self, pid, ppid, cmd, fd, reachable, user):
<snip>
> 4.2. Argument tagging
> ---------------------
> Arguments that needed to be stored within the instance could be marked with
> a
> special character, e.g. '~'. The character would be placed after the
> argument
> name for private variables:
>         class Process:
>             def __init__(self, ~pid, ~ppid, ~cmd, fd~, ~reachable, ~user)
> Pros:
>     Simple, short and explicit.
>     Can store any subset of the arguments.
>     Supports private variable notation.
> Cons:
>     Not intuitive. Changes the method signature and might be confusing.

You could easily combine 4.1 and 4.2 by using function annotations
(PEP 3107 - http://www.python.org/dev/peps/pep-3107/ ); this would
eliminate the need to add any new syntax. Example:

from wherever import initializer, Private as Priv, Public as Pub
class Process:
    @initializer
    def __init__(self, pid: Pub, ppid: Pub, cmd: Pub, fd: Priv,
reachable: Pub, user: Pub):

> 4.3 Standard function
> ---------------------
> A function will be called to store the argument as data attributes.
>         class Process:
>             def __init__(self, pid, ppid, cmd, fd, reachable, user)
>                 acquire(pid, ppid, cmd, reachable, user)
>                 acquire(fd, prefix='_')
> Possible keywords can ba acquire, store, absorp.
> Pros:
>     Explicit, clear and intuitive.

-1; I strongly disagree. This function would have to be rather magical
since `self` isn't passed to it; it would have to mess with call stack
frames to grab `self` from the caller's scope. I'm unsure whether that
would be resilient in the face of methods which name `self` something
else (e.g. `s`), and whether that would be easily portable to
non-CPython implementations.

> Cons:
>     Long - especially if more than a single prefix is used.
> 4.4 Initialization list
> -----------------------
> The argument list would include the name of the local data attribute, a
> separator, and the argument name.
>         class Process:
>             def __init__(self, pid:pid, ppid:ppid, cmd:cmd, _fd:fd,
> reachable:reachable, user:user)
>             """ pid, ppid, cmd, reachable and user are stored as data
> properties
>                 with the same name. fd is stored as _fd."""
> Or:
>         class Process:
>             def __init__(self, :pid, :ppid, :cmd, _fd:fd, :reachable, :user)
>             """Same, but local data attributes with the same name as
> arguments
>                would be stored without stating their name twice."""
> This is a developed argument tagging (4.2).

Again, I think function annotations would be a better approach here. Example:

class Process:
    @initializer
    def __init__(self, pid: 'pid', ppid: 'ppid', cmd: 'cmd', fd:
'_fd', reachable: 'reachable', user: 'user'):

or allowing for more implicitness:

class Process:
    @initializer
    def __init__(self, pid, ppid, cmd, fd: '_fd', reachable, user):


Cheers,
Chris
--
http://blog.rebertia.com



More information about the Python-ideas mailing list