<div>Two questions: </div><div><br></div><div>1 - is it documented that o.__dict__[attr] is a reliable way to bypass property methods?</div><div>2 - can one bypass a property method if the class has __slots__?</div><div><br>
</div>Reason: I have a couple of different flavors of request objects which I need to make lazily conform to a standard interface. As a simplified example,<div><br></div><blockquote class="webkit-indent-blockquote" style="margin: 0 0 0 40px; border: none; padding: 0px;">
<div><font class="Apple-style-span" face="'courier new', monospace">a_foo_request = { 'ip': '1.2.3.4' }</font></div><div><font class="Apple-style-span" face="'courier new', monospace">a_bar_request = { 'my-ip': b'\x01\x02\x03\x04' }</font></div>
</blockquote><div><br></div><div>My solution is to create two classes:</div><div><br></div><blockquote class="webkit-indent-blockquote" style="margin: 0 0 0 40px; border: none; padding: 0px;"><div><div><font class="Apple-style-span" face="'courier new', monospace">class FooRequest(dict):</font></div>
</div><div><div><font class="Apple-style-span" face="'courier new', monospace"> @property</font></div></div><div><div><font class="Apple-style-span" face="'courier new', monospace"> def ip(self):</font></div>
</div><div><div><font class="Apple-style-span" face="'courier new', monospace"> return self['ip']</font></div></div><div><div><font class="Apple-style-span" face="'courier new', monospace"><br>
</font></div></div><div><div><font class="Apple-style-span" face="'courier new', monospace">class BarRequest(dict):</font></div></div><div><div><font class="Apple-style-span" face="'courier new', monospace"> @property</font></div>
</div><div><div><font class="Apple-style-span" face="'courier new', monospace"> def ip(self):</font></div></div><div><div><font class="Apple-style-span" face="'courier new', monospace"> return "%i.%i.%i.%i" % struct.unpack("4B", self['my-ip'])</font></div>
</div></blockquote><div><div><br></div><div>Then:</div><div><br></div><div><blockquote class="webkit-indent-blockquote" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 40px; border-top-style: none; border-right-style: none; border-bottom-style: none; border-left-style: none; border-width: initial; border-color: initial; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">
<div><div><span class="Apple-style-span" style="font-family: 'courier new', monospace; ">FooRequest(a_foo_request).ip == '1.2.3.4'</span></div></div></blockquote><div></div></div></div><blockquote class="webkit-indent-blockquote" style="margin: 0 0 0 40px; border: none; padding: 0px;">
<div><div><font class="Apple-style-span" face="'courier new', monospace"># and</font></div><div><font class="Apple-style-span" face="'courier new', monospace">req = BarRequest(a_bar_request)</font></div><div>
<font class="Apple-style-span" face="'courier new', monospace">req.ip == '1.2.3.4'</font></div><div><font class="Apple-style-span" face="'courier new', monospace"><br></font></div></div></blockquote>
<div><div>But some of these getters are CPU-intensive, and since the extended objects always remain immutable, I memoize them in req.__dict__, like:</div></div><div><div><div><br></div></div></div><blockquote class="webkit-indent-blockquote" style="margin: 0 0 0 40px; border: none; padding: 0px;">
<div><div><div><div><font class="Apple-style-span" face="'courier new', monospace">class BarRequest(dict):</font></div></div></div></div><div><div><div><div><font class="Apple-style-span" face="'courier new', monospace"> @property</font></div>
</div></div></div><div><div><div><div><font class="Apple-style-span" face="'courier new', monospace"> def ip(self):</font></div></div></div></div><div><div><div><div><font class="Apple-style-span" face="'courier new', monospace"> if 'ip' in self.__dict__:</font></div>
</div></div></div><div><div><div><div><font class="Apple-style-span" face="'courier new', monospace"> return self.__dict__['ip']</font></div></div></div></div><div><div><div><div><font class="Apple-style-span" face="'courier new', monospace"> else:</font></div>
</div></div></div><div><div><div><div><span class="Apple-style-span" style="font-family: 'courier new', monospace; "> self.__dict__['ip'] = "%i.%i.%i.%i" % struct.unpack("4B", self['my-ip'])</span></div>
</div></div></div><div><div><div><div><font class="Apple-style-span" face="'courier new', monospace"> return self.__dict__['ip']</font></div></div></div></div></blockquote><div><div><div><div><br>
</div><div>Which works as intended, and (I think) can be made prettier with a custom constant_property decorator. So...</div><div><br></div><div>Question 0: Is there an obvious better way of achieving this functionality?</div>
<div>Question 1: Is it safe to rely on __dict__ to bypass properties this way?</div><div>Question 2: I'd like to use __slots__, but I can't seem to find a way to stop the property method from recursing. Is there one?</div>
<div><br></div><div><div>Cheers,</div><div>Andrey</div><div><br></div></div></div></div></div>