2012-11-15 33 views
6

Tôi cần nhập khẩu theo phương thức __init__() (vì tôi chỉ cần chạy nhập khi tôi dụ lớp đó).Nhập bằng Python trong __init __()

Nhưng tôi không thể thấy rằng việc nhập bên ngoài __init__(), phạm vi được giới hạn ở __init__? làm thế nào để làm gì?

+6

Quá trình nhập bị ràng buộc vào phạm vi được nhập vào ... Tôi cảm thấy bạn không muốn làm điều này, trường hợp sử dụng của bạn là gì? –

+0

Tại sao bạn chỉ muốn nhập nó trong '__init __()' nếu bạn cần nó trong các phạm vi khác? –

+1

bởi vì tôi có một lớp với sự phụ thuộc, và tôi muốn phụ thuộc đó chỉ được nạp nếu ai đó đang sử dụng lớp đó (tạo ra một cá thể) – tapioco123

Trả lời

8

Tên đã nhập được gắn với phạm vi hiện tại, do đó, việc nhập bên trong một hàm chỉ gắn với tên cục bộ.

Nếu bạn hoàn toàn để nhập khẩu một cái gì đó trong __init__ mà sau đó cần phải được sẵn trên toàn cầu, đánh dấu tên nhập khẩu như global đầu tiên:

>>> def foo(): 
...  global sys 
...  import sys 
... 
>>> sys 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
NameError: name 'sys' is not defined 
>>> foo() 
>>> sys 
<module 'sys' (built-in)> 

nhưng điều này thường dẫn đến lỗi kỳ lạ và tuyệt vời khó có thể xác định vị trí . Đừng làm điều đó, chỉ cần thực hiện nhập khẩu của bạn ở phạm vi mô-đun thay thế.

Nếu bạn cần tên nhập khẩu trong phương thức lớp khác, bạn cũng có thể gán tên nhập khẩu cho một biến Ví dụ:

class Foo(object): 
    def __init__(self): 
     import os 
     self.join = os.path.join 

nhưng một lần nữa, đó không phải là cách tốt nhất để sử dụng.

+0

Bạn sẽ giới thiệu gì sau đó? Tôi có một lớp trừu tượng (abc) và một lớp chứa các lớp thực hiện lớp abc đó. Và một hàm dựa trên chuỗi tìm kiếm một lớp sẽ triển khai lớp abc này và sau đó gọi hàm đó là chuẩn bị hàm (được yêu cầu bởi abstract). Các chức năng đó có thể yêu cầu các công cụ hoàn toàn khác nhau, như một hàm không cần sqlite và trình phân tích cú pháp xml khác. –

+0

Có lẽ đặt những triển khai đó vào mô-đun riêng của họ? Nhưng thực sự, vấn đề với việc chỉ đưa những hàng nhập khẩu đó lên cấp cao nhất là gì? –

+0

Mô-đun riêng nằm ngoài câu hỏi, vì dir() quá bị làm xáo trộn và nhiều thứ để xác nhận (và có khả năng phá mã). Ở cấp cao nhất cũng là một câu hỏi, bởi vì một số lớp yêu cầu các mô-đun lớn, như sqlite, tkinter, minidom vv và chúng tôi không muốn nhập chúng khi nhập mô-đun, chỉ một tập con của chúng theo lớp chúng ta yêu cầu. –

4

Bạn chỉ có thể nhập lại các địa điểm khác mà bạn cần - nó sẽ được lưu trong bộ nhớ cache sau lần đầu tiên vì vậy điều này tương đối rẻ.

Hoặc bạn có thể sửa đổi các không gian tên chung hiện tại bằng một cái gì đó như globals()['name'] = local_imported_module_name.

EDIT: Đối với hồ sơ, mặc dù sử dụng globals() chức năng chắc chắn sẽ làm việc, tôi nghĩ rằng một "sạch" giải pháp sẽ được công bố tên của mô-đun global và sau đó import nó, như một số câu trả lời khác đã đề cập.

+2

'nhập lại nó' là giải pháp đúng. Nó hoàn toàn miễn phí, vì nhập khẩu mô đun được lưu trữ trên toàn cầu trong 'sys.modules'. – katrielalex

+1

@katrielalex: Đó là ý của tôi trong phần "nó sẽ được lưu trong bộ nhớ cache". – martineau

+0

Đồng ý - Tôi chỉ nhấn mạnh =) – katrielalex

2

Nếu bạn muốn kết quả của nhập khẩu của bạn để được hiển thị cho các đối tượng khác của lớp, bạn sẽ cần phải gán đối tượng phát sinh từ nhập khẩu của bạn vào một lớp học hoặc trường hợp biến

Ví dụ:

>>> class Foo(object): 
... def __init__(self): 
...  import math 
...  self.bar = math.pi 
... def zoo(self): 
...  return self.bar 
... 
>>> a = Foo() 
>>> a.zoo() 
3.141592653589793 
+0

Đây là một ý tưởng hay, nhưng tôi nghĩ OP muốn một cái gì đó giống như 'Foo.math =' hoặc 'self.math = math' - tức là toàn bộ mô-đun. – martineau

3

Tuyên bố import làm cho tên đã nhập chỉ khả dụng cho phạm vi hiện tại. An import foo bên trong __init__ của bạn tạo ra một foo chỉ hiển thị trong phương thức __init__.

Bạn có thể thêm import foo vào bất kỳ phương thức nào cần truy cập vào mô-đun hoặc nếu bạn thấy mình đang viết lại lần nữa, hãy sử dụng từ khóa global để nhập từ khóa đó vào phạm vi mô-đun.

class Wayne(object): 
    def __init__(self): 
     global foo 
     import foo 
Các vấn đề liên quan