FAQ

On 8/24/2015 12:19 AM, Prof. Dr. L. Humbert wrote:


What students should be able to code:

1. varinat
#-------------wishful----------------------------------\
class Tree:
def __init__(self, left: Tree, right: Tree):
self.left = left
self.right = right

As you should know, at least after reading previous responses, making
this work would require one of two major changes to Python class statements.


1. The class name has special (context sensitive) meaning in enclosed
def statements. The compiler would have to compile def statements
differently than it would the same def statements not in a Tree class.
It would then have to patch all methods after the class is created. See
the annoclass function below.


A proposal to make the definition name of a function special within its
definition has already been rejected.


2. Class statements would initially create an empty class bound to the
class name. This could break back compatibility, and would require
cleanup in case of a syntax error in the body. This would be similar to
import statements initially putting a empty module in sys.modules to
support circular imports. This is messy and still bug prone is use.

what students have to write instead:

#-------------bad workaround----------------------------\
class Tree:
def __init__(self, left: 'Tree', right: 'Tree'):
self.left = left
self.right = right

You did not say why you think this is bad. Is it a) students have to
type "'"s?, or b) the resulting annotations are strings instead of the
class? The latter can easily be fixed.


---
from types import FunctionType


def annofix(klass):
      classname = klass.__name__
      for ob in klass.__dict__.values():
          if type(ob) is FunctionType:
              annotations = ob.__annotations__
              for arg, anno in annotations.items():
                  if anno == classname:
                      annotations[arg] = klass
      return klass


@annofix
class Tree:
      def __init__(self, left: 'Tree', right: 'Tree'):
          self.left = left
          self.right = right


print(Tree.__init__.__annotations__)
# {'left': <class '__main__.Tree'>, 'right': <class '__main__.Tree'>}
---


An alternative is to use a placeholder object instead of the class name.
This is less direct, not repeating the name of the class throughout the
definition makes it easier to rename the class or copy methods to
another class.


---
class Klass: pass
# An annotation object meaning 'the class this method is defined in'


def annofix2(klass):
      for ob in klass.__dict__.values():
          if type(ob) is FunctionType:
              annotations = ob.__annotations__
              for arg, anno in annotations.items():
                  if anno == Klass:
                      annotations[arg] = klass
      return klass


@annofix2
class Tree2:
      def __init__(self, left: Klass, right: Klass):
          self.left = left
          self.right = right


print(Tree2.__init__.__annotations__)
{'right': <class '__main__.Tree2'>, 'left': <class '__main__.Tree2'>}


--
Terry Jan Reedy

Search Discussions

Discussion Posts

Previous

Follow ups

Related Discussions

Discussion Navigation
viewthread | post
posts ‹ prev | 8 of 28 | next ›
Discussion Overview
grouppython-ideas @
categoriespython
postedAug 24, '15 at 4:19a
activeAug 28, '15 at 7:21p
posts28
users10
websitepython.org

People

Translate

site design / logo © 2017 Grokbase