Почему методы ** НЕ **, украшенные `@ abstractmethod`, имеют атрибут` __isabstractmethod__`, который имеет значение True? - PullRequest
0 голосов
/ 26 апреля 2018

Рассмотрим следующий класс :

from abc import abstractmethod

class K:

    @staticmethod
    def sm(*args):
        pass

    @classmethod
    def cm(*args):
        pass

    @abstractmethod
    def am(*args):
        pass

    # instance method
    def im(*args):
        pass

Почему методы, не украшенные @abstractmethod, имеют атрибут __isabstractmethod__, который установлен в True?

Чтобы воспроизвести это, вы можете запустить следующий код:

#  DON'T LET DESCRIPTORS' `__get__` methods be called!
#  USE THE DICT!
K_dct = object.__getattribute__(K, '__dict__')

sm = K_dct['sm']
cm = K_dct['cm']
am = K_dct['am']
im = K_dct['im']

ms = [sm, cm, am, im]

def go_soul_searching(obj):
    """
    :param obj:
    :return: string containing all global labels pointing to `obj`
    """
    g = globals()
    ns = [n for n in g.keys() if g[n] is obj]
    return '{' + ', '.join(ns[0:-1]) + ', ' + ns[-1] + '}'

print_nicely = lambda m, attrname: ''.join([str(x).ljust(25) for x in [
    attrname,
    str(hasattr(m, attrname))
]])

def inspect_method(m):
    header = '\n' + go_soul_searching(m) + '\n'
    print(header, end='')
    for attrname in inspect_method.attrs:
        print(print_nicely(m, attrname))
inspect_method.attrs = ['__call__', '__get__', '__set__', '__isabstractmethod__']

for m in ms:
    inspect_method(m)

Выходные данные:

{sm, m} # STATIC METHOD
__call__                 False                    
__get__                  True                     
__set__                  False                    
__isabstractmethod__     True                     

{cm, m} # CLASS METHOD
__call__                 False                    
__get__                  True                     
__set__                  False                    
__isabstractmethod__     True                     

{am, m} # ABSTRACT METHOD
__call__                 True                     
__get__                  True                     
__set__                  False                    
__isabstractmethod__     True                     

{im, m} # INSTANCE METHOD
__call__                 True                     
__get__                  True                     
__set__                  False                    
__isabstractmethod__     False

1 Ответ

0 голосов
/ 26 апреля 2018

Проще говоря, вы напечатали результат hasattr.Да, у них есть атрибут.Вы не проверяли значение атрибута.

>>> hasattr(cm, '__isabstractmethod__')
True
>>> cm.__isabstractmethod__
False
>>> hasattr(sm, '__isabstractmethod__')
True
>>> sm.__isabstractmethod__
False
...