Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #101052

Re: using __getitem()__ correctly

Path csiph.com!fu-berlin.de!uni-berlin.de!not-for-mail
From Oscar Benjamin <oscar.j.benjamin@gmail.com>
Newsgroups comp.lang.python
Subject Re: using __getitem()__ correctly
Date Thu, 31 Dec 2015 12:12:43 +0000
Lines 92
Message-ID <mailman.106.1451563991.11925.python-list@python.org> (permalink)
References <n60kcc$h89$1@dont-email.me> <mailman.70.1451481087.11925.python-list@python.org> <n60qcp$rtp$2@dont-email.me> <mailman.76.1451489799.11925.python-list@python.org> <n612fj$rtp$4@dont-email.me> <mailman.83.1451508086.11925.python-list@python.org> <n61nbh$rtp$5@dont-email.me> <mailman.92.1451517241.11925.python-list@python.org> <56846ddf$0$1601$c3e8da3$5496439d@news.astraweb.com> <mailman.93.1451521331.11925.python-list@python.org> <n633kb$gli$3@dont-email.me>
Mime-Version 1.0
Content-Type text/plain; charset=UTF-8
Content-Transfer-Encoding quoted-printable
X-Trace news.uni-berlin.de qrbpHH9rEyPWtMtCzTjvZA+Oqo28DbNs40w/6EZd3xYw==
Return-Path <oscar.j.benjamin@gmail.com>
X-Original-To python-list@python.org
Delivered-To python-list@mail.python.org
X-Spam-Status OK 0.001
X-Spam-Evidence '*H*': 1.00; '*S*': 0.00; 'failing': 0.05; 'attributes': 0.07; 'cc:addr:python-list': 0.09; "'name':": 0.09; 'dict': 0.09; 'falls': 0.09; 'kwargs': 0.09; 'lookup': 0.09; 'object;': 0.09; 'subclass': 0.09; 'subject:()': 0.09; 'subject:using': 0.09; 'itself.': 0.11; 'syntax': 0.13; 'def': 0.13; '...)': 0.16; 'attributes.': 0.16; 'cc:name:python list': 0.16; 'container.': 0.16; 'distinct': 0.16; 'distinction': 0.16; 'exhausted': 0.16; 'fallback': 0.16; 'received:io': 0.16; 'received:psf.io': 0.16; 'wrote:': 0.16; 'looked': 0.16; 'obviously': 0.16; 'attribute': 0.18; 'mechanism': 0.18; '>>>': 0.20; 'load': 0.20; '2015': 0.20; 'cc:2**0': 0.20; 'cc:addr:python.org': 0.20; 'keys': 0.22; 'referring': 0.22; 'trying': 0.22; 'implemented': 0.24; 'header:In-Reply-To:1': 0.24; "doesn't": 0.26; '(which': 0.26; 'message-id:@mail.gmail.com': 0.27; 'found.': 0.27; 'idea': 0.28; 'dictionary': 0.29; 'objects': 0.29; "i'm": 0.30; 'classes': 0.30; 'checks': 0.30; 'checked': 0.31; "can't": 0.32; 'skip:_ 10': 0.32; 'december': 0.32; 'generally': 0.32; 'class': 0.33; 'problem': 0.33; 'instances': 0.33; 'received:google.com': 0.35; 'could': 0.35; 'i.e.': 0.35; 'important.': 0.35; 'instance': 0.35; 'but': 0.36; 'there': 0.36; 'received:209.85': 0.36; 'possible': 0.36; '(i.e.': 0.36; 'skip:{ 10': 0.36; 'subject:: ': 0.37; 'method': 0.37; 'turn': 0.37; '(with': 0.38; 'associated': 0.38; 'difference': 0.38; 'no,': 0.38; 'virtual': 0.38; 'received:209': 0.38; 'names': 0.38; 'self': 0.38; 'means': 0.39; 'whatever': 0.39; 'does': 0.39; 'skip:x 10': 0.40; 'where': 0.40; 'your': 0.60; 'personally': 0.61; 'back': 0.62; 'different': 0.63; 'complete': 0.63; 'between': 0.65; 'subscript': 0.66; 'wanting': 0.66; 'talking': 0.67; 'skip:\xe2 10': 0.70; '8bit%:43': 0.72; 'covers': 0.72; 'special': 0.73; 'smith': 0.76; "'foo'}": 0.84; 'dict.': 0.84; 'oscar': 0.84; 'syntax;': 0.84
DKIM-Signature v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :cc:content-type:content-transfer-encoding; bh=MItqtCTBzmK8ysk9csNBIMLkwQ02/4ph371x60O/dh8=; b=T0mBvsn5G3SkrbVjSA83amsR/bSfqx6MO/Ssr2XteA/rEyIISXA6Pj87T1xQcnEK9T DqVuxLn8Bi4djDYTS57YJ7zU2ADV4goF7VY4z3wV1IK/8JsyI2qSOzkTh5SUH36uTzKb oa4en9VrISkR7U7AEwNLOwjB3kGjQJ+Ksi0ZbiDNHxFas20ssQX3S8dzOyMJhQgWUcp6 oHfQyf8nK14mTpos9DVwFFJNIMs8E8DSMqO8HCZdXO/mAea8pIVKQ98Ool3zo+KvvU5d lL1z8tcSpvj64l765U2kvI3EiC7MabZqNopdfg+Dqyru5DfSz0bf2Y760DSHMOGIbMjY sriw==
X-Received by 10.112.181.196 with SMTP id dy4mr8386492lbc.42.1451563982918; Thu, 31 Dec 2015 04:13:02 -0800 (PST)
In-Reply-To <n633kb$gli$3@dont-email.me>
X-BeenThere python-list@python.org
X-Mailman-Version 2.1.20+
Precedence list
List-Id General discussion list for the Python programming language <python-list.python.org>
List-Unsubscribe <https://mail.python.org/mailman/options/python-list>, <mailto:python-list-request@python.org?subject=unsubscribe>
List-Archive <http://mail.python.org/pipermail/python-list/>
List-Post <mailto:python-list@python.org>
List-Help <mailto:python-list-request@python.org?subject=help>
List-Subscribe <https://mail.python.org/mailman/listinfo/python-list>, <mailto:python-list-request@python.org?subject=subscribe>
Xref csiph.com comp.lang.python:101052

Show key headers only | View raw


On 31 December 2015 at 11:30, Charles T. Smith
<cts.private.yahoo@gmail.com> wrote:
>>> Obviously there is a syntax difference between x.attr and x['key']
>>
>> Not merely syntax; the attributes of an object are not generally
>> available as items of the container.
>
>
> What are the set of ways that an attribute is accessible?  Including
> implementation implications?
>
>
>>
>>> Either the instance __dict__, the class __dict__, or a superclass
>>> __dict__.
>>
>> No, I'm not referring to the ‘__dict__’ attribute of an object; I'm
>> referring to the object itself.
>>
>> To talk about the attributes of an object ‘foo’ is distinct from talking
>> about the items in a dictionary ‘foo’. That distinction is real, and
>> important.
>
>
> But wanting to deal with the attributes of an object without considering
> the way it's implemented - although possible - requires a complete virtual
> model that covers all implications.  It's easier to simply understand how the
> objects work under the covers.

When you write x.attr the name 'attr' is looked up on the object x.
This calls x.__getattribute__('attr'). In turn this checks the dict
associated with the object x i.e. x.__dict__['attr']. This in turn
calls x.__dict__.__getitem__('attr'). The lookup of x.__dict__ is
special and doesn't use the normal __getattribute__ mechanism
(otherwise this would be an infinite recursion). Generally special
attributes (with double underscores) are looked up in a different way.
If x.__dict__ does not have the attribute then the dict associated
with the class/type of x is checked i.e. x.__class__.__dict__['attr'].
The lookup of x.__class__ is also special. Failing this the other
classes in x.__class__.__mro__ are checked i.e.
x.__class__.__mro__[1].__dict__['attr']. Once these are exhausted
x.__getattribute__('attr') falls back on calling
x.__getattr__('attr').

IIUC you're trying to create an attribute dict where the same
attributes can be looked up via x.attr or x['attr'] (i.e.
x.__getattribute__('attr') or x.__getitem__('attr')). One way to do
this is to subclass dict and then set each instances __dict__ to be
itself. This way __getattribute__ will search the instance (which is a
dict subclass) as its own attribute dict. You can then use __getattr__
as the fallback for attributes that are not found. A simple
implementation of this could look like:

class attrdict(dict):
    def __init__(self, name=None):
        self.__dict__ = self
        kwargs = {'name':name} if name is not None else {}
        super(attrdict, self).__init__(**kwargs)
    def __getattr__(self, attrname):
        ob = self[attrname] = type(self)(name=attrname)
        return ob

>>> d = attrdict('foo')
>>> d
{'name': 'foo'}
>>> d.bar
{'name': 'bar'}
>>> d
{'bar': {'name': 'bar'}, 'name': 'foo'}

The problem with this as with any dict subclass approach is that a
dict has a load of methods (.items() .keys() .pop() ...) that will now
become conflated with your dict keys when you use the attribute
access:

>>> d.items
<built-in method items of attrdict object at 0x7f2025eab868>

This means that you can't use any of the dict method names in whatever
you're doing. This is the reason that a dict uses a different
mechanism __getitem__ so that it can store arbitrary keys at the same
time as having named methods which must be attributes. Personally I
think that the best approach is to ditch the idea of conflating
attributes and keys and just use the subscript x['attr'] syntax.

--
Oscar

Back to comp.lang.python | Previous | NextPrevious in thread | Next in thread | Find similar | Unroll thread


Thread

using __getitem()__ correctly "Charles T. Smith" <cts.private.yahoo@gmail.com> - 2015-12-30 12:57 +0000
  Re: using __getitem()__ correctly Chris Angelico <rosuav@gmail.com> - 2015-12-31 00:11 +1100
    Re: using __getitem()__ correctly "Charles T. Smith" <cts.private.yahoo@gmail.com> - 2015-12-30 14:40 +0000
      Re: using __getitem()__ correctly Ian Kelly <ian.g.kelly@gmail.com> - 2015-12-30 08:35 -0700
        Re: using __getitem()__ correctly "Charles T. Smith" <cts.private.yahoo@gmail.com> - 2015-12-30 16:58 +0000
          Re: using __getitem()__ correctly Ian Kelly <ian.g.kelly@gmail.com> - 2015-12-30 13:40 -0700
            Re: using __getitem()__ correctly "Charles T. Smith" <cts.private.yahoo@gmail.com> - 2015-12-30 22:54 +0000
              Re: using __getitem()__ correctly "Charles T. Smith" <cts.private.yahoo@gmail.com> - 2015-12-30 22:58 +0000
              Re: using __getitem()__ correctly Ben Finney <ben+python@benfinney.id.au> - 2015-12-31 10:13 +1100
                Re: using __getitem()__ correctly "Charles T. Smith" <cts.private.yahoo@gmail.com> - 2015-12-30 23:18 +0000
                Re: using __getitem()__ correctly Steven D'Aprano <steve@pearwood.info> - 2015-12-31 10:50 +1100
                Re: using __getitem()__ correctly Ben Finney <ben+python@benfinney.id.au> - 2015-12-31 11:21 +1100
                Re: using __getitem()__ correctly "Charles T. Smith" <cts.private.yahoo@gmail.com> - 2015-12-31 11:30 +0000
                Re: using __getitem()__ correctly Ben Finney <ben+python@benfinney.id.au> - 2015-12-31 22:51 +1100
                Re: using __getitem()__ correctly Oscar Benjamin <oscar.j.benjamin@gmail.com> - 2015-12-31 12:12 +0000
                Re: using __getitem()__ correctly "Charles T. Smith" <cts.private.yahoo@gmail.com> - 2015-12-31 13:39 +0000
                Re: using __getitem()__ correctly Steven D'Aprano <steve@pearwood.info> - 2016-01-01 02:03 +1100
                Re: using __getitem()__ correctly "Charles T. Smith" <cts.private.yahoo@gmail.com> - 2015-12-31 11:17 +0000
                Re: using __getitem()__ correctly Steven D'Aprano <steve@pearwood.info> - 2016-01-01 01:43 +1100
              Re: using __getitem()__ correctly Ian Kelly <ian.g.kelly@gmail.com> - 2015-12-30 17:31 -0700
                Re: using __getitem()__ correctly "Charles T. Smith" <cts.private.yahoo@gmail.com> - 2015-12-31 12:45 +0000

csiph-web