0

In statically typed languages to solve the problem below I would use interface (or abstract class etc.). But I wonder if in python there is more "pythonic" way of doing it.

So, consider the situation:

class MyClass(object):
    # ...
    def my_function(self, value_or_value_provider):
        if is_value_provider(value_or_value_provider):
            self._value_provider = value_or_value_provider
        else:
            self._value_provider = StandardValueProvider(value_or_valie_provider)
            # `StandardValueProvider` just always returns the same value.

Above "value provider" is custom class, which has get_value() method. Of course, the idea is that it can be implemented by the user.

Now, the question is: what is the best way to implement is_value_provider()? I.e., what is the best way to distinguish between "single value" and "value provider"?

The first idea, which came to my mind is to use inheritance: Introduce base class BaseValueProvider with empty implementation and tell in documentation, that custom "value providers" must inherit from it. Then in is_value_provider() function just check isinstance(objectToCheck, BaseValueProvider). What I don't like about this solution is that inheritance seems to be somehow redundant in this case (specifically in case of python), because we cannot even force one, who derive to implement get_value() method. Besides, for someone who wants to implement custom "value provider" this solution implies need to have a dependency on the module, which exposes BaseValueProvider.

The other solution would be to use "trait attribute". I.e. instead of checking base class, check existence of particular attribute with hasattr() function. We can check either existence of get_value() method itself. Or, if we afraid, that the name of the method is too common, we could check for dedicated trait attribute, like is_my_library_value_provider. Then in documentation tell, that any custom "value provider" must have not only get_value() method, but also is_my_library_value_provider. This second solution seems to be better, as it does not abuse inheritance and allows to implement custom "value providers" without being dependent on some additional library, which provides base class.

Could someone comment on which solution is preferable (or if there are other better ones), and why?

EDIT: Change the example slightly to reflect the fact, that value-provider is going to be stored and used later (probably, multiple times).

Dmitrii Semikin
  • 2,134
  • 2
  • 20
  • 25
  • Use the `try`-`except` thing in Python – ssm Feb 03 '16 at 07:56
  • @ssm In this specific context try-except does not work (or I don't see how). In fact, as you can imagine, the value-provider is delayed value generator. This means, that actually I want to store value provider. If I get single value, I will create some standard value provider, which always returns given value. This way I will be sure, that what is stored in my object is value-provider and I do not have to test it every time I use it. – Dmitrii Semikin Feb 03 '16 at 08:07
  • @DmitrySemikin `try`-`except` *does* work: `def is_value_provider(x): try: x.get_value;return True except AttributeError: return False`. Anyway what you call "checking for the trait attribute" seems exactly what is mean by *duck typing*, which is the way in which things are usually done in python. – Bakuriu Feb 03 '16 at 08:09
  • @Bakuriu Ah, ok, indeed. I did not get the idea first. But what if `get_value` is long operation? – Dmitrii Semikin Feb 03 '16 at 08:11
  • 1
    Doing `x.get_value` does **not** execute anything, so it doesn't matter what `get_value` is. It simply looks up the attribute. In fact that code is equivalent to calling `hasattr` with the name `"get_value"`. – Bakuriu Feb 03 '16 at 08:12
  • A simple way to handle this is for `my_function()` to test its argument with the `callable()` built-in function. If the arg is callable, call it to get the value, otherwise use the arg as the value. See [here](http://stackoverflow.com/a/35151536/4014959) for an example I wrote yesterday. – PM 2Ring Feb 03 '16 at 08:17
  • @Bakuriu Now I see... but for me `hasattr` seems to be much more straightforward. One who reads code exactly sees our intension: check if attribute exists... And with `try-except` less experienced pythoner may be confused (like I was)... I thought, that `try-except` idiom should be used when actual call is intended (instead of first checking, if method exists). But when we do not really want to call it... it seem strange for me. But thanks for explaining me the technique. – Dmitrii Semikin Feb 03 '16 at 08:18
  • @PM 2Ring It looks for me to be very similar to using `hasattr(__call__)`. But IMHO, `_call__` is even more common, that `get_value()`. What if the values themselves are callable? Actually, they can even be functions. Or some math objects, or something else... – Dmitrii Semikin Feb 03 '16 at 08:31

1 Answers1

0

I highly suggest using hasattr().

Your code will be highly readable and via ducktyping you can later on make it work with other types you have in mind.

Regarding not getting confused with other objects having the get_value() function, Python idioms assume the coder is a responsible person and won't try to destoy the system he is implementing the code with, therefore a single hasattr(obj, "get_value") is enough. If the class has .get_value() it can be assumed as a value provider and not a value (else, the value is the value itself. .get_value() on a value, returning self is rather useless).

Bharel
  • 23,672
  • 5
  • 40
  • 80
  • Thanks for the answer. I agree. One notice: it may be the case, that the "value" returned by value provider itself may have "get_value" method. Than it becomes hard to distinguish between them. Similar problem shows up, when one tries to distinguish between a collection and single object by checking usability of `len()`. But then get collection of strings... – Dmitrii Semikin May 08 '16 at 08:33