Here are a few use cases, some more useful than others.
class Baz(object):
"""
I namespace my variables because reasons.
"""
baz_sheep = 'mutton'
baz_cow = 'beef'
baz_pig = 'pork'
def __getattr__(self, name):
return getattr(self, 'baz_%s' % name)
baz = Baz()
print baz.cow # 'beef'
class Foo(dict):
"""
I am some sort of struct-like object.
Usefulness becomes more obvious when nested deeply:
(dict) one['two']['three']['four']['five']['six']
(Foo) one.two.three.four.five.six
..but you can use me either way.
"""
def __getattr__(self, name):
try:
return self[name]
except KeyError:
raise AttributeError(name)
def __setattr__(self, name, value):
self[name] = value
def __delattr__(self, name):
del self[name]
foo = Foo(herp='derp',
hash=dict(frick='frack'),
array=['tweedledee', 'tweedledum'])
print foo.herp # 'derp'
class Bar(Foo):
"""
I'm an encoded struct?
I suppose this is marginally interesting.
"""
def __init__(self, codec, d=None, **kwargs):
"""
:type codec: str
"""
from codecs import lookup
self.__dict__['__codec__'] = lookup(codec)
for k, v in dict(d or dict(), **kwargs).items():
setattr(self, k, v)
@property
def __codec__(self):
return self.__dict__['__codec__']
def __getattr__(self, name):
return self.__codec__.decode(super(Bar, self).__getattr__(name))[0]
def __setattr__(self, name, value):
super(Bar, self).__setattr__(name, self.__codec__.encode(value)[0])
bar = Bar('rot13', beavis='butthead')
print bar.beavis # 'butthead'
print bar['beavis'] # 'ohggurnq'
print bar.__codec__ # <codecs.CodecInfo object for encoding rot-13 at ...>
bar.__codec__ = 'foo'
print bar.__codec__ # <codecs.CodecInfo object for encoding rot-13 at ...>
print bar['__codec__'] # 'sbb'
bar['daria'] = 'morgendorffer'
print bar.daria # 'zbetraqbessre' (oops; it wasn't encoded in the first place!)
The bar.__codec__ = 'foo' is especially weird; it doesn't raise an exception
but feels like it should. Couldn't figure out how to get that to happen; tried
both:
@property
def __codec__(self, value=None):
if value is not None:
raise ValueError()
return self.__dict__['__codec__']
and
@__codec__.setter
def __codec__(self, value):
raise ValueError()
...but neither was triggered with a bar.__codec__ = 'foo'. Anyone know what's
up with that?
Chris
--
Christopher Hiller
Decipher, Inc.
On January 26, 2014 at 3:36:34 PM, Ethan Furman ([email protected]) wrote:
On 01/26/2014 02:04 PM, mark gross wrote:
> On Sun, Jan 26, 2014 at 12:16:37PM -0800, Ethan Furman wrote:
>> On 01/26/2014 12:06 PM, mark gross wrote:
>>>
>>> But, I'd like to ask the pdx-python crew about uses of __getattrib__.
>>
>> There is no __getattrib__ -- there is a __getattr__ and a __getattribute__;
>> which did you mean?
>
> Sorry for the type-oh. I'm talking about __getattr__
Okay, I read your blog entry -- pretty nice!
And yes, __getattr__ is at the tail-end of lookup attempts that Python will
perform when trying to find an attribute on
an object, and yes, you can do juts about anything there. The only thing more
powerful than __getattr__ is
__getattribute__ (because __getattribute__ is *always* called, while
__getattr__ is only called when an attribute cannot
be found).
The most common use for __getattr__ is to allow virtual attributes, and the way
git-python is using it is normal.
Because __getattr__ can be a bit of a nuisance for introspection other
helper-type methods have been added, such as
__dir__ (so git-python could specify in its __dir__ method the various
command-line converters it allowed); also,
descriptors (such as property) are encouraged where appropriate.
--
~Ethan~
_______________________________________________
Portland mailing list
[email protected]
https://mail.python.org/mailman/listinfo/portland
-------------- next part --------------
An HTML attachment was scrubbed...
URL:
<http://mail.python.org/pipermail/portland/attachments/20140126/a5a30a17/attachment.html>
_______________________________________________
Portland mailing list
[email protected]
https://mail.python.org/mailman/listinfo/portland