2013-04-24 78 views
16

Câu hỏi của tôi là tìm ra "cách tốt" để xác định một hàm có triển khai khác nhau theo một tiêu chí nhất định. Hàm này sẽ được gọi từ nhiều tập lệnh, do đó tôi phải đặt nó trong một mô-đun.Định nghĩa có điều kiện của hàm trong một mô-đun

Vì lợi ích của ví dụ, tiêu chí của tôi liên quan đến nền tảng kịch bản nào được chạy, nhưng rõ ràng là thử nghiệm có thể chịu bất kỳ điều gì. chức năng của tôi cho phép dai dẳng định nghĩa/thu lấy các biến môi trường, vì vậy tôi đã tạo ra một mô-đun tên persistenv.py theo sơ đồ sau (SOLUTION 1):

# CROSS-PLATFORM PART 
def my_function1() : 
    # ... body1 ... 

# WINDOWS-ONLY PART 
if sys.platform.lower().startswith('win') : 
    def my_function2() : 
     # ...body2 for Windows... 

# LINUX-ONLY PART 
elif sys.platform.lower().startswith('linux') : 
    def my_function2() : 
     # ...body2 for Linux... 

else : 
    raise ImportError('Your platform is not supported') 

Trên đây giới thiệu hai định nghĩa có thể có của các chức năng tương tự trong một đơn mô-đun. Dù sao, nó có vẻ khá sạch hơn nhiều với tôi hơn thử nghiệm nền tảng này mỗi lần hàm được gọi (SOLUTION 2):

# CROSS-PLATFORM PART 
def my_function1() : 
    # ... body1 ... 


def my_function2() : 

    # WINDOWS-ONLY PART 
    if sys.platform.lower().startswith('win') : 
     # ...body2 for Windows... 

    # LINUX-ONLY PART 
    elif sys.platform.lower().startswith('linux') : 
     # ...body2 for Linux... 

Tôi tìm thấy một approach trong đó mỗi phần nền tảng cụ thể được chiết xuất vào mô-đun riêng của mình, và sau đó nhập khẩu có điều kiện trong persistenv.py (SOLUTION 3):

# CROSS-PLATFORM PART 
def my_function1() : 
    # ... body1 ... 

# WINDOWS-ONLY PART 
if sys.platform.lower().startswith('win') : 
    from persistenv_win import my_function2 

# LINUX-ONLY PART 
elif sys.platform.lower().startswith('linux') : 
    from persistenv_linux import my_function2 

else : 
    raise ImportError('Your platform is not supported') 

cho đến nay, tôi đạt đến kết luận sau đây (và đã nhận được câu hỏi sau đây):

  • GIẢI PHÁP 2 khó có thể được sử dụng, đặc biệt nếu bạn có một số chức năng nền tảng cụ thể my_function2, my_function3, my_function4 ... (như bạn sẽ phải lặp lại kiểm tra trong mỗi người)

  • GIẢI PHÁP 1 xuất hiện khá đơn giản (không có tập tin bổ sung, một thử nghiệm duy nhất), nhưng tôi tự hỏi làm thế nào để Python hành xử (nội bộ) nếu một trong những nhu cầu gọi "từ persistenv nhập my_function2"?

  • GIẢI PHÁP 3 có vẻ nhiều hơn Pythonic (được sử dụng trong cài đặt sẵn, ví dụ os.path), nhưng không thể có vấn đề khi persistenv.py, persistenv_win.py và persistenv_linux.py là một phần của cùng một gói (trong số các mô-đun khác) mà tôi sẽ nhập khẩu toàn cầu bằng cách thực hiện "nhập my_package" trong tập lệnh chính?

Trả lời

10

Nếu bạn có một cái nhìn tại các tiêu chuẩn lib Python, bạn sẽ thấy rằng tất cả ba trong số họ được sử dụng:

  • subprocess sử dụng các giải pháp 1 và 2; có một số nơi thử nghiệm xảy ra.

  • os sử dụng biến thể của giải pháp 3 (import ... as path).

Vì vậy, hãy sử dụng cái có vẻ thích hợp và đơn giản nhất.

[Giải pháp 1]

như thế nào Python cư xử (nội bộ) nếu người ta cần phải gọi là "from persistenv import my_function2"?

Nó hoạt động chính xác như mong muốn.Hàm đã được xác định khi nhập mô-đun được xuất.

Về mặt kỹ thuật, mô-đun được nhập giống như import module và sau đó tên được cho sẽ được tra cứu trong không gian tên của nó và đưa vào tên hiện tại.

[Giải pháp 3]

nó không thể là có vấn đề khi persistenv.py, persistenv_win.py và persistenv_linux.py là một phần của một gói phần mềm tương tự (trong số các module khác) mà tôi sẽ nhập khẩu trên toàn cầu bằng cách làm "nhập my_package" trong tập lệnh chính?

Tại sao nó có vấn đề? Bạn nhập my_package vào tập lệnh chính và sau đó là tập lệnh chính (hoặc một mô-đun của gói) thực hiện việc nhập đã nhập từ mô-đun phụ thuộc vào nền tảng. Điều đó hoàn toàn hợp lệ.

+0

Cảm ơn nhận xét của bạn. Tôi lấy nó rằng đây không phải là "thực hành bẩn thỉu" để sử dụng bất kỳ một trong 3 mẫu, nó chỉ phụ thuộc vào tình hình. Tuy nhiên, tôi không hoàn toàn hiểu điểm cuối cùng của bạn: Tôi phải sai, nhưng khi bạn 'nhập my_package', bạn tải persistenv.py (tải persistenv_win.py hoặc persistenv_linux.py) AND persistenv_win.py AND persistenv_linux.py, không nhất thiết phải theo thứ tự này cho vấn đề đó. Mỗi một trong 3 mô-đun này có được gắn với vùng tên riêng của nó không? (ví dụ 'my_package.persistenv_win.my_function2()'? – gromk13

+0

@ gromk13 Ngay cả khi chúng sẽ được nạp đồng thời (điều này không đúng), chúng thực sự sẽ có không gian tên riêng của chúng, nhưng việc tải chỉ xảy ra theo yêu cầu, nghĩa là, chỉ những mô-đun đó – glglgl

+0

Sai lầm của tôi, tôi giả định sai rằng việc nhập một gói sẽ tự động nhập tất cả các mô-đun của nó. Trên thực tế, tình huống có vấn đề tôi mô tả ở trên thay vì là kết quả của 'từ my_package import *', với ' __all__ = [..., 'persistenv', 'persistenv_win', 'persistenv_linux', ...] ', đó sẽ là một động tác ngớ ngẩn ... – gromk13