Good semantics, Subclass or emulate?
I have been using python for a while now and Im happy using it in most forms but I am wondering which form is more pythonic. Is it right to emulate objects and types or is it better to subclass or inherit from these types. I can see advantages for both and also the disadvantages. Whats the correct method to be doing this?
Subclassing method
class UniqueDict(dict)开发者_如何学Python:
def __init__(self, *args, **kwargs):
dict.__init__(self, *args, **kwargs)
def __setitem__(self, key, value):
if key not in self:
dict.__setitem__(self, key, value)
else:
raise KeyError("Key already exists")
Emulating method
class UniqueDict(object):
def __init__(self, *args, **kwargs):
self.di = dict(*args, **kwargs)
def __setitem__(self, key, value):
if key not in self.di:
self.di[key] = value
else:
raise KeyError("Key already exists")
Key question you have to ask yourself here is:
"How should my class change if the 'parent' class changes?"
Imagine new methods are added to dict
which you don't override in your UniqueDict
. If you want to express that UniqueDict
is simply a small derivation in behaviour from dict
's behaviour, then you'd go with inheritance since you will get changes to the base class automatically. If you want to express that UniqueDict
kinda looks like a dict
but actually isn't, you should go with the 'emulation' mode.
Subclassing is better as you won't have to implement a proxy for every single dict method.
I would go for subclass, and for the reason I would refer to the motivation of PEP 3119:
For example, if asking 'is this object a mutable sequence container?', one can look for a base class of 'list', or one can look for a method named 'getitem'. But note that although these tests may seem obvious, neither of them are correct, as one generates false negatives, and the other false positives.
The generally agreed-upon remedy is to standardize the tests, and group them into a formal arrangement. This is most easily done by associating with each class a set of standard testable properties, either via the inheritance mechanism or some other means. Each test carries with it a set of promises: it contains a promise about the general behavior of the class, and a promise as to what other class methods will be available.
In short, it is sometimes desirable to be able to check for mapping properties using isinstance
.
精彩评论