unpythonic use of property()?

Carl Banks pavlovevidence at gmail.com
Fri Apr 17 22:56:55 CEST 2009


On Apr 17, 10:21 am, J Kenneth King <ja... at agentultra.com> wrote:
> Consider:
>
> code:
> ------------------------------------------------------------------------
>
> class MyInterface(object):
>
>     def __get_id(self):
>         return self.__id
>
>     id = property(fget=__get_id)
>
>     def __init__(self, id, foo):
>         self.__id = id
>         self.foo = foo
>
> class MyInterface2(object):
>
>     def __init__(self, id, foo):
>         self._id = id
>         self.foo = foo
>
>     @property
>     def id(self):
>         return self._id
>
> ------------------------------------------------------------------------
>
> The situation is that an API to an external resource must enforce
> consistency with the resource's expectations of data (ie: ID's must be
> immutable).
>
> The Python docs clearly show the use of the property() decorator in both
> the example classes shown here. Both ensure that an assignment to the
> class objects' 'id' attribute will raise an AttributeError
> exception. Both will satisfy the requirements.
>
> I assume we all know what the implementation differences are between the
> two examples here. What I am curious about is what use case would the
> MyInterface example have? My guess is that it's added protection for
> attribute names on objects generated from factories or generators. I'd
> like a more concrete explanation from someone who has encountered a
> scenario where it was required.

The MyInterface2 version is preferred because it avoids creating an
extra symbol in the class's namespace.  That's pretty much it.

The MyInterface example was how you had to do it before there were
decorators.  It still works, and the world won't end if you do it that
way.  There is not really much practical difference between the two
versions to someone using the class.

Also, the MyInterface version stores its data in a name-mangled
attribute (two underscores), but you can also use a name-mangled
attribute for the MyInterface2 version if you want.

Neither version is foolproof.


> I was recently informed that it was 'unpythonic' and have since been a
> little confused by the term. I've heard it bandied about before but
> never paid much attention. What is 'unpythonic'? What about this example
> is unpythonic?

There are different reasons someone might have said it.

It's probably just for the reason I mentioned.  Python likes to have
an quasi-official way to do basic things such as define properties.
("There should be one--and preferrably only one--obvious way to do
it.")  That current quasi-official way is to use property is as a
decorator, for the reason I gave: it avoids namespace pollution.

Some people think attribute name-mangling is unpythonic.  It's true
that people sometimes mistakenly treat it a solid information hiding
mechanism, but I wouldn't call its usage unpythonic when used as
intended: as a way to avoid name-collisions.  If you think it's
worthwhile to protect an attribute from being overwritten, you might
as well guard against accidental conflict with the underlying name.

Finally, some people think read-only attributes are unpythonic.  I
think that's ridiculous, although in general I'd advise against making
attributes read-only willy-nilly.  But there's a time and place for
it.

Last thing I'll advise is don't get too hung up on terms like
"Pythonic".  Treat such labels are more of a red flag and get people
who throw out the term to explain why.


Carl Banks



More information about the Python-list mailing list