I have a Base
class that stores some basic methods, attributes, etc in it and I've got a Mixin
that I'd like to share across one or more sub-classes of Base
. Something like this:
class Base(object): pass
class Mixin(object):
# IMPORTANT: cache _x locally on Mixin to only compute for all subclasses
_x = None
@property
def x(self):
if self._x is None:
print 'reset _x'
self._x = 2
return self._x
class A(Base, Mixin): pass
class B(Base, Mixin): pass
Importantly, I want to cache the _x
variable on the Mixin
so it is only computed once across all subclasses A
, B
, etc. --- it takes a long time to compute this value. Oddly, this doesn't appear to work as I expected in python:
a = A()
b = B()
print 'calling a.x'
a.x
print 'calling a.x'
a.x
print 'calling b.x'
b.x
print 'calling b.x'
b.x
This prints out reset _x
twice --- once for the first call to ax, which I expected, and again for the first call to bx, which I didn't expect. My understanding of python class attributes was that they are stored once on a per-class basis. Can anyone explain what is going on here?
Are there better patterns for having _x
cached locally on Mixin
?
Your problem is that you're referencing self._x
. This is an instance attribute, ie, it is different for every instance. If you haven't set self._x
then Python uses the first _x
found on classes in the inheritance hierarchy (which will be _x
on your Mixin
class), but as soon as you set self._x
then _x
will always be found on that instance. On a new instance, the attribute won't be set, so Mixin._x
will be used, but it's always None
because you never change it.
So you want to use Mixin._x
everywhere you have self._x
, but especially when setting that attribute.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.