Helpex - Trao đổi & giúp đỡ Đăng nhập
22

Tôi đang lập trình bằng Python và tôi đang tự hỏi liệu tôi có thể kiểm tra xem một hàm đã được gọi trong mã của mình hay chưa

def example():
    pass
example()
#Pseudocode:
if example.has_been_called:
   print("foo bar")

Làm thế nào tôi sẽ làm điều này?

22 hữu ích 2 bình luận 23k xem chia sẻ
32

Nếu hàm biết tên riêng của nó, bạn có thể sử dụng thuộc tính hàm:

def example():
    example.has_been_called = True
    pass
example.has_been_called = False


example()

#Actual Code!:
if example.has_been_called:
   print("foo bar")

Bạn cũng có thể sử dụng trình trang trí để đặt thuộc tính:

import functools

def trackcalls(func):
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        wrapper.has_been_called = True
        return func(*args, **kwargs)
    wrapper.has_been_called = False
    return wrapper

@trackcalls
def example():
    pass


example()

#Actual Code!:
if example.has_been_called:
   print("foo bar")
32 hữu ích 3 bình luận chia sẻ
2

Chúng ta có thể sử dụng mock.Mock

from unittest import mock


def check_called(func):
    return mock.Mock(side_effect=func)


@check_called
def summator(a, b):
    print(a + b)


summator(1, 3)
summator.assert_called()
assert summator.called == True
assert summator.call_count > 0

summator.assert_called_with(1, 3)

summator.assert_called_with(1, 5)  # error
# AssertionError: Expected call: mock(1, 5)
# Actual call: mock(1, 3)
2 hữu ích 0 bình luận chia sẻ
1

Các chức năng ghi nhớ đã có từ những năm 1960. Trong python, bạn có thể sử dụng chúng làm trình trang trí trên hàm example () của mình .

Chức năng ghi nhớ tiêu chuẩn trông giống như sau:

def memoize(func):
    memo = {}
    def wrapper(*args):
        if not args in memo:
            memo[args] = func(*args)
        return memo[args]
    return wrapper 

và bạn trang trí chức năng của mình như thế này:

@memoize
def example():
    pass

Trong python3.2, bạn có thể sử dụng functools.lru_cache thay vì hàm ghi nhớ.

import functools

@functools.lru_cache(maxsize=None)
def example():
     pass
1 hữu ích 0 bình luận chia sẻ
0

Đây là một trình trang trí sẽ xem tất cả các chức năng của bạn, sử dụng màu sắc và trả về một kết quả đẹp.

try:
    import colorama
except ImportError:
    class StdClass: pass
    def passer(*args, **kwargs): pass
    colorama = StdClass()
    colorama.init = passer
    colorama.Fore = StdClass()
    colorama.Fore.RED = colorama.Fore.GREEN = ''

def check_for_use(show=False):
    if show:
        try:
            check_for_use.functions
        except AttributeError:
            return
        no_error = True
        for function in check_for_use.functions.keys():
            if check_for_use.functions[function][0] is False:
                print(colorama.Fore.RED + 'The function {!r} hasn\'t been called. Defined in "{}" '.format(function, check_for_use.functions[function][1].__code__.co_filename))
                no_error = False
        if no_error:
            print(colorama.Fore.GREEN + 'Great! All your checked function are being called!')
        return check_for_use.functions
    try:
        check_for_use.functions
    except AttributeError:
        check_for_use.functions = {}
        if colorama:
            colorama.init(autoreset=True)

    def add(function):
        check_for_use.functions[function.__name__] = [False, function]
        def func(*args, **kwargs):
            check_for_use.functions[function.__name__] = [True, function]
            function(*args, **kwargs)
        return func
    return add

@check_for_use()
def hello():
    print('Hello world!')

@check_for_use()
def bonjour(nb):
    print('Bonjour tout le monde!')


# hello(); bonjour(0)

hello()


check_for_use(True) # outputs the following
Đầu ra:
Hello world!
The function 'bonjour' hasn't been called. Defined in "path_to_file.py" 
0 hữu ích 0 bình luận chia sẻ
0

Một ví dụ tối thiểu sử dụng unittest.mock.Mocktừ thư viện tiêu chuẩn:

from unittest.mock import Mock

def example():
    pass

example_mock = Mock(side_effect=example)
example_mock()
#Pseudocode:
if example_mock.called:
   print("foo bar")

Đầu ra bảng điều khiển sau khi chạy tập lệnh:

foo bar

Cách tiếp cận này rất hay vì nó không yêu cầu bạn phải sửa đổi examplechính chức năng, điều này rất hữu ích nếu bạn muốn thực hiện kiểm tra này trong một số mã kiểm tra đơn vị, mà không cần sửa đổi chính mã nguồn (EG để lưu trữ một has_been_calledthuộc tính hoặc bọc chức năng trong trình trang trí).

Giải trình

Như được mô tả trong tài liệu cho unittest.mock.Mocklớp , side_effectđối số đối với phương thức Mock()khởi tạo chỉ định "một hàm được gọi bất cứ khi nào Mock được gọi".

Các Mock.calledquy định cụ thể thuộc tính "một boolean đại diện hay không đối tượng giả đã được gọi là".

Các Mocklớp có các thuộc tính khác mà bạn có thể tìm thấy hữu ích, EG:

call_count: Một số nguyên cho bạn biết đối tượng giả đã được gọi bao nhiêu lần

call_args: Đây là Không có (nếu mô hình chưa được gọi) hoặc các đối số mà mô hình được gọi lần cuối cùng

call_args_list: Đây là danh sách tất cả các lệnh gọi đến đối tượng giả lập theo thứ tự (vì vậy độ dài của danh sách là số lần nó đã được gọi). Trước khi bất kỳ cuộc gọi nào được thực hiện, nó là một danh sách trống

Các Mocklớp cũng có phương pháp thuận tiện cho việc lập báo cáo khẳng định dựa trên bao nhiêu lần một Mockđối tượng được gọi, và những gì lẽ nó được gọi với, EG:

assert_called_once_with(*args, **kwargs): Khẳng định rằng mô hình đã được gọi chính xác một lần và lệnh gọi đó là với các đối số được chỉ định

0 hữu ích 0 bình luận chia sẻ
loading
Không tìm thấy câu trả lời bạn tìm kiếm? Duyệt qua các câu hỏi được gắn thẻ python python-3.x , hoặc hỏi câu hỏi của bạn.

Có thể bạn quan tâm

loading