Tự Học Data Science · 04/08/2023 0

Chương 1 – Bài 1 – Trợ giúp và tài liệu trong IPython

Nếu bạn chỉ đọc một phần trong chương này, hãy đọc phần này: Tôi thấy các công cụ được thảo luận ở đây là những thông tin hữu ích nhất của IPython cho quy trình làm việc hàng ngày của tôi.

Khi một người có tư duy công nghệ được yêu cầu giúp đỡ bạn bè, thành viên gia đình hoặc đồng nghiệp với một vấn đề máy tính, đa phần vấn đề không phải là biết câu trả lời mà là biết cách tìm nhanh câu trả lời không biết trước. Trong khoa học dữ liệu cũng vậy: các nguồn tài liệu trực tuyến có thể tìm kiếm như các câu trả lời trên StackOverflow chứa một lượng thông tin vô cùng lớn, ngay cả (đặc biệt?) khi đó là một chủ đề mà bạn đã từng tìm kiếm. Việc trở thành một chuyên gia trong khoa học dữ liệu không phải là ghi nhớ công cụ hoặc lệnh cần sử dụng cho mọi tình huống có thể xảy ra, mà hơn hết là phải học cách tìm thông tin mà bạn không biết một cách hiệu quả, dù qua công cụ tìm kiếm web hay các phương tiện khác.

Một trong những chức năng hữu ích nhất của IPython/Jupyter là rút ngắn khoảng cách giữa người dùng với các loại tài liệu. Trong khi việc tìm kiếm trên web vẫn là mấu chốt để giải quyết những vấn đề phức tạp, có rất nhiều thông tin tuyệt vời có thể tìm thấy chỉ thông qua IPython. Dưới đây là một số ví dụ về các câu hỏi mà IPython có thể giúp trả lời chỉ trong vài thao tác gõ:

Làm thế nào để gọi hàm này? Các parameter và option của hàm đó là gì? Mã nguồn của Python object này trông như thế nào? Thư viện mà tôi đã import có gì? Object này có những thuộc tính hoặc phương thức nào? Dưới đây, chúng ta sẽ thảo luận về các công cụ của IPython để truy cập nhanh thông tin này.

Cách truy cập Documentation từ IPython

Ngôn ngữ Python và hệ sinh thái khoa học dữ liệu của nó được xây dựng với người dùng làm trung tâm, và một phần quan trọng của việc đó là truy cập vào Documentation. Mỗi đối tượng Python chứa tham chiếu đến một chuỗi được gọi là doc string, nó chứa một bản tóm tắt ngắn gọn về object và cách sử dụng nó. Python có một hàm tích hợp sẵn là help() có thể truy cập thông tin này và hiển thị kết quả. Ví dụ, để xem tài liệu của hàm tích hợp sẵn len, bạn có thể làm như sau:

In [1]: help(len)
Trợ giúp về hàm len  sẵn trong module builtins:

len(...)
    len(object) -> integer

    Trả về số lượng các phần tử của sequence hoặc mapping.

Vì việc tìm kiếm trợ giúp về một đối tượng là rất phổ biến và hữu ích, trong IPython bạn có thể dùng ký tự “?” như một cách ngắn gọn để truy cập vào tài liệu này và thông tin liên quan khác:

In [2]: len?
Type:        builtin_function_or_method
String form: <built-in function len>
Namespace:   Python builtin
Docstring:
len(object) -> integer

Return the number of items of a sequence or mapping.

Phương thức này hoạt động với hầu hết mọi thứ, bao gồm cả phương thức của đối tượng:

In [3]: L = [1, 2, 3]
In [4]: L.insert?
Type:        builtin_function_or_method
String form: <built-in method insert of list object at 0x1024b8ea8>
Docstring:   L.insert(index, object) -- insert object before index

hoặc thậm chí là đối tượng chính, với kiểu dữ liệu của chúng:

In [5]: L?
Type:        list
String form: [1, 2, 3]
Length:      3
Docstring:
list() -> new empty list
list(iterable) -> new list initialized from iterable's items

Cách này này thậm chí còn hoạt động cho các hàm hoặc các đối tượng khác mà bạn tự tạo ra! Ở đây chúng ta sẽ định nghĩa một hàm nhỏ có một đoạn văn bản mô tả:

In [6]: def square(a):
  ....:     """Return the square of a."""
  ....:     return a ** 2
  ....:

Lưu ý rằng để tạo một chuỗi tài liệu (docstring) cho hàm của chúng ta, chúng ta chỉ đơn giản đặt một chuỗi văn bản vào dòng đầu tiên.Vì tài liệu (docstring) thường là nhiều dòng, theo quy ước chúng tôi sử dụng cú pháp ba dấu ngoặc kép ”’ của Python cho string nhiều dòng.

Bây giờ chúng ta sẽ sử dụng dấu ? để tìm chuỗi tài liệu này:

In [7]: square?
Type:        function
String form: <function square at 0x103713cb0>
Definition:  square(a)
Docstring:   Return the square of a.

Việc truy cập nhanh vào tài liệu thông qua docstrings là một lý do bạn nên hình thành thói quen luôn thêm chú thích trực tiếp vào mã code mà bạn viết!

Truy cập mã nguồn

Do ngôn ngữ Python rất dễ đọc, hiểu được đối tượng ở một mức độ bằng cách đọc mã nguồn.IPython cung cấp một lối tắt để lấy mã nguồn với hai dấu chấm hỏi liên tiếp (??):

In [8]: square??
Type:        function
String form: <function square at 0x103713cb0>
Definition:  square(a)
Source:
def square(a):
    "Return the square of a"
    return a ** 2

Đối với các function đơn giản như thế này, dấu chấm hỏi kép có thể cung cấp cái nhìn nhanh về các chi tiết bên trong của chúng.

Nếu bạn dùng cái này thường xuyên, bạn sẽ nhận thấy rằng đôi khi ?? không hiển thị source code: điều này thường xảy ra vì đối tượng không được chạy trên Python, mà là trong C hoặc một ngôn ngữ mở rộng khác. Khi đó, tiền tố ?? cho kết quả tương tự như tiền tố ?. Bạn sẽ thường gặp điều này với nhiều đối tượng và kiểu tích hợp sẵn trong Python, ví dụ như len ở trên:

In [9]: len??
Type:        builtin_function_or_method
String form: <built-in function len>
Namespace:   Python builtin
Docstring:
len(object) -> integer

Return the number of items of a sequence or mapping.

Khám phá các Modules với Tab-Completion

Một công cụ hữu ích khác của IPython là sử dụng phím tab để tự động hoàn thành và hiển thị thêm các thuộc tính của đối tượng, module và name-space. Trong những ví dụ tiếp theo, chúng tôi sẽ sử dụng <TAB> để chỉ khi nào nút Tab nên được nhấn.

Tab-completion

Mỗi đối tượng Python đều có các thuộc tính và phương thức đi kèm với nó. Giống như với hàm help đã được đề cập trước đó, Python có một hàm tích hợp sẵn là dir trả về một danh sách các thuộc tính này, nhưng giao diện của tab-completion dễ sử dụng hơn nhiều. Để xem danh sách tất cả các thuộc tính có sẵn của một đối tượng, bạn có thể gõ tên của đối tượng, theo sau là một dấu chấm (“.“) và phím Tab:

In [10]: L.c<TAB>
L.clear  L.copy   L.count  

In [10]: L.co<TAB>
L.copy   L.count

Để thu hẹp danh sách, bạn có thể gõ ký tự đầu tiên hoặc một số ký tự của tên, và phím Tab sẽ tìm các thuộc tính và phương thức tương ứng:

In [10]: L.c<TAB>
L.clear  L.copy   L.count  

In [10]: L.co<TAB>
L.copy   L.count

Nếu chỉ có một tùy chọn duy nhất, nhấn phím Tab sẽ tự động hoàn thành dòng lệnh cho bạn.Ví dụ, đoạn mã sau sẽ tức thì được thay thế bằng L.count:

In [10]: L.cou<TAB>

Mặc dù Python không có sự phân biệt rõ ràng giữa các thuộc tính publib và các thuộc tính private, theo quy ước thì một gạch dưới trước sẽ được sử dụng để đặt tên cho các phương thức này. Để làm rõ, các phương thức private và các phương thức đặc biệt sẽ không được liệt kê trong danh sách mặc định, nhưng có thể liệt kê chúng bằng cách gõ gạch dưới:

In [10]: L._<TAB>
L.__add__           L.__gt__            L.__reduce__
L.__class__         L.__hash__          L.__reduce_ex__

Tab completion khi import thư viện

Tab completion cũng hữu ích khi nhập các đối tượng từ những package khác nhau.Ở đây chúng ta sẽ sử dụng nó để tìm tất cả các imports có thể trong thư viện itertools bắt đầu bằng co:

In [10]: from itertools import co<TAB>
combinations                   compress
combinations_with_replacement  count

Tương tự, bạn có thể sử dụng tính năng tab-completion để xem các thư viện có sẵn trên hệ thống của bạn:

In [10]: import <TAB>
Display all 399 possibilities? (y or n)
Crypto              dis                 py_compile
Cython              distutils           pyclbr
...                 ...                 ...
difflib             pwd                 zmq

In [10]: import h<TAB>
hashlib             hmac                http         
heapq               html                husl

(Lưu ý rằng vì lý do tóm tắt, tôi không in ra đây tất cả các thư viện và mô-đun có thể import được trên hệ thống của tôi.)

Vượt qua tab tự động hoàn thành: khớp wildcard

Tab completion rất hữu ích nếu bạn biết một vài ký tự đầu của đối tượng hoặc thuộc tính mà bạn đang tìm kiếm, nhưng nó không giúp ích nhiều nếu bạn muốn khớp với các ký tự ở giữa hoặc cuối từ. Đối với trường hợp này, IPython cung cấp cách để khớp với ký tự đại diện cho tên bằng cách sử dụng ký tự *.

Ví dụ, chúng ta có thể sử dụng điều này để liệt kê tất cả các đối tượng trong không gian tên kết thúc bằng Warning:

In [10]: *Warning?
BytesWarning                  RuntimeWarning
DeprecationWarning            SyntaxWarning
FutureWarning                 UnicodeWarning
ImportWarning                 UserWarning
PendingDeprecationWarning     Warning
ResourceWarning

Lưu ý rằng ký tự * khớp với bất kỳ chuỗi nào, bao gồm cả chuỗi rỗng.

Tương tự, giả sử chúng ta đang tìm kiếm một phương thức chuỗi mà chứa từ find ở bất kỳ vị trí nào trong tên của nó.Chúng ta có thể tìm kiếm theo cách sau:

In [10]: str.*find*?
str.find
str.rfind

Tôi thấy loại tìm kiếm với ký tự đại diện linh hoạt này có thể rất hữu ích để tìm một lệnh cụ thể khi làm quen với một package mới.