2008-10-28 40 views
39

Tôi cảm thấy như tôi nên biết điều này, nhưng tôi đã không thể tìm ra nó ...Làm cách nào để lấy tên hàm hoặc phương thức từ bên trong hàm hoặc phương thức Python?

Tôi muốn lấy tên của một phương pháp - điều này xảy ra là một thử nghiệm tích hợp - từ bên trong nó để nó có thể in ra một số văn bản chẩn đoán. Tôi có thể, tất nhiên, chỉ cần mã hóa cứng tên của phương thức trong chuỗi, nhưng tôi muốn thực hiện thử nghiệm nhiều hơn một chút nếu có thể.

+0

bản sao có thể có của [Cách lấy tên hàm dưới dạng chuỗi trong Python?] (Http://stackoverflow.com/questions/251464/how-to-get-the-function-name-as-string-in- python) – DarenW

+0

@ DarenW Nó không phải. Yêu cầu tên của một hàm từ một biến chứa đối tượng hàm và yêu cầu tên của một hàm từ bên trong là hai câu hỏi rất khác nhau. –

Trả lời

23

Những câu trả lời liên quan đến mẫn qua inspect và như thế là hợp lý . Nhưng có thể có một tùy chọn khác, tùy thuộc vào trường hợp của bạn:

Nếu kiểm tra tích hợp của bạn được viết bằng mô-đun unittest, thì bạn có thể sử dụng self.id() trong TestCase của mình.

+1

Tôi vừa phát hiện ra self.id() hoạt động trong phương thức setUp() không nhất thiết (nó trả về tên của bài kiểm tra chứ không phải là "thiết lập"), không giống như các giải pháp khác. Vì vậy, tôi đang thay đổi điều này thành câu trả lời được chấp nhận cho câu hỏi cụ thể này. –

+0

@ DarylSpitzer thật tuyệt! – Dan

3

Tôi nghĩ mô-đun traceback có thể có những gì bạn đang tìm kiếm. Đặc biệt, hàm extract_stack trông giống như nó sẽ thực hiện công việc.

16

Trình trang trí này làm cho tên của phương thức có sẵn bên trong hàm bằng cách chuyển nó làm đối số từ khóa.

from functools import wraps 
def pass_func_name(func): 
    "Name of decorated function will be passed as keyword arg _func_name" 
    @wraps(func) 
    def _pass_name(*args, **kwds): 
     kwds['_func_name'] = func.func_name 
     return func(*args, **kwds) 
    return _pass_name 

Bạn sẽ sử dụng nó theo cách này:

@pass_func_name 
def sum(a, b, _func_name): 
    print "running function %s" % _func_name 
    return a + b 

print sum(2, 4) 

Nhưng có lẽ bạn muốn viết những gì bạn muốn trực tiếp bên trong trang trí riêng của mình. Sau đó, mã là một ví dụ về một cách để có được tên hàm trong một trình trang trí. Nếu bạn cung cấp thêm chi tiết về những gì bạn muốn làm trong chức năng, điều đó đòi hỏi tên, có lẽ tôi có thể đề xuất một cái gì đó khác.

+2

+1 về cách sử dụng trang trí dựa trên chi tiết triển khai –

+1

@MatthewTrevor Thành thật mà nói tôi thấy một người trang trí dựa vào chi tiết triển khai. Theo http://stackoverflow.com/questions/251464/how-to-get-a-function-name-as-a-string-in-python thì tốt hơn nên sử dụng '.__ name__' trên' .func_name' . Mặc dù vậy, tôi đồng ý với ý tưởng cơ bản. –

53

này có vẻ là cách đơn giản nhất sử dụng mô-đun inspect:

import inspect 
def somefunc(a,b,c): 
    print "My name is: %s" % inspect.stack()[0][3] 

Bạn có thể khái quát này với:

def funcname(): 
    return inspect.stack()[1][3] 

def somefunc(a,b,c): 
    print "My name is: %s" % funcname() 

tín dụng để Stefaan Lippens được tìm thấy qua google.

+0

Typo: tên phải là "Stefaan". Liên kết cũ và không hoạt động --- thử "http://stefaanlippens.net/python_inspect". –

10
# file "foo.py" 
import sys 
import os 

def LINE(back = 0): 
    return sys._getframe(back + 1).f_lineno 
def FILE(back = 0): 
    return sys._getframe(back + 1).f_code.co_filename 
def FUNC(back = 0): 
    return sys._getframe(back + 1).f_code.co_name 
def WHERE(back = 0): 
    frame = sys._getframe(back + 1) 
    return "%s/%s %s()" % (os.path.basename(frame.f_code.co_filename),  
          frame.f_lineno, frame.f_code.co_name) 

def testit(): 
    print "Here in %s, file %s, line %s" % (FUNC(), FILE(), LINE()) 
    print "WHERE says '%s'" % WHERE() 

testit() 

Output:

$ python foo.py 
Here in testit, file foo.py, line 17 
WHERE says 'foo.py/18 testit()' 

Sử dụng "trở lại = 1" để tìm thông tin liên quan đến hai cấp độ trở xuống stack vv

Các vấn đề liên quan