[issue37203] Correct classmethod emulation in Descriptor HowTo Guide
New submission from Géry
and raises:
TypeError: newfunc() got an unexpected keyword argument 'x'
instead of only printing:
>
like the `@classmethod` decorator would do.
So the `ClassMethod` implementation fails in two regards:
* it does not return a bound method to a class;
* it does not handle keyword-only arguments.
With this PR `ClassMethod` will correctly emulate `classmethod`. This approach (`types.MethodType`) is already used in the Python equivalent `Function` implementation of functions given earlier in the same guide.
----------
assignee: docs@python
components: Documentation
messages: 345031
nosy: docs@python, eric.araujo, ezio.melotti, maggyero, mdk, rhettinger, willingc
priority: normal
pull_requests: 13785
severity: normal
status: open
title: Correct classmethod emulation in Descriptor HowTo Guide
type: behavior
versions: Python 3.7
_______________________________________
Python tracker
Change by Raymond Hettinger
Raymond Hettinger
Géry
Though less accurate, the current version communicates better
I agree that types.MethodType is more accurate but may be less understandable. But in this case I think that the Function class for emulating instance methods should not use types.MethodType either, but a custom newfunc function as well. And **kwargs parameters should be added to both newfunc functions.
----------
_______________________________________
Python tracker
Raymond Hettinger
Géry
The goal in the descriptor how-to is to give an understanding of how descriptors work.
Okay. So I don't know if that was clear in my last message but that also means replacing the current "Function" implementation:
class Function(object):
. . .
def __get__(self, obj, objtype=None):
"Simulate func_descr_get() in Objects/funcobject.c"
if obj is None:
return self
return types.MethodType(self, obj)
with something like this:
class Function(object):
. . .
def __get__(self, obj, objtype=None):
"Simulate func_descr_get() in Objects/funcobject.c"
if obj is None:
return self
def newfunc(*args, **kwargs):
return self(obj, *args, **kwargs)
return newfunc
# "newfunc" emulates "types.MethodType(self, obj)"
And as you said, adding a similar comment to the "ClassMethod" implementation (and **kwargs):
class ClassMethod(object):
"Emulate PyClassMethod_Type() in Objects/funcobject.c"
def __init__(self, f):
self.f = f
def __get__(self, obj, klass=None):
if klass is None:
klass = type(obj)
def newfunc(*args, **kwargs):
return self.f(klass, *args, **kwargs)
return newfunc
# "newfunc" emulates "types.MethodType(self.f, klass)"
----------
_______________________________________
Python tracker
Raymond Hettinger
Change by Géry
Change by Géry
Change by Géry
participants (2)
-
Géry
-
Raymond Hettinger