1

I recently started using UtilSnips, a Vim plugin allowing for a certain level of automation while coding by using template-like code snippets for common code fragments (class and function definitions, for example).

When using a popular snippet pack with Python, I noticed that snippets used when writing a class use a pattern I've never seen before in __init__ when using more arguments than just self:

class MyClass(object):

    """Docstring for MyClass. """

    def __init__(self, user, password):
        """TODO: to be defined.

        :user: TODO
        :password: TODO

        """
        self._user = user  # this is the pattern I'm unfamiliar with
        self._password = password

Is it common (or good) practice to use underscore when assigning instance variables in a constructor for a class in Python, or is this likely just the snippet pack author's preference? I haven't seen this type of naming convention in any other Python code I've interacted with.

  • 4
    See PEP 8: one leading underscore marks a field as private by convention, though it does not actually hide the field. – amon Feb 11 '16 at 15:11
2

Leading Underscores

A leading underscore means "hands off" to the user, though an advanced user may expect to use it in certain circumstances, such as when subclassing your object.

Usage demonstration with property decorator

We tend to use underscores when using a property, for example:

class MyClass(object):
    def __init__(self, user, password):
        self._user = user
        self._password = password
    @property
    def user(self):
        return self._user
    # The rest are optional - leaving off has same behavior
    # but this demonstrates usage.
    @user.setter
    def user(self, value):
        """optional, raise a custom AttributeError message"""
        raise AttributeError('do not attempt to modify user member')
    @user.deleter
    def user(self):
        """optional, raise a custom AttributeError message"""
        raise AttributeError('do not attempt to modify user member')

So one using your code can create the object, but when attempting to modify the attribute they get a warning telling them hands off, for which you ostensibly have a good reason:

>>> mc = MyClass('foo', 'bar')
>>> mc.user = 'huh?'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 10, in user
AttributeError: do not attempt to modify user member
>>> del mc.user
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 13, in user
AttributeError: do not attempt to modify user member

Without our optional setter and deleter methods we get a more generic error message:

>>> mc.user = 'huh?'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: can't set attribute
>>> del mc.user
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: can't delete attribute

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.