Dealing with non-callable classmethod objects
Weatherby,Gerard
gweatherby at uchc.edu
Sat Nov 12 13:44:32 EST 2022
Use the inspect module as Cameron suggested.
import inspect
def analyze_class(clzz):
"""Analyze a class proof of concept"""
assert inspect.isclass(clzz)
for k, v in inspect.getmembers(clzz, lambda v: inspect.isfunction(v) or inspect.ismethod(v)):
if inspect.ismethod(v):
print(f"{v.__qualname__} -> class method ")
if inspect.isfunction(v):
sig = inspect.signature(v)
names = [n for n, _ in sig.parameters.items()]
if len(names) > 0 and str(names[0]) == 'self':
print(f"{v.__qualname__}-> probably a bound method ")
else:
print(f"{v.__qualname__}-> probably a static method ")
class Demo:
@classmethod
def us(cls):
print(cls.__name__)
@staticmethod
def double(x):
return x + x
def triple(self, y):
return 3 * y
analyze_class(Demo)
output:
Demo.double-> probably a static method
Demo.triple-> probably a bound method
Demo.us -> class method
From: Python-list <python-list-bounces+gweatherby=uchc.edu at python.org> on behalf of Ian Pilcher <arequipeno at gmail.com>
Date: Saturday, November 12, 2022 at 11:36 AM
To: python-list at python.org <python-list at python.org>
Subject: Re: Dealing with non-callable classmethod objects
*** Attention: This is an external email. Use caution responding, opening attachments or clicking on links. ***
On 11/11/22 16:47, Cameron Simpson wrote:
> On 11Nov2022 15:29, Ian Pilcher <arequipeno at gmail.com> wrote:
>> * Can I improve the 'if callable(factory):' test above? This treats
>> all non-callable objects as classmethods, which is obviously not
>> correct. Ideally, I would check specifically for a classmethod, but
>> there doesn't seem to be any literal against which I could check the
>> factory's type.
>
> Yeah, it does feel a bit touchy feely.
>
> You could see if the `inspect` module tells you more precise things
> about the `factory`.
>
> The other suggestion I have is to put the method name in `_attrs`; if
> that's a `str` you could special case it as a well known type for the
> factory and look it up with `getattr(cls,factory)`.
So I've done this.
class _HasUnboundClassMethod(object):
@classmethod
def _classmethod(cls):
pass # pragma: no cover
_methods = [ _classmethod ]
_ClassMethodType = type(_HasUnboundClassMethod._methods[0])
Which allows me to do this:
def __init__(self, d):
for attr, factory in self._attrs.items():
if callable(factory):
value = factory(d[attr])
else:
assert type(factory) is self._ClassMethodType
value = factory.__func__(type(self), d[attr])
setattr(self, attr, value)
It's a bit cleaner, although I'm not thrilled about having a throwaway
class, just to define a literal that ought to be provided by the
runtime.
--
========================================================================
Google Where SkyNet meets Idiocracy
========================================================================
--
https://urldefense.com/v3/__https://mail.python.org/mailman/listinfo/python-list__;!!Cn_UX_p3!nx6jxVGHt4Gj1WplLAV4uuhaMyS7Ry0qTCGvZm7jLCj9GbK4vto49sfmP12TTgcAT6Akjz5hJWw9JoylO_FrgQ$<https://urldefense.com/v3/__https:/mail.python.org/mailman/listinfo/python-list__;!!Cn_UX_p3!nx6jxVGHt4Gj1WplLAV4uuhaMyS7Ry0qTCGvZm7jLCj9GbK4vto49sfmP12TTgcAT6Akjz5hJWw9JoylO_FrgQ$>
More information about the Python-list
mailing list