6

As I am sure you are well aware, python, as do most programming languages, comes with built-in exceptions. I have gone through the list, and cannot deduce which would be appropriate. Of course I can make my own exception, but this is a fairly standard error that would be excepted.

This is an error based on instance relations. Instances of a class are related to only some of the other instances. Computations can be made depending on the different connections. This error will be raised if a computation is attempted on an unrelated instance.

example

class Foo:
    def __init__(self,related=None):
        '''related is a list of Foo instances'''
        if related is not None:
            self.related = related
        else:
            self.related = []
    def compute(self,instance):
        if instance in self.related:
            #execute code
        else:
            raise SomeError("You cannot make a computation with an unrelated instance")

my thoughts

To be honest, it seems like ValueError would make most sense because the value is not allowed, but for some reason this does not fully sit well with me. The fact that there is no relation is the importance of this error, not simply the fact that the value attempted is not allowed.

Is there a better exception than ValueError for my logic?

note: I understand that this ValueError may just be the right answer, but I am curious if there is something more precise that I may have not been able to see the connection with when I went through the documentation.

Ryan Saxe
  • 17,123
  • 23
  • 80
  • 128
  • The answer was in the page you linked, you just had to read it fully :) – UltraInstinct Dec 15 '13 at 18:56
  • @Thrustmaster I did read it fully. I went through the page from top to bottom slowly twice and did not see a "perfect" match. I figured I was missing some logic as to why use that specific error. Could you please explain which one you are referring to. Thanks! – Ryan Saxe Dec 15 '13 at 19:00
  • 6
    Tip: As shown [here](http://stackoverflow.com/questions/1132941/least-astonishment-in-python-the-mutable-default-argument), having `related=[]` in `def __init__(self,related=[])` is just a problem waiting to happen. :) –  Dec 15 '13 at 19:04
  • @iCodez it is not actually a problem in this case and fairly unrelated. I use `related` as a list of instances that are related to the relevant instance. The fact that you can add to related is very important for updating the related instances. As well, I will not run into this issue because I am never actually editing the related parameter as I am saving it in the `related` instance variable. It is simply a default, but changing it to `None` and using an if statement to make a blank list is also a plausible solution. Thanks for the input though, I hope I have clarified the necessity – Ryan Saxe Dec 15 '13 at 19:13
  • @iCodez is right, you should use a default parameter of `None` since the default value is shared between all instances (e.g., adding to that list on one instance will affect all the other instances). – Kevin Stone Dec 15 '13 at 19:14
  • @KevinStone yes defaulting to `None` is probably a better choice since it scrapes error, but the way I have set this up is unlikely to affect `relation` in that way as I make it an instance variable and not a class variable. So adding to the list on one instance will only affect that instance – Ryan Saxe Dec 15 '13 at 19:16
  • @KevinStone @iCodez I have posted some code displaying that in my case that the `related=[]` does not provide an issue, but I changed the code anyways as both results are correct – Ryan Saxe Dec 15 '13 at 19:25
  • Here's a demonstration of the error: https://gist.github.com/kevinastone/db18cd80c61e9584d6e9. The problem is the shared default value for the parameter `[]` which is constructed when the method is defined, not when the method is called. So it becomes shared by all the instances. – Kevin Stone Dec 15 '13 at 19:26
  • And here's the same code fixed by testing the default parameter to ensure the attribute is created for each instance: https://gist.github.com/kevinastone/3eefa976aadc448d8ffe – Kevin Stone Dec 15 '13 at 19:31
  • @KevinStone Alright, then there actually was an issue with that. I figured an instance wouldn't make a difference, but that is correct because it would define it globally. Thank you – Ryan Saxe Dec 15 '13 at 19:47

1 Answers1

6

For me unrelated instance sounds like you want to do something with the instance of wrong type.

What about choosing TypeError?

Raised when an operation or function is applied to an object of inappropriate type. The associated value is a string giving details about the type mismatch.

Source

EDIT based on your comment:

Documentation says:

ValueError Raised when a built-in operation or function receives an argument that has the right type but an inappropriate value, and the situation is not described by a more precise exception such as IndexError.

It is the right type - as you stated in your comment but it has an inappropriate value. Situation can't be described by IndexError => I'd go for ValueError.

Jan Vorcak
  • 19,261
  • 14
  • 54
  • 90
  • an unrelated instance and a related instance are the same `Type`. the issue is that they are not related (as in not in the list `instance.related`). So unfortunately this cannot be the answer. I do consider `TypeError` in my actual code by checking to make sure that the value is of the correct class type since all related instances must be of the same type, there is more to check for. – Ryan Saxe Dec 15 '13 at 18:58
  • fair enough, I guess `ValueError` is the closest I have. I was hoping I had missed something and that there was a sort of relational or contains error – Ryan Saxe Dec 15 '13 at 19:14