Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
OrganizationEventAdvent CalendarQiitadon (β)
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What are the problem?

More than 5 years have passed since last update.

posted at

updated at


ValueObject implementation in Python

I searched for Value object implementation in Python, and found keleshev's implementation in github. But it doesn't provide the feature of immutability of Value object. So, I implemented property based immutable Value object class by myself.

  • explicit property definition
  • value based comparison, including hash

Any feedbacks are welcome.

ValueObject class

class ValueObject(object):
    """ base class for Value Objects

    please call _set_properties in constructor.

    def __new__(class_, *args, **kwargs):
        self = object.__new__(class_, *args, **kwargs)
        self.__initialized = False
        self.__params = dict()
        return self

    def _set_properties(self, mapping):
        if self.__initialized:
            raise AttributeError('callable only by constructor')

        self.__initialized = True
        self.__params = dict(mapping)
        self.__labels = [k for k, v in mapping]

        def setprop(key):
            setattr(self.__class__, key, property(lambda x: x.__params[key]))

        for k, v in mapping:
            if not hasattr(self.__class__, k):

    def get_values(self):
        return self.__params

    def __repr__(self):
        return unicode(self).encode('utf-8')

    def __unicode__(self):
        return u'%s(%s)' % (
            u', '.join(unicode(self.__params[k]) for k in self.__labels))

    def __hash__(self):
        return hash(repr(self))

    def __eq__(self, other):
        if not isinstance(other, self.__class__):
            return False
        return repr(self) == repr(other)

    def __ne__(self, other):
        if not isinstance(other, self.__class__):
            return True
        return repr(self) != repr(other)


# -*- coding: utf-8 -*-
import pytest

from . import ValueObject

class Date(ValueObject):

    def __init__(self, year, month, day):
            ('year', int(year)),
            ('month', int(month)),
            ('day', int(day)),

class Foo(ValueObject):
    def __init__(self, text='foo'):
            ('text', text),

def date():
    return Date(2012, 2, 20)

def foo_unicode():
    return Foo(u'ふー')

def test_properties(date):
    assert date.year == 2012
    assert date.month == 2
    assert date.day == 20

def test_immutable(date):
    with pytest.raises(AttributeError):
        date.year = 2015

def test_set_properties(date):
    with pytest.raises(AttributeError):
            ('year', 2015),

def test_repr(date):
    assert repr(date) == "Date(2012, 2, 20)"

def test_get_values(date):
    date.get_values == {'year': 2012, 'month': 2, 'day': 20}

def test_unicode(foo_unicode):
    assert foo_unicode.text == u'ふー'
    assert unicode(foo_unicode) == u"Foo(ふー)"
    assert repr(foo_unicode) == u"Foo(ふー)".encode('utf-8')


Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Help us understand the problem. What are the problem?