ast
module có thể làm điều này khá dễ dàng. Nếu chúng ta giả định nguồn được lưu trữ trong một biến có tên source
(có thể được đọc từ một tập tin):
import ast
root = ast.parse(source)
names = sorted({node.id for node in ast.walk(root) if isinstance(node, ast.Name)})
mà mất đặt hàng để đạt được uniquification và thứ tự hiển thị thân thiện, nhưng bạn chỉ có thể sử dụng một sự hiểu biết danh sách hoặc biểu hiện máy phát điện thay vì một thiết lập hiểu nếu bạn không cần độc đáo nhưng muốn đặt hàng. Kết quả là list
là:
['a', 'b', 'c', 'do_something', 'f', 'myList', 'range', 'someMethod', 'something', 'x']
Không giống như các giải pháp khác được đăng cho đến nay, điều này sẽ recurse vào lớp học và chức năng để có được những tên được sử dụng bên trong chúng, và không yêu cầu bạn phải nhập khẩu các mô-đun hoặc lớp để kiểm tra, cũng không yêu cầu bạn phải tự thực hiện xử lý đệ quy; mọi mã Python hợp lệ sẽ hoạt động.
Nhưng kỳ lạ, trên Python 3 (thay thế một giá trị print
chức năng cuộc gọi), bạn nhận được:
['a', 'b', 'c', 'do_something', 'f', 'myList', 'print', 'range', 'someMethod', 'something']
mà thêm print
(như mong đợi, đó là một tên bây giờ, không phải là một tuyên bố từ khóa), nhưng bỏ qua x
. Bạn đã không yêu cầu x
(đối số nhận được bởi someMethod
), và điều này không tạo ra nó trên Python 3. Tên trong các nguyên mẫu hàm xuất hiện để không tạo ra một nút ast.Name
ở đó, đi con số. Bạn có thể lấy thông tin đó ra khỏi nút ast.FunctionDef
từ thuộc tính arg
của mỗi mục nhập trong list
node.args.args
nhưng có thể vẫn chưa hoàn chỉnh; Tôi nghi ngờ các tên liên quan đến định nghĩa khác có thể bị bỏ qua, ví dụ: trong khai báo lớp với thừa kế. Bạn sẽ cần phải poke xung quanh với một số ví dụ để đảm bảo rằng bạn đang kiểm tra tất cả mọi thứ (giả sử bạn muốn các công cụ như x
và muốn làm việc trên Python 3).
Điều đó nói rằng, x
sẽ hiển thị tốt nếu bạn tham chiếu; nếu bạn chuyển nó đến do_something
hoặc sử dụng nó theo bất kỳ cách nào ngoài việc nhận và loại bỏ nó, nó sẽ hiển thị.
Bạn cũng có thể làm cho một nỗ lực để chỉ xử lý tên giao cho, không được sử dụng (để loại trừ do_something
, range
) bằng cách mở rộng các thử nghiệm để:
names = sorted({node.id for node in ast.walk(root) if isinstance(node, ast.Name) and not isinstance(node.ctx, ast.Load)})
Nhưng điều đó cũng sẽ thả someMethod
(trong cả hai Py2 và Py3) bởi vì bản thân định nghĩa không tạo ra một ast.Name
, chỉ việc sử dụng nó. Vì vậy, một lần nữa, bạn phải nghiên cứu sâu hơn một chút về nội bộ ast.Node
cho ast.FunctionDef
, ast.ClassDef
, v.v. để lấy các tên không trực tiếp là walk
.
Chỉ cần tự hỏi, liệu đầu ra của bạn có bao gồm 'something'? – Lafexlos
oh vâng, tôi xin lỗi tôi sẽ sửa câu hỏi của tôi .. Cảm ơn dude – farhawa
Tại sao bạn cần tất cả các tên này? Điều này trông giống như một vấn đề XY tiềm năng ... http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem – turbulencetoo