Is this a good reason to check types in Python?
I know that checking types in Python is bad and you should probably never do it. But I can't seem to find the disadvantage to this.
class O(object):
def __init__(self, name):
'''Can only be called in derived classes.'''
if type(self) is O:
message = "%(class)s cannot be instantiated, it mus开发者_JAVA技巧t be derived."
raise TypeError, message % { "class" : O }
self.name = name
def fn(self):
'''Must be populated in derived classes.'''
raise NotImplementedError
Now if someone tries to instantiate O, a class I never meant to be instantiated, they know immediately.
Is this still bad form?
Look at Abstract Base Classes as they will provide more fine grained control over how the subclasses are instantiated if this is something that you really want to do.
All in all, this might be a valid use because you are not preventing me from passing whatever I want to your code but I still wouldn't consider it pythonic. You are telling me that I can't instantiate your class. What If I want to?
Using ABC's, it looks like:
import abc
class O(object):
__metaclass__ = abc.ABCMeta
def __init__(self, name):
self.name = name
@abc.abstractmethod
def fn(self):
pass
This has the advantage of not breaking super on the fn
method. As you have it with the raise NotImplementedError
, you are breaking super for multiple inheritance. If a class derives from two classes that subclass O
and both call super (as they should to allow for multiple inheritance) then it will create the exception that you raise.
So now, you are not just telling me that I can't instantiate your class, you are telling me that I can't use multiple inheritance when subclassing from your class.
Don't check at all, we're are all adults here. Just add a note that O
shouldn't be instantiated directly, either as a comment and/or in the documentation.
It's the same as if someone would call a method that requires an int
as its parameter with a string
instead. If the program crashes, they screwed it up. Otherwise you would need to add type checks to just about everything.
What is that you are trying to achieve with the above code.
In this case self is of type O and will always result in raising the exception.
Look at this snippet to understand it a little better
class O(object):
def __init__(self, name):
self.name = name
o = O("X")
print type(o)
print isinstance(o, O)
if type(o) is O:
print "Yes"
This will output
<class '__main__.O'>
True
Yes
精彩评论