0

It's widely agreed that Python's properties are not merely a kludge for working around the past mistake of exposing of publicly exposing data members. But then when is it not Pythonic to use a property instead of a method that doesn't take any arguments?

For example, if we were writing the Python standard library from scratch, would it be more Pythonic to replace dict.items() with dict.items? We could even add a setter with perfectly intuitive behavior. That feels wrong but I can't articulate rules for what is and isn't a Pythonic use of properties that would disqualify this use. One obvious rule might be that if there's no reasonable setter, then properties shouldn't be used. That disqualifies dict.values() and dict.keys() but not dict.items().

Obviously style can be subjective, but since it's a Python motto that "There should be one -- and preferably only one -- obvious way to do it.", I think this question is reasonable. Also, let's try to stick to the PEPs and code in the Python standard library.

4

This problem is not specific to Python, but is shared by any language with properties, e.g. C#. And since there is only syntactic difference between getters and properties, this is the same question as whether we should use a getter-like method or a normal method.

In general:

  • Prefer properties where you would have otherwise used a getter method.
  • Prefer properties/getters when you are conceptually accessing a property of the object, and not telling the object to do some work. Getters and even more so properties come with the expectation that they are fast, and run in O(1) time.
  • Prefer ordinary methods if you're telling the object to do something, if the operation is expensive, or if you need to supply arguments. (Although for a single argument, a __getitem__-interface can sometimes be appropriate in cases where you would otherwise use a property.)
  • Whether a property is read-only or not is not in itself a good indicator of whether a property or a method would be more idiomatic.

In case of a dictionary, these are often implemented in a way that allows cheap iteration over entries, keys, and values. It would then be feasible to use dict.items, dict.keys properties that return an iterator. This is in fact a big difference between Python 2 and 3: in Python 2, these would all return lists that would have to eagerly traverse all entries, not just return a cheap view object as in Python 3. So it was a sensible design in Python 2 to use methods. In Python 3 this is only a sensible design because of backwards compatibility.

Note that while the “Zen of Python” is a nice goal, it is not a good description for a language that has accumulated a lot of cruft and weird corners over the years. As in all things, you will have to use your own judgement rather than relying on a vague motto.

  • +1 for "As in all things, you will have to use your own judgement rather than relying on a vague motto." – Giorgio Mar 7 '18 at 6:44
1

This question is incredibly subjective, Python's motto be damned, but I think there is a reasonable approach to it:

Use properties when an object should act as-if it contains those members.

Getters are inherently a grey area for encapsulation. They technically encapsulate the data, but they are "supposed" to avoid doing lots of calculations. They're supposed to act as-if they were simply members. If a particular piece of code leaves that grey area, and becomes black and white, then it probably should be either a data member or a function.

In the case of dict.items(), that's a poor place for properties. items() creates a new list of tuples. It doesn't use anything inside the dictionary. For instance, dict.items.append(("foo", "bar")) does not add anything to the dictionary.

As for "There should be one -- and preferably only one -- obvious way to do it," call me heretical, but Python treats that as a guideline, not a rule. Consider string concatenation as an example which surprised Guido in the past.

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.