Path: csiph.com!fu-berlin.de!uni-berlin.de!not-for-mail From: Ian Kelly Newsgroups: comp.lang.python Subject: Re: Descriptor: class name precedence over instance name Date: Sat, 2 Jul 2016 07:55:02 -0600 Lines: 69 Message-ID: References: <85shvstze5.fsf@benfinney.id.au> Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 X-Trace: news.uni-berlin.de raigJ+T6ZNFt8NbEynJN+gYe/TVj4bFWMA8Ybo34gAoA== Return-Path: 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; 'essentially': 0.04; 'append': 0.07; 'method,': 0.07; 'descr': 0.09; 'descriptor': 0.09; 'dict': 0.09; 'hiding': 0.09; 'lookup': 0.09; 'loop.': 0.09; 'name)': 0.09; 'precedence': 0.09; "hasn't": 0.15; 'skip:f 30': 0.15; '*any*': 0.16; '2016': 0.16; 'attribute,': 0.16; 'clarified': 0.16; 'descriptor.': 0.16; 'foo()': 0.16; 'reason.': 0.16; 'received:io': 0.16; 'received:psf.io': 0.16; 'skip:n 50': 0.16; 'subject:class': 0.16; 'subject:instance': 0.16; 'used:': 0.16; 'wrote:': 0.16; 'attribute': 0.18; 'basically': 0.18; 'algorithm': 0.20; 'class,': 0.22; 'am,': 0.23; 'bit': 0.23; 'sat,': 0.23; 'this:': 0.23; 'tried': 0.24; 'thus': 0.24; 'header :In-Reply-To:1': 0.24; 'example': 0.26; 'order.': 0.27; 'message- id:@mail.gmail.com': 0.27; 'actual': 0.28; 'declared': 0.29; 'searches': 0.29; 'raise': 0.29; "i'm": 0.30; 'skip:- 30': 0.32; 'skip:_ 10': 0.32; 'class': 0.33; 'url:python': 0.33; 'foo': 0.33; 'null': 0.33; "i'll": 0.33; 'skip:d 20': 0.34; 'received:google.com': 0.35; 'done': 0.35; 'instance': 0.35; 'according': 0.36; 'but': 0.36; 'skip:i 20': 0.36; 'should': 0.36; 'instead': 0.36; 'there': 0.36; 'url:org': 0.36; 'to:addr:python- list': 0.36; 'subject:: ': 0.37; 'thanks': 0.37; 'sure': 0.39; 'whatever': 0.39; 'does': 0.39; 'takes': 0.39; 'to:addr:python.org': 0.40; 'avoid': 0.61; 'back': 0.62; 'skip:n 10': 0.62; 'here:': 0.63; 'between': 0.65; 'said:': 0.66; 'therefore': 0.67; 'answer.': 0.72; 'jul': 0.72; 'as:': 0.79; 'gain': 0.82; 'eg:': 0.84; 'ian,': 0.84; 'subject:over': 0.84; 'to:name:python': 0.84; 'url:cpython': 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; bh=K3CU3PRUygDZ0DT72V2gqTtHanmPmieEzv3EbmrjioM=; b=L9s2TF/gESpnDju2XEdPHgdox/P6C+lLSPvUum2ofBGou4LWS2BOnKK+sUk/5QuA0C KI7kuDvWy6v0gRBaA91/ZMoH41k+k2DrXHDIoqAAkaMmEZIDBNFJxnWCHZ+gGqXQqudE LysyDdISs20e8BuNDS/xoO5xN+WvDt0RoDK7kt6NTknAiSqDu3XTC99RaPVOa8xVVP8D n6rJySnSV/jendUvfN1I0BDbV0sB7qhXgk9jViQosBsiNgjyEuJDBBHDi0ovqQXEe9B2 XZLOfL4a6FSFKsKZQ/b2Zq6eOI9xwq1XPxTp8qkGCKCGOo2FnPRYHjWr1UWCCMoTfa2j RqjA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:in-reply-to:references:from:date :message-id:subject:to; bh=K3CU3PRUygDZ0DT72V2gqTtHanmPmieEzv3EbmrjioM=; b=cIZZIUUBEzMZEenOh6NGw6e5WbSuIR2wVh4HDVzFoRI1tyfY6FF/m5TOHWV+W6rj5E n194byT6jx3fjFu+T29hJV39ERQ/ppJ2P1V+k1tmG3N4zWKX/ZwY0QMqdK8ZVzPyid9A WUgG45/VSZ0d79OfUg8gPMvIgk7GZ4VShZ3mLxE07JaZprrQLA/GdLS2YuIDJh6fgOT2 VcvufFcuoJYo60tDbtcGmLoaH/fxM0XrqWjMqnW81JuWmcMfXN/5O0tzQpDaHzi9HDsq xcL14kAHTLnhmXgRMHL1FWVJvUgJZecvU8UyyePFazhVKXT70rAaE809v6LM7m8hoCgp /RPg== X-Gm-Message-State: ALyK8tJMzuieK/Va8pL7nE80udkCq5UwPpnIa6K3AaXiUWlCU0SyBEouDjq4l+viFfm7Av958qnAVJhv6EgHVA== X-Received: by 10.202.231.83 with SMTP id e80mr1894617oih.159.1467467741452; Sat, 02 Jul 2016 06:55:41 -0700 (PDT) In-Reply-To: X-BeenThere: python-list@python.org X-Mailman-Version: 2.1.22 Precedence: list List-Id: General discussion list for the Python programming language List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Mailman-Original-Message-ID: X-Mailman-Original-References: <85shvstze5.fsf@benfinney.id.au> Xref: csiph.com comp.lang.python:110958 On Sat, Jul 2, 2016 at 3:34 AM, Veek. M wrote: > So essentially from what Ian said: > data_descriptor_in_instance -> instance_attribute -> non- > data_descriptor_in_instance -->__mro__ > > is how the search takes place. Correct? Close, but I would write it as: data_descriptor_in_class_including_mro -> instance_attribute -> non_data_descriptor_or_class_attribute_including_mro In either case the class dict search is in __mro__ order. You can find the actual implementation here: https://hg.python.org/cpython/file/30099abdb3a4/Objects/object.c#l1326 Roughly, the algorithm is this: tp = type(obj) # This call searches the MRO. descr = _PyType_Lookup(tp, name) if descr != NULL and is_data_descriptor(descr): return descr.__get__(obj, tp) if name in obj.__dict__: return obj.__dict__[name] if descr != NULL and is_non_data_descriptor(descr): return descr.__get__(obj, tp) if descr != NULL: return descr raise AttributeError(name) > ------------------------------ > > Regarding part2 of the Q, :) Ian hasn't explained it, so I'm not sure > how to explain it better :) but i'll try given that he has clarified > part of the answer. > > Basically Beazley has a TypedProperty descriptor class, and in class Foo > he instantiates: > name = TypedProperty > Then he does f = Foo() > > Thanks to Ian, we now know that any lookup on 'f' eg: f.name would Not *any* lookup, only one for which there is a declared descriptor. So in this example f.name or f.num would resolve according to the descriptor's __get__ method, but any other attribute lookup would just return whatever value is set on the instance (if any). > cause.. well.. the f.name(TypedProperty-descriptor) to gain precedence > thus hiding the f.name attribute! Therefore he needs to name-decorate or > in this example append an '_' for whatever stupid reason. Right, if the "name" descriptor tried to store the value in the unmangled "name" instance attribute, then its getattr call would just recur back to the descriptor and you'd have an infinite loop. In my opinion the mangling should be a bit heavier than what's done in this example, to avoid collisions between the descriptor and the class that's using it. I like to follow the pattern of __foo name mangling, so I would have instead used: self.name = "_TypedProperty__" + name