-
Notifications
You must be signed in to change notification settings - Fork 167
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
PR: use single inheritance #677
Conversation
These remarks are a reply to a discussion started in PR #675. They apply equally to this PR. @lieryan said: AbstractFunction classes defines the interface for what it means to be a function, it just provides a default implementation so that subclasses don't have to implement anything if it doesn't need to implement something, ditto with the others. Defining empty interface immediately screams that something is wrong with the new version of Abstract classes. The three
getattr(obj, "type_", None) == "Function" Summary
|
@lieryan A word about workflow: I prefer to use "good enough" PRs. This speeds development. I would much rather tweak code in later PRs than wait for perfection. |
@lieryan Afaik # Super Works with known inheritance.
class A:
def __init__(self, a):
print('A1', a)
super().__init__()
print('A2')
class B(A):
def __init__(self, a, b):
print('B1', b)
super().__init__(a)
print('B2')
class C(B):
def __init__(self):
print('C1')
super().__init__('a', 'b')
print('C2')
C()
print('-----')
# super() does not work with mixins.
class E:
def __init__(self, e):
print('E', e)
class F:
def __init__(self, f):
print('F', f)
class G(E, F):
def __init__(self):
print('G')
E.__init__(self, 'e')
F.__init__(self, 'f')
G() The output is: C1
B1 b
A1 a
A2
B2
C2
-----
G
E e
F f I know of no way to use |
super() works fine with mixins, it will just follows the MRO of the actual runtime type rather than the lexical type, that is how super() is designed to work. When a class uses
Your second example violates a number of those rules, so that's why it's not working correctly. Combined together, the correct usage of class E:
def __init__(self, e, *args, **kwargs):
print('E', e)
super().__init__(*args, **kwargs)
class F:
def __init__(self, f, *args, **kwargs):
print('F', f)
super().__init__(*args, **kwargs)
class G(E, F):
def __init__(self, *args, **kwargs):
print('G')
super().__init__('e', 'f', *args, **kwargs)
# output:
# G
# E e
# F f Raymond Hettinger's "Python's super() considered super()!" is an old article, but it is still one of the best article describing the practical use of |
@lieryan Thanks for these comments about super.
Single inheritance sidesteps the need for "cooperation". Everything just works. |
@lieryan I wonder whether (in this branch) the annotation |
@lieryan The only difference is that the In other words, Rope already uses an empty target class. I'll add a docstring to Update: Done at rev b8ec122. |
@lieryan The following test file passes mypy: """Is there any advantage to using Union[A, B] if B is a subclass of A?"""
from typing import Union
class A:
def __init__(self, a):
self.a: int = a
class B(A):
def __init__(self, a, b):
super().__init__(a)
self.b: float = b
a1 = A(1)
a2: A = A(2)
a3: Union[A, B] = A(3) # Dubious annotation.
b1 = B(4, 1.0)
b2: B = B(5, 5.0)
b3: Union[A, B] = B(6, 6.0)
b4: A = B(7, 7.0) # Dubious annotation. My (tentative) takeaway is that mypy does not force us to be a specific as possible:
|
This PR is based on PR #664, but it retains all tests of the form
isinstance(obj, AbstractX)
.Differences from PR 664
is_abstract_*
predicates.664 shows that these predicates do work, but for this PR I wanted to minimize the changed files.
Abstract
classes as empty classes.Alas, circular imports prevented using tuples as proxies for the
Abstract
classes._BuiltinElement
as a subclass ofpo.PyObject
.pyobjects.PyObject
as an explicit base class wherever anAbstract
class appeared.@staticmethod
with a function.Abstract
classes.Discussion
This PR shows that:
builtins.py
,pyobjects.py
andpyobjectsdef
is straightforward.PyDefinedObject
is now a subclass ofpo.PyObject
. This change simplifies annotations.po.PyObject
!Abstract
classes were faux helpers:The revised ctors all use
super().__init__
. As a result, the ctors are easier to understand.Abstract
classes have only one function: to tag various classes.The
Abstract
classes now have docstrings explaining why they exist.