Improved dirty tracking

This builds upon the fix in #34, and only marks an attribute as dirty if it actually changes. I don't see any reason why the library shouldn't work this way, but this could be considered an enhancement, whereas #34 is clearly a bug, so I decided to split them up.