Как проверить, реализуется ли __str__ объектом

Я хочу динамически реализовать метод __str__ на объекте, если объект еще не реализовал его.

Я пытаюсь использовать hasattr(obj, '__str__'), он всегда возвращает мне истину, так как берет его из класса объекта.

Есть ли способ определить, действительно ли объект реализует __str__?

Я знаю, что могу использовать inspect.getmembers(obj), но я ищу более питонический способ

EDIT

class Employee(object):
def __init__(self, name, age, emp_code):
    self.name = name
    self.age  = age
    self.emp_code = emp_code

Test

e = Employee("A", 23, "E1")
print hasattr(e, '__str__')
>> True

Я хочу чек, который возвращает False вместо выбора метода, унаследованного от object.

Ответ 1

Так как вы хотите проверить, имеет ли он реализацию __str__, которая не является значением по умолчанию object.__str__. Поэтому вы можете сделать это:

Foo.__str__ is not object.__str__

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

type(f).__str__ is not object.__str__

Это также будет работать, даже если Foo не реализует непосредственно __str__, но унаследовал его от другого класса, чем object, который, кажется, вам нужен.

Ответ 2

Любой объект, наследующий базу object, будет иметь метод __str__, поэтому тестирование, если оно существует, ничтожно.

Вы можете сохранить атрибут флага на объекте и проверить вместо этого:

if not getattr(obj, 'has_str_override_flag'):
    override_str_here(obj)
    setattr(obj, 'has_str_override_flag', True)

Ответ 3

В вашем объекте есть __dict__, который содержит все методы и переменные, которые есть у объекта. Вы можете проверить, есть ли у данного объекта метод __str __(), реализованный

'__str__' in Employee.__dict__

или

'__str__' in vars(Employee)

Между vars() и __dict__ нет разницы, просто vars() более Pythonic.

Ответ 4

Оказывается, что встроенные типы полагаются на object.__str__ для их (умного) форматирования. Я действительно хотел только исключить бесполезные строки, такие как <__main__.Foo object at 0x10299d390>, и по-прежнему правильно печатать dict и другие типы. Мое решение:

objre = re.compile(r"<.* object at 0x[0-9a-f]+>")
if objre.fullmatch(str(obj)):
    # Do smarter formatting

Это не отразит форматирование модулей, функций и т.д. по умолчанию, для которого вместо этого можно было бы показать исходный код через inspect.getsource(), но я все равно не отображаю их в моем инспекторе переменных.

Ответ 5

Используйте type (e).__ dict __. Get (method_name), чтобы избежать KeyError, если method_name не существует в классе при использовании type (e).__ dict __ [method_name]

e = Employee("A", 23, "E1")
if type(e).__dict__.get('__str__'):
    print('__str__ implemented')
else:
    print('__str__ not implemented')