[Edu-sig] what is 'self'? (plus link to Trey's article on callability)

Wes Turner wes.turner at gmail.com
Tue Apr 16 15:44:44 EDT 2019


Or ``a.__get__('x')`` ?

On Tuesday, April 16, 2019, Wes Turner <wes.turner at gmail.com> wrote:

> > Direct Call
> The simplest and least common call is when user code directly invokes a
> descriptor method: x.__get__(a).
>
> Should this be `a.__get__(x)`?
>
> On Tuesday, April 16, 2019, Wes Turner <wes.turner at gmail.com> wrote:
>
>> When you access an attribute of a class object (a dict), the class
>> attribute is looked up by __get__().
>> the class's instance of that function attribute is 'bound'; it receives
>> 'self' (an object reference) as its first argument.
>>
>> If you write your own __get__ (e.g. with functools.partial or
>> functools.wrap),
>> or try and assign a function to a class [instance],
>> or create a @staticmethod or a @classmethod,
>> you can more fully understand how methods receive self as their first
>> argument.
>>
>> - https://docs.python.org/3/howto/descriptor.html#functions-and-methods
>> - https://python-reference.readthedocs.io/en/latest/docs/dunderdsc/ :
>>
>> """
>> Descriptor Protocol
>> In general, a descriptor is an object attribute with “binding behavior”,
>> one whose attribute access has been overridden by methods in the descriptor
>> protocol: __get__(), __set__(), and __delete__(). If any of those methods
>> are defined for an object, it is said to be a descriptor.
>>
>> The default behavior for attribute access is to get, set, or delete the
>> attribute from an object’s dictionary. For instance, a.x has a lookup chain
>> starting with a.__dict__[‘x’], then type(a).__dict__[‘x’], and continuing
>> through the base classes of type(a) excluding metaclasses.
>>
>> However, if the looked-up value is an object defining one of the
>> descriptor methods, then Python may override the default behavior and
>> invoke the descriptor method instead. Where this occurs in the precedence
>> chain depends on which descriptor methods were defined and how they were
>> called. Note that descriptors are only invoked for new style objects or
>> classes (ones that subclass object() or type()).
>>
>> The starting point for descriptor invocation is a binding, a.x. How the
>> arguments are assembled depends on a:
>>
>> Direct Call
>> The simplest and least common call is when user code directly invokes a
>> descriptor method: x.__get__(a).
>>
>> Instance Binding
>> If binding to a new-style object instance, a.x is transformed into the
>> call: type(a).__dict__[‘x’].__get__(a, type(a)).
>>
>> Class Binding
>> If binding to a new-style class, A.x is transformed into the call:
>> A.__dict__[‘x’].__get__(None, A).
>>
>> Super Binding
>> If a is an instance of super, then the binding super(B, obj).m() searches
>> obj.__class__.__mro__ for the base class A immediately preceding B and then
>> invokes the descriptor with the call: A.__dict__[‘m’].__get__(obj,
>> obj.__class__).
>> """
>>
>>
>> On Tuesday, April 16, 2019, kirby urner <kirby.urner at gmail.com> wrote:
>>
>>>
>>> If we're ever at a loss for what to talk about, in this context, of
>>> Python teachers, I could recommend a list of default topics, one of which
>>> would always be...
>>>
>>> What is this 'self'?
>>>
>>> The self appears right when we introduce the class construct (keyword
>>> class).  And then we say things like "Python provides it" or "Python fills
>>> it in".  What is "it" then?  "It" is "the instance".  For some, things are
>>> starting to get muddy.
>>>
>>> For coders familiar with OOP style grammars i.e. they're coming from
>>> another language such as JavaScript or Java (quite different I realize),
>>> they've got a sense of it, from keyword 'this'.
>>>
>>> However Python is widely touted as a gateway language into OOP style
>>> thinking, so we get a lot of first timers.  We owe them a clear picture of
>>> self.
>>>
>>> One andragogical technique comes straight from the docs:
>>>
>>> instance = C()
>>> C.method(instance)   # <-- needs instance as argument
>>>
>>> is equivalent to:
>>>
>>> instance = C()
>>> instance.method()  # <-- instance is "subject" as in subject.verb()
>>>
>>> ... of course we may add additional arguments at will, but lets keep it
>>> simple.
>>>
>>> In OOP, all the selves share the same template or class code, so how is
>>> Python to distinguish one self from another?
>>>
>>> It's not like each self is carrying around a copy of the method code.
>>> The model is more like having DNA in common (a shared genetic core).
>>>
>>> As in:
>>>
>>> class Creature:
>>>
>>>     def eat(self, food):  # <--- needs to know which self
>>>         self.stomach.append(food)
>>>
>>> With:
>>>
>>> instance.eat("spaghetti")  # <-- self known to Python
>>>
>>> we have enough info to figure out which self, and Python obligingly
>>> brings it forward, to fill the placeholder, usually 'self'.
>>>
>>> With:
>>>
>>> Creature.eat(instance, "spaghetti")  # self supplied by the caller
>>>
>>> we're not giving enough distinguishing information with generic
>>> Creature, and so instance has to be provided, as the self.
>>>
>>> Further andragogical elaboration involves showing what I mean by
>>> "usually 'self'" i.e. self is not a keyword but a placeholder.
>>>
>>> Here I tend to go for a Chinese character substitute, e.g. for "Ego", to
>>> remind the learner of Unicode in addition.  Emoji can't be Python names or
>>> I might go for one of them.
>>>
>>>         *            *            *
>>>
>>> Another good article by Trey Hunner just came out.  He's one of the more
>>> prolific Python teachers *that I know about* (an important caveat as I'm
>>> always missing *a lot*):
>>>
>>> https://treyhunner.com/2019/04/is-it-a-class-or-a-function-i
>>> ts-a-callable/
>>>
>>> He takes up the issue of "callables that are functions" versus
>>> "callables that are actually types (classes)".
>>>
>>> That can help with fine tuning one's sense of what a "type" is, plus
>>> callability in general is a bridge to decorators, and this article
>>> definitely goes there.
>>>
>>> Kirby
>>>
>>>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/edu-sig/attachments/20190416/f88577c9/attachment-0001.html>


More information about the Edu-sig mailing list