Давайте предположим, что оригинальная версия что-то вроде этого:
class BitsInteger:
"""BitsInteger docstring"""
def __init__(self, num):
pass
def singleton(cls):
return cls()
def singletonfunction(func):
return func()
@singletonfunction
def Bit():
"""A 1-bit BitField; must be enclosed in a BitStruct"""
return BitsInteger(1)
b = Bit
print("b.__doc__ :", b.__doc__)
Запуск этого с Python3.5 дает выход:
b.__doc_ : BitsInteger docstring
Это не может быть то, что вы ожидаете. Когда мы бежим с python -i original.py
мы можем осмотреться на то, что на самом деле происходит здесь:
>>> vars()
{'__name__': '__main__', '__builtins__': <module 'builtins' (built-in)>, 'b': <__main__.BitsInteger object at 0x7ff05d2ae3c8>, '__spec__': None, 'singletonfunction': <function singletonfunction at 0x7ff05d2b40d0>, 'singleton': <function singleton at 0x7ff05d30cd08>, '__cached__': None, 'BitsInteger': <class '__main__.BitsInteger'>, '__loader__': <_frozen_importlib.SourceFileLoader object at 0x7ff05d2eb4a8>, '__package__': None, 'Bit': <__main__.BitsInteger object at 0x7ff05d2ae3c8>, '__doc__': None}
>>>
Как вы можете видеть b
на самом деле типа BitsInteger
Причина в том, что то, что происходит на самом деле в том, что когда вы пишете:
@singleton_function
def Bit():
"""Bit docstring"""
...
return BitsInteger(1)
вы действительно просто получить синтаксический сахар для этого:
def Bit():
"""Bit docstring"""
...
return BitsInteger(1)
Bit = singleton_function(Bit)
В этом случае Bit
- это возвращаемое значение singleton_function
, которое фактически является BitsInteger
. Я нахожу, когда вы отбрасываете синтаксический сахар, гораздо яснее, что здесь происходит.
Если вы хотели бы иметь удобство декоратора, который не изменяет строку документации, я бы рекомендовал использовать wrapt
import wrapt
class BitsInteger:
"""BitsInteger docstring"""
def __init__(self, num):
pass
def singleton(cls):
return cls()
@wrapt.decorator
def singletonfunction(func):
return func()
@singletonfunction
def Bit():
"""A 1-bit BitField; must be enclosed in a BitStruct"""
return BitsInteger(1)
b = Bit
print("b.__doc_ :", b.__doc__)
Воспроизводит:
b.__doc_ : A 1-bit BitField; must be enclosed in a BitStruct
Теперь, когда вы смотрите на Vars()
вы видите, что 'b': <FunctionWrapper at 0x7f9a9ac42ba8 for function at 0x7f9a9a9e8c80>
, который больше не является BitInteger
. Лично мне нравится использовать wrapt, потому что я получаю то, что хочу немедленно. Реализация этой функциональности и покрытие всех крайних случаев требует усилий, и я знаю, что wrapt хорошо протестирован и работает по назначению.
По существу «бит = битИнтегер (1)». У вас есть опечатка в определении бит, он не возвращает класс, а экземпляр. Хуже того, он, похоже, не работает на PY3, и он не наследует/>> операторов. – ArekBulski
Я запускал это с помощью cPython 3.5. Если вы можете поместить некоторое определение класса «BitsInteger» вместе с тем, что вам нужно достичь в вопросе, это может помочь мне улучшить ответ здесь. Я не совсем понимаю, какова первоначальная проблема, которую вы пытаетесь решить. Вам нужно, чтобы бит был доступен для вызова и всегда возвращал тот же (singleton) объект? – shuttle87
Бит может быть экземпляром класса, который имеет docstring, взятый из функции, а не класса. Вот и все. Я принимаю ваше решение, даже если оно иногда работает. – ArekBulski