Việc nhập Python có lười biếng không?

Trong bài đăng này, chúng ta sẽ hiểu Lazy import trong Python là gì? . Hãy xem các câu lệnh nhập bên dưới bằng Python

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import sklearn
import nltk
import os
import sys
import re
import seaborn as sns
import pickle

Và danh sách được tiếp tục. Thông thường trong một dự án khoa học dữ liệu lớn, chúng tôi cần nhập thêm nhiều thư viện vào mã của mình. Trong những trường hợp như vậy, chúng ta có thể tránh sử dụng nhiều câu lệnh nhập bằng cách sử dụng một câu lệnh nhập duy nhất sẽ nhập thư viện pyforest. Thư viện này, sau khi được nhập, sẽ lười nhập gần như tất cả thư viện khoa học dữ liệu mà chúng tôi sẽ phải sử dụng trong dự án của mình

Để sử dụng thư viện này, trước tiên chúng ta cần cài đặt nó trong hệ thống của mình. Sử dụng lệnh sau để cài đặt pyforest

pip install pyforest

Để lười nhập tất cả các thư viện có sẵn trong pyforest, chúng ta sẽ cần nhập nó vào chương trình của mình như trong đoạn mã dưới đây

Một trong những tính năng mới trong Python 3. 7 là PEP 562 bổ sung hỗ trợ cho __getattr__[]__dir__[] trên các mô-đun. Cả hai đều mở ra một số khả năng thú vị. Chẳng hạn, với __dir__[], giờ đây bạn có thể có

pip install pyforest
0 chỉ hiển thị những gì mà
pip install pyforest
1 định nghĩa

Nhưng quá đắm chìm trong hệ thống nhập của Python, mối quan tâm của tôi nằm ở __getattr__[] và cách nó có thể được sử dụng để nhập chậm. Bây giờ tôi sẽ bắt đầu bài đăng này bằng cách tuyên bố rằng hầu hết mọi người không cần nhập khẩu lười biếng. Chỉ khi chi phí ban đầu là tối quan trọng thì điều này mới phát huy tác dụng, e. g. Các ứng dụng CLI có thời gian chạy ngắn. Đối với hầu hết mọi người, những tiêu cực đối với việc lười tải là không đáng, e. g. biết nhiều sau này khi nhập không thành công thay vì khởi chạy ứng dụng

những cách cũ

Theo truyền thống, có hai cách để thực hiện nhập chậm/chậm. Cái cũ nhất đang thực hiện nhập cục bộ thay vì nhập toàn cầu [i. e. nhập trong chức năng của bạn thay vì ở đầu mô-đun của bạn]. Mặc dù điều này có tác dụng trì hoãn quá trình nhập cho đến khi bạn chạy mã thực sự cần mô-đun mà bạn đang nhập, nhưng nó lại gây bất lợi khi phải viết đi viết lại cùng một câu lệnh nhập. Và nếu bạn chỉ thực hiện một số nhập cục bộ, bạn sẽ dễ dàng quên những cái bạn đang cố tránh và sau đó vô tình nhập mô-đun trên toàn cầu. Vì vậy, phương pháp này hoạt động, nó chỉ không lý tưởng

Cách tiếp cận khác là sử dụng lazy loader được cung cấp trong

pip install pyforest
3. Giờ đây, nhiều người như Google, Facebook và Mercurial đã sử dụng thành công trình tải chậm này. Hai người đầu tiên thích nó để giảm thiểu chi phí khi chạy thử nghiệm trong khi người cuối cùng muốn khởi động nhanh. Một ưu điểm đối với trình tải lười biếng so với nhập cục bộ là bạn có thể kích hoạt sớm
# In pkg/__init__.py with a pkg/sub.py.
mod, __getattr__ = lazy_import[__name__, {'sys', '.sub as thingy'}]

def test1[]:
    return mod.sys

def test2[]:
    return mod.thingy.answer
0 khi việc tìm kiếm một mô-đun được thực hiện một cách háo hức, chỉ là quá trình tải bị hoãn lại

Hầu hết mọi người cũng thiết lập nó để mọi thứ được tải một cách lười biếng. Bây giờ đó là một điều tốt và xấu. Nó tốt ở chỗ bạn phải làm rất ít để khiến mọi thứ tải một cách lười biếng. Điều tồi tệ là khi bạn làm điều gì đó không rõ ràng, cuối cùng bạn có thể phá vỡ những kỳ vọng mà mã đó có [có một lý do là "rõ ràng tốt hơn là không rõ ràng"]. Nếu một mô-đun mong muốn được tải háo hức thì nó có thể bị hỏng nặng khi được tải một cách lười biếng. Mercurial thực sự đã phát triển một danh sách đen các mô-đun không tải một cách lười biếng để giải quyết vấn đề này, nhưng họ phải đảm bảo luôn cập nhật nó để nó không phải là một giải pháp hoàn hảo

cách mới

Trong Trăn 3. 7, các mô-đun hiện có thể có __getattr__[] được xác định trên chúng, cho phép một người viết một hàm sẽ nhập một mô-đun khi nó không có sẵn dưới dạng thuộc tính trên mô-đun. Điều này có nhược điểm là làm cho nó trở thành một quá trình nhập lười biếng thay vì tải và do đó phát hiện ra rất muộn nếu một

# In pkg/__init__.py with a pkg/sub.py.
mod, __getattr__ = lazy_import[__name__, {'sys', '.sub as thingy'}]

def test1[]:
    return mod.sys

def test2[]:
    return mod.thingy.answer
0 sẽ được nâng lên. Nhưng nó rõ ràng và vẫn được xác định trên toàn cầu cho mô-đun của bạn, vì vậy việc kiểm soát sẽ dễ dàng hơn

Bản thân mã thực sự không phức tạp

import importlib


def lazy_import[importer_name, to_import]:
    """Return the importing module and a callable for lazy importing.

    The module named by importer_name represents the module performing the
    import to help facilitate resolving relative imports.

    to_import is an iterable of the modules to be potentially imported [absolute
    or relative]. The `as` form of importing is also supported,
    e.g. `pkg.mod as spam`.

    This function returns a tuple of two items. The first is the importer
    module for easy reference within itself. The second item is a callable to be
    set to `__getattr__`.
    """
    module = importlib.import_module[importer_name]
    import_mapping = {}
    for name in to_import:
        importing, _, binding = name.partition[' as ']
        if not binding:
            _, _, binding = importing.rpartition['.']
        import_mapping[binding] = importing

    def __getattr__[name]:
        if name not in import_mapping:
            message = f'module {importer_name!r} has no attribute {name!r}'
            raise AttributeError[message]
        importing = import_mapping[name]
        # imortlib.import_module[] implicitly sets submodules on this module as
        # appropriate for direct imports.
        imported = importlib.import_module[importing,
                                           module.__spec__.parent]
        setattr[module, name, imported]
        return imported

    return module, __getattr__

Để sử dụng nó, bạn có thể làm như sau

# In pkg/__init__.py with a pkg/sub.py.
mod, __getattr__ = lazy_import[__name__, {'sys', '.sub as thingy'}]

def test1[]:
    return mod.sys

def test2[]:
    return mod.thingy.answer

Khi thiết kế cái này, phần khó nhất là làm thế nào để mô phỏng cú pháp

# In pkg/__init__.py with a pkg/sub.py.
mod, __getattr__ = lazy_import[__name__, {'sys', '.sub as thingy'}]

def test1[]:
    return mod.sys

def test2[]:
    return mod.thingy.answer
3 để tránh xung đột tên. Cuối cùng tôi đã chấp nhận một chuỗi gần giống với câu lệnh nhập mà bạn đã viết nếu bạn thực hiện nhập toàn cầu. Tôi có thể chia nó thành một đối số thứ ba lấy ánh xạ, nhưng tôi nghĩ điều đó là không cần thiết và tôi muốn có một API thống nhất hơn

Dù sao, tôi luôn hài lòng khi tôi có thể làm điều gì đó như thế này chỉ trong 20 dòng mã Python và cảm thấy như đó không phải là một vụ hack hoàn toàn. 😉

Điều gì xảy ra khi nhập Python?

Khi một mô-đun được nhập lần đầu tiên, Python tìm kiếm mô-đun và nếu tìm thấy, nó sẽ tạo một đối tượng mô-đun 1, khởi tạo nó . Nếu không tìm thấy mô-đun được đặt tên, Lỗi ModuleNotFoundError sẽ xuất hiện. Python thực hiện các chiến lược khác nhau để tìm kiếm mô-đun được đặt tên khi máy móc nhập khẩu được gọi.

Việc nhập tệp Python có chạy không?

Khi bạn nhập một mô-đun bằng Python, tất cả mã trong đó sẽ được chạy và tất cả các biến trong mô-đun đó sẽ bị kẹt .

Cách tốt nhất để nhập bằng Python là gì?

Hướng dẫn kiểu nhập .
Giữ nhập ở đầu tệp
Viết nhập trên các dòng riêng biệt
Tổ chức nhập khẩu thành các nhóm. nhập thư viện tiêu chuẩn đầu tiên, sau đó nhập của bên thứ ba và cuối cùng là nhập thư viện hoặc ứng dụng cục bộ
Đặt hàng nhập khẩu theo thứ tự bảng chữ cái trong mỗi nhóm

Tất cả các mục nhập có nên ở đầu Python không?

Nội dung nhập phải luôn được viết ở đầu tệp, sau bất kỳ nhận xét và chuỗi tài liệu mô-đun nào . Nhập khẩu nên được chia theo những gì đang được nhập khẩu. Nhìn chung có ba nhóm. nhập thư viện tiêu chuẩn [các mô-đun tích hợp sẵn của Python]

Chủ Đề