Не можете украсить стороннюю функцию только для чтения, как обернуть ее для дополнительной функциональности? - PullRequest
0 голосов
/ 29 марта 2019

У меня есть следующий (сильно упрощенный) декоратор:

def log_and_execute(func):
    def wrapper(*args, **kwargs):
        print(*args, **kwargs)
        return func(*args, **kwargs)
    return wrapper

Я хочу использовать это для украшения pyodbc.connect.cursor.

Поскольку я, очевидно, не могу отредактировать исходный код, чтобы сделать это, я пытаюсь сделать это так:

import pyodbc

connection = pyodbc.connect("connection_string_here")
cursor = connection.cursor()

cursor.execute = log_and_execute(cursor.execute)

Но я получаю следующую ошибку:

AttributeError: 'pyodbc.Cursor' object attribute 'execute' is read-only

Как мне это сделать, чтобы мне не пришлось менять все мои уже существующие cursor.execute звонки?

1 Ответ

2 голосов
/ 29 марта 2019

Вы не можете изменить класс pyodbc Cursor, он написан на C и не позволяет устанавливать атрибуты.

В лучшем случае вы можете написать класс-оболочку:

class CursorWrapper:
    def __init__(self, cursor):
        self.cursor = cursor

    def execute(self, *args, **kwargs):
        print(*args, **kwargs)
        return self.cursor.execute(*args, **kwargs)

    def __getattr__(self, attr):
        return getattr(self.cursor, attr)

    def __iter__(self):
        return iter(self.cursor)

    def __enter__(self):
        return self.cursor.__enter__()

    def __exit__(self, *args, **kwargs):
        return self.cursor.__exit__(*args, **kwargs)

затем каждый раз оборачивайте курсор в этот класс:

cursor = CursorWrapper(connection.cursor())
...