tại sao chức năng trống là cần thiết


9

Tôi bắt đầu học python và tôi tự hỏi tại sao hàm rỗng lại cần thiết trong ngôn ngữ lập trình

ví dụ như trong trăn:

def empty_func():
    pass

thậm chí trong shell script chức năng trống chức năng trống có sẵn.

Hiểu và câu hỏi của tôi:

  1. Tại sao ngôn ngữ lập trình cần các hàm trống? Có phải chỉ để chơi xung quanh với ngôn ngữ lập trình hoặc không có gì khác thực sự quan trọng?

  2. Nếu điều này có mục đích, bất cứ ai cũng có thể mô tả trường hợp sử dụng hoặc đưa ra một ví dụ thực tế về việc sử dụng các hàm trống?

  3. Hoặc có bất kỳ truyền thống của ngôn ngữ lập trình cho phép các chức năng trống?


EDIT (Những điều tôi nhận được từ việc đọc câu trả lời của bạn):

  • Đối với thuật toán phác thảo hoặc với các hàm trừu tượng
  • Đối với các biểu mẫu Đệ trình không có hành động cần phải được thực hiện
  • Giữ chỗ cho một số hoạt động bắt buộc

1
chúng có thể được sử dụng như STUBS nếu việc thực thi chương trình mong muốn tìm / sử dụng chúng, tuy nhiên bạn không muốn thay đổi bất cứ điều gì thông qua chúng.
G.Rassovsky

Câu trả lời:


5

Trong các ngôn ngữ shell của họ Bourne, :lệnh, không có gì cả, thường được sử dụng trong hai tình huống:

  • Giữ chỗ khi một cái gì đó mong đợi một lệnh bắt buộc, ví dụ

    while some_condtion
    do :
    done

    kể từ khi doyêu cầu ít nhất một lệnh.

  • Loại bỏ các đối số, nhưng thực hiện các tác dụng phụ bên trong danh sách đối số, ví dụ:

    : ${myvar=foo}

Tôi chắc chắn có những ứng dụng khác mà các chuyên gia shell sẽ biết :)

Trong Python (và các ngôn ngữ khác), nó được sử dụng ít thường xuyên hơn. Nó có thể hoạt động như một đối số cho hàm bậc cao hơn khi bạn không thực sự muốn làm bất cứ điều gì. Ví dụ: giả sử bạn có một hàm gửi biểu mẫu và cho phép một hàm được gọi không đồng bộ sau khi gửi xong:

def submit(callback=empty_func):
    ...

Bằng cách này, nếu callbackkhông được cung cấp, việc gửi vẫn sẽ được thực hiện nhưng không có hành động nào nữa sẽ được thực hiện. Nếu bạn đã sử dụng Nonelàm giá trị mặc định, bạn phải kiểm tra rõ ràng xem có gọi lại được không None, thêm lộn xộn vào mã.


1

Nó phụ thuộc vào vị trí của bạn trong chu kỳ phát triển, nhưng đôi khi khi phác thảo ra một thuật toán, bạn muốn thực hiện trừu tượng về các khối phức tạp mà không thực hiện chúng ngay lập tức.

def full_algo():
  init_stuff()
  process_stuff()
  ...

Bạn biết nó init_stuffsẽ hoạt động như thế nào , nó khá đơn giản trong đầu bạn nhưng bạn không thực sự cần nó ngay lập tức, vì vậy bạn tuyên bố nó là một hàm trống. Nó sẽ cho phép mã của bạn biên dịch và chạy mà không cần bận tâm về các chi tiết chính.

Một cách sử dụng khác cho các ứng dụng được phát hành là khi sử dụng tính kế thừa. Giả sử rằng bạn có một lớp lớn xác định hành vi của mã cụ thể nền tảng. Bạn có thể kết thúc với một logic tương tự như thế này:

init_filesystem();
access_files();
release_filesystem();

Mã này sẽ hoạt động trên nhiều nền tảng, nhưng một số nền tảng có thể không cần khởi tạo hệ thống tệp. Sau đó, kế thừa của bạn sẽ trông như thế này (ảo với = 0 trong C ++ chỉ có nghĩa là các lớp dẫn xuất PHẢI thực hiện các phương thức đó):

class FileSystem{
  virtual void init_filesystem() = 0;
  virtual void access_files() = 0;
  virtual void release_filesystem() = 0;
};

Sau đó, một triển khai cụ thể của lớp này (giao diện) có thể không làm gì đối với một số phương thức đó. Ngoài ra, lớp cơ sở có thể khai báo các phương thức rỗng cho init / phát hành thay vì khai báo chúng ảo.

Cuối cùng (và đáng xấu hổ), đôi khi bạn duy trì một ứng dụng rất cũ. Bạn sợ rằng các phương pháp xóa sẽ phá vỡ mọi thứ. Điều này xảy ra khi bạn có sự kế thừa phức tạp không được hiểu đúng hoặc khi bạn có nhiều con trỏ hàm (gọi lại). Bạn chỉ cần xóa mã bên trong chúng để chúng được gọi bằng mọi cách mà không phá vỡ bất cứ điều gì.


0

Rufflewind đã thực hiện tốt công việc khi bạn có thể sử dụng một chức năng trống trong một chương trình đã hoàn thành. Theo kinh nghiệm của tôi, nó có xu hướng được sử dụng thường xuyên hơn trong các chương trình chưa hoàn thành, vì vậy bạn có thể lên kế hoạch cho những gì bạn sẽ viết và nó vẫn được biên dịch cho đến khi bạn thực sự thực hiện nó. Nói cách khác, nó thường chỉ là một trình giữ chỗ.

Nó cần thiết trong trường hợp của python vì nó sử dụng thụt đầu dòng để đánh dấu các khối, không giống như các ngôn ngữ giống như C sử dụng dấu ngoặc nhọn {}. Điều này có nghĩa là nếu bạn không có pass, trình phân tích cú pháp không thể cho biết nếu bạn có ý định để trống hoặc nếu bạn quên. Bao gồm passlàm cho trình phân tích cú pháp đơn giản hơn nhiều và cung cấp cho bạn một từ thuận tiện để tìm kiếm khi bạn đang tìm kiếm các khối chưa được thực hiện.


1
Đối với mã chưa hoàn thành, việc ném NotImplementedErrorlà một giải pháp phù hợp hơn vì "Lỗi không bao giờ được truyền âm thầm" và gọi một hàm chưa được thực hiện trong chương trình trực tiếp là một lỗi.
ivan_pozdeev

Mà phụ thuộc. Đối với mã bạn gửi, có. Nhưng nếu đó là mã mà bạn dự kiến ​​sẽ thực hiện trong một giờ và bạn chỉ để nó không được thực hiện trong khi bạn làm bài kiểm tra đơn vị, chỉ cần không để thực hiện có thể là một lựa chọn tốt hơn. Thông thường quy trình công việc của tôi là 1) ghi phương thức còn sơ khai với pass 2) kiểm tra đơn vị ghi kiểm tra giá trị trả về 3) xác minh kiểm tra không thành công (vì phương thức trả về không xác định) 4) thực hiện phương pháp kiểm tra 5 hiện tại
Gort Robot

0

Mặc dù đó không phải là điều bạn muốn làm trong Python, nhưng đôi khi trong thế giới trình điều khiển thiết bị bạn cần cung cấp một chức năng trống, để xử lý một sự kiện mà bạn (a) biết sẽ không xảy ra hoặc ( b) không quan tâm ngay cả khi nó làm.

Bạn cũng thấy điều này trong C với các cuộc gọi lại. Đôi khi, bạn sẽ thấy mã chỉ ĐÁNH GIÁ bạn đã cung cấp một cuộc gọi lại và cố gắng gọi nó, bỏ qua rủi ro của một con trỏ null. Tất cả những gì bạn có thể làm trong trường hợp đó là cung cấp một thói quen gọi lại trống. (Vâng, tôi có một nhà cung cấp cụ thể trong tâm trí.)


Tôi đã sử dụng passrất nhiều như một trình giữ chỗ khi viết mã, đặc biệt là trong các lớp, khi tôi muốn một cái gì đó có thể chạy được trước khi mọi thứ hoàn tất. Nó thực sự tương đương với python {}, mà python không thể làm vì nó không sử dụng niềng răng. Theo nghĩa đó, tất cả các ngôn ngữ mà tôi biết đều cho phép điều này, chỉ là một cặp đôi giống như pythonyêu cầu một từ khóa. Ngay cả trong những ngày lắp ráp chúng tôi đã có NOP.
Gort Robot

@StevenBurnap, thông thường khi tôi làm điều gì đó tương tự, tôi bao gồm tương đương cục bộ của printf (">>> thường trình XXX được gọi là \ n");
John R. Strohm
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.