Python vượt qua giá trị hoặc tràn ngăn xếp tham chiếu?

Các nhà phát triển chuyển sang lập trình Python từ các ngôn ngữ khác như C ++ và Java thường bị nhầm lẫn bởi quá trình truyền đối số trong Python. Mô hình dữ liệu lấy đối tượng làm trung tâm và cách xử lý phân công của nó là nguyên nhân đằng sau sự nhầm lẫn ở cấp độ cơ bản.  

Trong bài viết này, chúng ta sẽ thảo luận về khái niệm về cách truyền giá trị theo tham chiếu trong Python và cố gắng hiểu các ví dụ về truyền tham chiếu trong Python

Truyền theo giá trị và truyền theo tham chiếu trong Python

Bạn có thể muốn đấm một cái gì đó sau khi đọc trước, vì vậy hãy chuẩn bị tinh thần. Mô hình truyền đối số của Python không phải là “Truyền theo giá trị” hay “Truyền theo tham chiếu” mà là “Truyền theo tham chiếu đối tượng”.  

Có thể hiểu các mô hình “Truyền theo giá trị”, “Truyền theo tham chiếu” và “Truyền theo tham chiếu đối tượng” bằng cách khám phá các hàm ví dụ dưới đây. Nhìn vào hai chức năng được xác định dưới đây

Python3




def set_list(list):

    list = [

 a = ["X", "Y"]
0_______0_______1
 a = ["X", "Y"]
2
 a = ["X", "Y"]
1
 a = ["X", "Y"]
4
 a = ["X", "Y"]
5

    

 a = ["X", "Y"]
7 list

 

def def0list):

    listdef5def6def7

    

 a = ["X", "Y"]
7 list

 

set_list(1= [set_list(4

 a = ["X", "Y"]
5

 

set_list(6_______114_______7

 

set_list(6_______114_______9

đầu ra

['A', 'B', 'C']
['E', 'D']

Bây giờ, hãy cùng khám phá đoạn mã trên,

Biến không phải là đối tượng

Ở đây “a” là một biến trỏ đến một danh sách chứa phần tử “X” và “Y”. Nhưng bản thân “a” không phải là danh sách. Coi “a” là một nhóm chứa đối tượng “X” và “Y”.  

 a = ["X", "Y"]

Python vượt qua giá trị hoặc tràn ngăn xếp tham chiếu?

 

Pass by Reference trong Python là gì?

Truyền theo tham chiếu có nghĩa là bạn phải truyền hàm (tham chiếu) cho một biến chỉ rằng biến đó đã tồn tại trong bộ nhớ.  

Ở đây, biến (cái xô) được truyền trực tiếp vào hàm. Biến hoạt động như một Gói đi kèm với nội dung của nó (các đối tượng)

Python vượt qua giá trị hoặc tràn ngăn xếp tham chiếu?

 

Trong hình ảnh mã ở trên, cả “list” và “my_list” đều là cùng một biến vùng chứa và do đó đề cập đến chính xác cùng một đối tượng trong bộ nhớ. Bất kỳ hoạt động nào được thực hiện bởi hàm trên biến hoặc đối tượng sẽ được phản ánh trực tiếp bởi người gọi hàm. Chẳng hạn, hàm có thể thay đổi hoàn toàn nội dung của biến và trỏ nó vào một đối tượng hoàn toàn khác.  

Python vượt qua giá trị hoặc tràn ngăn xếp tham chiếu?

 

Ngoài ra, hàm có thể gán lại nội dung của biến với tác dụng tương tự như bên dưới.  

Python vượt qua giá trị hoặc tràn ngăn xếp tham chiếu?

 

Tóm lại, trong tham chiếu chuyển qua, hàm và người gọi sử dụng cùng một biến và đối tượng

Truyền theo giá trị trong Python là gì?

Theo cách tiếp cận này, chúng tôi chuyển một bản sao của các biến thực trong hàm dưới dạng tham số. Do đó, bất kỳ sửa đổi nào đối với các tham số bên trong hàm sẽ không phản ánh trong biến thực tế

Python vượt qua giá trị hoặc tràn ngăn xếp tham chiếu?

 

Điều này cũng đúng với mọi thao tác được thực hiện bởi hàm trên biến hoặc đối tượng

Python vượt qua giá trị hoặc tràn ngăn xếp tham chiếu?

 

Để tóm tắt các bản sao của các biến và các đối tượng trong ngữ cảnh của người gọi hàm là hoàn toàn bị cô lập

Có rất nhiều điều đơn giản bạn có thể làm để cải thiện JavaScript. Dưới đây là một số phương pháp chúng tôi sử dụng để viết JS tốt hơn

Ryland Goldstein Trưởng bộ phận sản phẩm tạm thời


Trong Khảo sát dành cho nhà phát triển năm 2019 của mình, chúng tôi đã hỏi người dùng Stack Overflow muốn xem loại nội dung nào ngoài câu hỏi và câu trả lời. Nhiều nhất là “các bài báo công nghệ được viết bởi các nhà phát triển khác. ” Vì vậy, từ bây giờ chúng tôi sẽ thường xuyên xuất bản các bài báo từ những người đóng góp. Nếu bạn có ý tưởng và muốn gửi quảng cáo chiêu hàng, bạn có thể gửi email cho pitches@stackoverflow. com



Xin chào, tôi là Ryland Goldstein, một nhân viên sản phẩm đang làm việc cho Reshuffle tại Binaris. Đây là tác phẩm thứ hai của tôi cho Stack Overflow. Nào cùng đào vào bên trong

Tôi không thấy đủ người nói về những cách thiết thực để cải thiện JavaScript. Dưới đây là một số phương pháp hàng đầu tôi sử dụng để viết JS tốt hơn

Sử dụng TypeScript

Điều số một bạn có thể làm để cải thiện JS của mình là không viết JS. Đối với những người không quen biết, TypeScript (TS) là một bộ siêu dữ liệu được “biên dịch” của JS (bất kỳ thứ gì chạy trong JS đều chạy trong TS). TS bổ sung một hệ thống gõ tùy chọn toàn diện trên trải nghiệm vanilla JS. Trong một thời gian dài, hỗ trợ TS trên toàn hệ sinh thái không nhất quán đến mức tôi cảm thấy không thoải mái khi giới thiệu nó. Rất may, những ngày đó đã ở phía sau chúng ta rất lâu và hầu hết các khung đều hỗ trợ TS ngay lập tức. Bây giờ tất cả chúng ta đều đã hiểu về TS là gì, hãy nói về lý do tại sao bạn muốn sử dụng nó

TypeScript thực thi an toàn kiểu

An toàn loại mô tả một quy trình trong đó trình biên dịch xác minh rằng tất cả các loại đang được sử dụng theo cách hợp pháp trong suốt một đoạn mã. Nói cách khác, nếu bạn tạo một hàm

console.log(foo("two")); // invalid TS code
8 nhận vào một số

function foo(someNum: number): number {
  return someNum + 5;
}

Hàm

console.log(foo("two")); // invalid TS code
8 đó chỉ nên được gọi với một số

good
console.log(foo(2)); // prints "7"
no good
console.log(foo("two")); // invalid TS code

Ngoài chi phí chung cho việc thêm các loại vào mã của bạn, không có nhược điểm nào đối với việc thực thi an toàn loại. Mặt khác, lợi ích quá lớn để bỏ qua. An toàn loại cung cấp một mức độ bảo vệ bổ sung chống lại các lỗi/lỗi phổ biến, đây là một điều may mắn đối với một ngôn ngữ vô luật như JS


Các loại Typescript giúp tái cấu trúc các ứng dụng lớn hơn có thể

Tái cấu trúc một ứng dụng JS lớn có thể là một cơn ác mộng thực sự. Hầu hết khó khăn của việc tái cấu trúc JS là do nó không thực thi chữ ký hàm. Điều này có nghĩa là một chức năng JS không bao giờ thực sự có thể bị lạm dụng. Ví dụ: nếu tôi có một chức năng

function myAPI(someNum, someString) {
  if (someNum > 0) {
    leakCredentials();
  } else {
    console.log(someString);
  }
}
0 được sử dụng bởi 1000 dịch vụ khác nhau

function myAPI(someNum, someString) {
  if (someNum > 0) {
    leakCredentials();
  } else {
    console.log(someString);
  }
}

và tôi thay đổi chữ ký cuộc gọi một chút

function myAPI(someString, someNum) {
  if (someNum > 0) {
    leakCredentials();
  } else {
    console.log(someString);
  }
}

Tôi phải chắc chắn 100% rằng mọi nơi sử dụng chức năng này (hàng nghìn nơi), tôi đều cập nhật chính xác cách sử dụng. Nếu tôi thậm chí bỏ lỡ một thông tin đăng nhập của tôi có thể bị rò rỉ. Đây là kịch bản tương tự với TS

before
function myAPITS(someNum: number, someString: string) { .. }
after
good
0

Như bạn có thể thấy, hàm

function myAPI(someNum, someString) {
  if (someNum > 0) {
    leakCredentials();
  } else {
    console.log(someString);
  }
}
1 đã trải qua thay đổi tương tự như đối tác JavaScript. Nhưng thay vì dẫn đến JavaScript hợp lệ, mã này dẫn đến TypeScript không hợp lệ, vì hàng nghìn nơi mã này được sử dụng hiện đang cung cấp sai loại. Và vì loại an toàn mà chúng ta đã thảo luận trước đó, hàng nghìn trường hợp đó sẽ chặn quá trình biên dịch và thông tin đăng nhập của bạn sẽ không bị rò rỉ (điều đó luôn luôn tốt)

TypeScript giúp giao tiếp kiến ​​trúc nhóm dễ dàng hơn

Khi TS được thiết lập chính xác, sẽ rất khó để viết mã mà không xác định trước các giao diện và lớp của bạn. Điều này cung cấp một cách để chia sẻ các đề xuất kiến ​​trúc ngắn gọn, giao tiếp. Trước TS, đã tồn tại các giải pháp khác cho vấn đề này, nhưng không có giải pháp nào giải quyết được nó một cách tự nhiên mà không khiến bạn phải làm thêm việc. Ví dụ: nếu tôi muốn đề xuất loại

function myAPI(someNum, someString) {
  if (someNum > 0) {
    leakCredentials();
  } else {
    console.log(someString);
  }
}
2 mới cho chương trình phụ trợ của mình, tôi có thể gửi nội dung sau cho đồng đội bằng TS

good
1

Tôi đã phải viết mã, nhưng bây giờ tôi có thể chia sẻ tiến trình gia tăng của mình và nhận phản hồi mà không cần đầu tư thêm thời gian. Tôi không biết liệu TS có ít lỗi hơn JS hay không. Tôi thực sự tin rằng việc buộc các nhà phát triển xác định giao diện và API trước tiên sẽ dẫn đến mã tốt hơn

Nhìn chung, TS đã phát triển thành một giải pháp thay thế hoàn thiện và dễ đoán hơn cho vanilla JS. Các nhà phát triển chắc chắn vẫn cần cảm thấy thoải mái với vanilla JS, nhưng hầu hết các dự án mới mà tôi bắt đầu hiện nay đều là TS ngay từ đầu

Python vượt qua giá trị hoặc tràn ngăn xếp tham chiếu?

Sử dụng các tính năng hiện đại

JavaScript là một trong những ngôn ngữ lập trình phổ biến nhất (nếu không muốn nói là nhiều nhất) trên thế giới. Bạn có thể mong đợi rằng một ngôn ngữ hơn 20 năm tuổi được sử dụng bởi hàng trăm triệu người sẽ hầu hết được tìm ra ngay bây giờ, nhưng thực tế thì ngược lại. Trong thời gian gần đây, nhiều thay đổi và bổ sung đã được thực hiện đối với JS (vâng, tôi biết, về mặt kỹ thuật là ECMAScript), về cơ bản đã thay đổi trải nghiệm của nhà phát triển. Là một người chỉ mới bắt đầu viết JS trong hai năm qua, tôi có lợi thế khi tham gia mà không có sự thiên vị hay kỳ vọng nào. Điều này dẫn đến nhiều lựa chọn thực dụng hơn về những tính năng nào của ngôn ngữ nên sử dụng và những tính năng nào nên tránh.

function myAPI(someNum, someString) { if (someNum > 0) { leakCredentials(); } else { console.log(someString); } }3 và function myAPI(someNum, someString) { if (someNum > 0) { leakCredentials(); } else { console.log(someString); } }4

Trong một thời gian dài, các cuộc gọi lại theo hướng sự kiện, không đồng bộ là một phần không thể tránh khỏi của quá trình phát triển JS

good
2_______14_______3

Tôi sẽ không dành thời gian giải thích lý do tại sao những điều trên lại có vấn đề (nhưng tôi đã từng làm trước đây). Để giải quyết vấn đề với các cuộc gọi lại, một khái niệm mới—Lời hứa—đã được thêm vào JS. Lời hứa cho phép bạn viết logic không đồng bộ trong khi tránh được các sự cố lồng nhau đã gây khó khăn cho mã dựa trên lệnh gọi lại trước đây

good
4
good
5

Ưu điểm lớn nhất của Lời hứa so với cuộc gọi lại là khả năng đọc và khả năng xâu chuỗi

Mặc dù Lời hứa rất tuyệt, nhưng họ vẫn để lại điều gì đó mong muốn. Đối với nhiều người, trải nghiệm Promise vẫn quá gợi nhớ đến các cuộc gọi lại. Cụ thể, các nhà phát triển đã yêu cầu một giải pháp thay thế cho mô hình Promise. Để khắc phục điều này, ủy ban ECMAScript đã quyết định thêm một phương pháp mới để sử dụng các lời hứa,

function myAPI(someNum, someString) {
  if (someNum > 0) {
    leakCredentials();
  } else {
    console.log(someString);
  }
}
3 và
function myAPI(someNum, someString) {
  if (someNum > 0) {
    leakCredentials();
  } else {
    console.log(someString);
  }
}
4

good
6_______14_______7

Một lưu ý là, bất cứ điều gì bạn

function myAPI(someNum, someString) {
  if (someNum > 0) {
    leakCredentials();
  } else {
    console.log(someString);
  }
}
4 phải được khai báo
function myAPI(someNum, someString) {
  if (someNum > 0) {
    leakCredentials();
  } else {
    console.log(someString);
  }
}
3

good
8
good
9

Cũng có thể

function myAPI(someNum, someString) {
  if (someNum > 0) {
    leakCredentials();
  } else {
    console.log(someString);
  }
}
4 một Lời hứa trực tiếp vì hàm
function myAPI(someNum, someString) {
  if (someNum > 0) {
    leakCredentials();
  } else {
    console.log(someString);
  }
}
3 thực sự chỉ là một trình bao bọc Lời hứa lạ mắt. Điều này cũng có nghĩa là mã
function myAPI(someString, someNum) {
  if (someNum > 0) {
    leakCredentials();
  } else {
    console.log(someString);
  }
}
1 và mã Hứa hẹn có chức năng tương đương. Vì vậy, hãy thoải mái sử dụng
function myAPI(someString, someNum) {
  if (someNum > 0) {
    leakCredentials();
  } else {
    console.log(someString);
  }
}
1 mà không cảm thấy tội lỗi

function myAPI(someString, someNum) { if (someNum > 0) { leakCredentials(); } else { console.log(someString); } }3 và function myAPI(someString, someNum) { if (someNum > 0) { leakCredentials(); } else { console.log(someString); } }4

Trong phần lớn thời gian tồn tại của JS, chỉ có một vòng loại phạm vi biến.

function myAPI(someString, someNum) {
  if (someNum > 0) {
    leakCredentials();
  } else {
    console.log(someString);
  }
}
5.
function myAPI(someString, someNum) {
  if (someNum > 0) {
    leakCredentials();
  } else {
    console.log(someString);
  }
}
5 có một số quy tắc khá độc đáo/thú vị liên quan đến cách nó xử lý phạm vi. Hành vi phạm vi của
function myAPI(someString, someNum) {
  if (someNum > 0) {
    leakCredentials();
  } else {
    console.log(someString);
  }
}
5 không nhất quán và khó hiểu và đã dẫn đến hành vi không mong muốn và do đó có lỗi trong suốt vòng đời của JS. Nhưng kể từ ES6, có một giải pháp thay thế cho
function myAPI(someString, someNum) {
  if (someNum > 0) {
    leakCredentials();
  } else {
    console.log(someString);
  }
}
5.
function myAPI(someString, someNum) {
  if (someNum > 0) {
    leakCredentials();
  } else {
    console.log(someString);
  }
}
4 và
function myAPI(someString, someNum) {
  if (someNum > 0) {
    leakCredentials();
  } else {
    console.log(someString);
  }
}
3. Thực tế không cần sử dụng
function myAPI(someString, someNum) {
  if (someNum > 0) {
    leakCredentials();
  } else {
    console.log(someString);
  }
}
5 nữa, vì vậy đừng. Bất kỳ logic nào sử dụng
function myAPI(someString, someNum) {
  if (someNum > 0) {
    leakCredentials();
  } else {
    console.log(someString);
  }
}
5 luôn có thể được chuyển đổi thành mã dựa trên
function myAPI(someString, someNum) {
  if (someNum > 0) {
    leakCredentials();
  } else {
    console.log(someString);
  }
}
4 và
function myAPI(someString, someNum) {
  if (someNum > 0) {
    leakCredentials();
  } else {
    console.log(someString);
  }
}
3 tương đương

Về thời điểm sử dụng

function myAPI(someString, someNum) {
  if (someNum > 0) {
    leakCredentials();
  } else {
    console.log(someString);
  }
}
4 so với
function myAPI(someString, someNum) {
  if (someNum > 0) {
    leakCredentials();
  } else {
    console.log(someString);
  }
}
3, tôi luôn bắt đầu bằng cách khai báo mọi thứ
function myAPI(someString, someNum) {
  if (someNum > 0) {
    leakCredentials();
  } else {
    console.log(someString);
  }
}
4.
function myAPI(someString, someNum) {
  if (someNum > 0) {
    leakCredentials();
  } else {
    console.log(someString);
  }
}
4 hạn chế hơn nhiều và “bất biến”, điều này thường dẫn đến mã tốt hơn. Không có nhiều “tình huống thực tế” trong đó việc sử dụng
function myAPI(someString, someNum) {
  if (someNum > 0) {
    leakCredentials();
  } else {
    console.log(someString);
  }
}
3 là cần thiết, tôi sẽ nói 1/20 biến tôi khai báo với
function myAPI(someString, someNum) {
  if (someNum > 0) {
    leakCredentials();
  } else {
    console.log(someString);
  }
}
3. Phần còn lại là tất cả
function myAPI(someString, someNum) {
  if (someNum > 0) {
    leakCredentials();
  } else {
    console.log(someString);
  }
}
4

Tôi đã nói

function myAPI(someString, someNum) {
  if (someNum > 0) {
    leakCredentials();
  } else {
    console.log(someString);
  }
}
4 là “bất biến” bởi vì nó không hoạt động theo cách giống như
function myAPI(someString, someNum) {
  if (someNum > 0) {
    leakCredentials();
  } else {
    console.log(someString);
  }
}
4 trong C/C++. Điều mà
function myAPI(someString, someNum) {
  if (someNum > 0) {
    leakCredentials();
  } else {
    console.log(someString);
  }
}
4 có ý nghĩa đối với thời gian chạy JavaScript là tham chiếu đến biến
function myAPI(someString, someNum) {
  if (someNum > 0) {
    leakCredentials();
  } else {
    console.log(someString);
  }
}
4 đó sẽ không bao giờ thay đổi. Điều này không có nghĩa là nội dung được lưu trữ tại tham chiếu đó sẽ không bao giờ thay đổi. Đối với các loại nguyên thủy (số, boolean, v.v. ),
function myAPI(someString, someNum) {
  if (someNum > 0) {
    leakCredentials();
  } else {
    console.log(someString);
  }
}
4 có nghĩa là bất biến (vì đó là một địa chỉ bộ nhớ duy nhất). Nhưng đối với tất cả các đối tượng (lớp, mảng, ký tự),
function myAPI(someString, someNum) {
  if (someNum > 0) {
    leakCredentials();
  } else {
    console.log(someString);
  }
}
4 không đảm bảo tính bất biến

Mũi tên function myAPITS(someNum: number, someString: string) { .. }8 Chức năng

Các hàm mũi tên là một phương pháp ngắn gọn để khai báo các hàm ẩn danh trong JS. Các hàm ẩn danh mô tả các hàm không được đặt tên rõ ràng. Thông thường, các hàm ẩn danh được chuyển dưới dạng gọi lại hoặc móc sự kiện

console.log(foo(2)); // prints "7"
0
console.log(foo(2)); // prints "7"
1

Phần lớn, không có gì "sai" với phong cách này. Các hàm ẩn danh Vanilla hoạt động “thú vị” về phạm vi, điều này có thể/đã dẫn đến nhiều lỗi không mong muốn. Chúng ta không phải lo lắng về điều đó nữa nhờ chức năng mũi tên. Đây là cùng một mã được triển khai với chức năng mũi tên

console.log(foo(2)); // prints "7"
2
console.log(foo(2)); // prints "7"
3

Ngoài việc ngắn gọn hơn nhiều, các hàm mũi tên có hành vi phạm vi thực tế hơn nhiều. Các hàm mũi tên kế thừa

function myAPITS(someNum: number, someString: string) { .. }
9 từ phạm vi mà chúng được xác định trong

Trong một số trường hợp, các hàm mũi tên có thể ngắn gọn hơn nữa

console.log(foo(2)); // prints "7"
4

Các hàm mũi tên nằm trên một dòng bao gồm một câu lệnh

after
0 ẩn. Không cần dấu ngoặc hoặc dấu chấm phẩy với các chức năng mũi tên một dòng

tôi muốn làm cho nó rõ ràng. Đây không phải là một tình huống

function myAPI(someString, someNum) {
  if (someNum > 0) {
    leakCredentials();
  } else {
    console.log(someString);
  }
}
5; . Điều đó đang được nói, tôi đã thấy rằng nếu bạn luôn đặt mặc định cho một hàm mũi tên, thì cuối cùng bạn sẽ ít phải gỡ lỗi hơn so với việc đặt mặc định cho các hàm ẩn danh vanilla

console.log(foo(2)); // prints "7"
5

Toán tử lây lan after2

Trích xuất các cặp khóa/giá trị của một đối tượng và thêm chúng làm con của một đối tượng khác là một kịch bản rất phổ biến. Trong lịch sử, đã có một số cách để thực hiện điều này, nhưng tất cả các phương pháp đó đều khá phức tạp.

console.log(foo(2)); // prints "7"
6

Mô hình này cực kỳ phổ biến, vì vậy cách tiếp cận trên nhanh chóng trở nên tẻ nhạt. Nhờ toán tử trải rộng, không bao giờ cần sử dụng lại

console.log(foo(2)); // prints "7"
7

Điều tuyệt vời là, điều này cũng hoạt động trơn tru với các mảng

console.log(foo(2)); // prints "7"
8

Nó có thể không phải là tính năng JS quan trọng nhất gần đây, nhưng nó là một trong những tính năng yêu thích của tôi

Chữ mẫu (Chuỗi mẫu)

Chuỗi là một trong những cấu trúc lập trình phổ biến nhất. Đây là lý do tại sao thật đáng xấu hổ khi các chuỗi khai báo nguyên gốc vẫn chưa được hỗ trợ ở nhiều ngôn ngữ. Một thời gian dài, JS thuộc họ “crappy string”. Nhưng việc bổ sung các chữ mẫu đã đặt JS vào một danh mục của riêng nó. Mẫu chữ tự nhiên và thuận tiện giải quyết hai vấn đề lớn nhất với việc viết chuỗi. thêm nội dung động và viết các chuỗi kết nối nhiều dòng

console.log(foo(2)); // prints "7"
9

Tôi nghĩ rằng mã nói cho chính nó. Thật là một triển khai tuyệt vời

Phá hủy đối tượng

Phá hủy đối tượng là một cách để trích xuất các giá trị từ bộ sưu tập dữ liệu (đối tượng, mảng, v.v. ), mà không cần phải lặp lại dữ liệu hoặc truy cập các khóa của nó một cách rõ ràng

no good
0
no good
1

hủy diệt

no good
2

Nhưng xin chờ chút nữa. Bạn cũng có thể định nghĩa phá hủy trong chữ ký của hàm

no good
3_______16_______4

Nó cũng hoạt động với mảng

no good
5
no good
6

Có rất nhiều tính năng hiện đại khác mà bạn nên sử dụng. Dưới đây là một số ít những người khác nổi bật với tôi

  • Thông số nghỉ ngơi
  • Nhập quá yêu cầu
  • Tìm phần tử mảng

Luôn cho rằng hệ thống của bạn được phân phối

Khi viết các ứng dụng song song, mục tiêu của bạn là tối ưu hóa lượng công việc bạn đang làm cùng một lúc. Nếu bạn có sẵn bốn lõi và mã của bạn chỉ có thể sử dụng một lõi, thì 75% tiềm năng của bạn đang bị lãng phí. Điều này có nghĩa là chặn, các hoạt động đồng bộ là kẻ thù cuối cùng của điện toán song song. Nhưng xem xét rằng JS là một ngôn ngữ đơn luồng, mọi thứ không chạy trên nhiều lõi. Vậy vấn đề là gì?

JS là một luồng, nhưng không phải là tệp đơn (như trong các dòng ở trường). Dù không song song nhưng vẫn đồng quy. Việc gửi một yêu cầu HTTP có thể mất vài giây hoặc thậm chí vài phút, vì vậy nếu JS ngừng thực thi mã cho đến khi có phản hồi từ yêu cầu, thì ngôn ngữ đó sẽ không sử dụng được

JavaScript giải quyết vấn đề này bằng một vòng lặp sự kiện. Vòng lặp sự kiện lặp qua các sự kiện đã đăng ký và thực hiện chúng dựa trên logic lập lịch/ưu tiên nội bộ. Đây là thứ cho phép gửi hàng nghìn yêu cầu HTTP đồng thời hoặc đọc nhiều tệp từ đĩa cùng một lúc. Đây là bắt. JavaScript chỉ có thể sử dụng khả năng này nếu bạn sử dụng đúng tính năng. Ví dụ đơn giản nhất là vòng lặp for

no good
7

Vanilla for-loop là một trong những cấu trúc song song nhất tồn tại trong lập trình. Ở công việc cuối cùng của mình, tôi đã lãnh đạo một nhóm dành nhiều tháng để cố gắng chuyển đổi các vòng lặp for-lang truyền thống thành mã song song tự động. Về cơ bản, đó là một vấn đề bất khả thi, chỉ có thể giải quyết được bằng cách chờ học sâu cải thiện. Khó khăn trong việc song song hóa vòng lặp for bắt nguồn từ một số mẫu có vấn đề. Các vòng lặp for tuần tự rất hiếm gặp, nhưng chỉ riêng chúng khiến không thể đảm bảo khả năng phân tách của các vòng lặp for

no good
8

Mã này chỉ tạo ra kết quả dự kiến ​​nếu nó được thực thi theo thứ tự, lặp đi lặp lại. Nếu bạn cố thực hiện nhiều lần lặp cùng một lúc, bộ xử lý có thể phân nhánh không chính xác dựa trên các giá trị không chính xác, điều này làm mất hiệu lực kết quả. Chúng ta sẽ có một cuộc trò chuyện khác nếu đây là mã C, vì cách sử dụng khác nhau và có khá nhiều thủ thuật mà trình biên dịch có thể thực hiện với các vòng lặp. Trong JavaScript, các vòng lặp truyền thống chỉ nên được sử dụng nếu thực sự cần thiết. Mặt khác, sử dụng các cấu trúc sau



bản đồ

no good
9

bản đồ với chỉ số

console.log(foo("two")); // invalid TS code
0

cho mỗi

console.log(foo("two")); // invalid TS code
1

Tôi sẽ giải thích tại sao đây là một cải tiến so với các vòng lặp for truyền thống. Thay vì thực hiện từng lần lặp theo thứ tự (tuần tự), các cấu trúc như

after
4 lấy tất cả các phần tử và gửi chúng dưới dạng các sự kiện riêng lẻ cho hàm bản đồ do người dùng xác định. Phần lớn, các bước lặp riêng lẻ không có kết nối hoặc phụ thuộc vốn có với nhau, cho phép chúng chạy đồng thời. Điều này không có nghĩa là bạn không thể hoàn thành điều tương tự với các vòng lặp for. Trong thực tế, nó sẽ trông giống như thế này

console.log(foo("two")); // invalid TS code
2

Như bạn có thể thấy, vòng lặp for không ngăn cản tôi thực hiện đúng cách, nhưng nó chắc chắn cũng không làm cho việc đó trở nên dễ dàng hơn. So sánh với phiên bản bản đồ

console.log(foo("two")); // invalid TS code
3

Như bạn có thể thấy,

after
4 chỉ hoạt động. Ưu điểm của bản đồ càng trở nên rõ ràng hơn nếu bạn muốn chặn cho đến khi hoàn thành tất cả các thao tác không đồng bộ riêng lẻ. Với mã vòng lặp for, bạn sẽ cần tự mình quản lý một mảng. Đây là phiên bản
after
4

console.log(foo("two")); // invalid TS code
4
console.log(foo("two")); // invalid TS code
5

Có nhiều trường hợp vòng lặp for có hiệu suất tương đương (hoặc có thể hơn) so với

after
4 hoặc
after
8. Tôi vẫn tranh luận rằng việc mất một vài chu kỳ bây giờ đáng để tận dụng lợi thế của việc sử dụng API được xác định rõ. Bằng cách đó, mọi cải tiến trong tương lai đối với việc triển khai các mẫu truy cập dữ liệu đó sẽ có lợi cho mã của bạn. Vòng lặp for quá chung chung để có các tối ưu hóa có ý nghĩa cho cùng một mẫu đó

Có các tùy chọn không đồng bộ hợp lệ khác bên ngoài
after
4 và
after
8, chẳng hạn như
good
01

Lint mã của bạn và thực thi một phong cách

Mã không có phong cách nhất quán (nhìn và cảm nhận) cực kỳ khó đọc và hiểu. Do đó, một khía cạnh quan trọng của việc viết mã cao cấp bằng bất kỳ ngôn ngữ nào là có một phong cách nhất quán và hợp lý. Do bề rộng của hệ sinh thái JS, có RẤT NHIỀU tùy chọn cho các chi tiết cụ thể về kiểu dáng và kiểu dáng. Điều tôi không thể nhấn mạnh đủ là việc bạn đang sử dụng kẻ nói dối và thực thi một phong cách (bất kỳ kiểu nào) quan trọng hơn nhiều so với việc bạn chọn cụ thể kiểu kẻ nói dối/phong cách nào. Vào cuối ngày, sẽ không có ai viết mã chính xác như tôi sẽ làm, vì vậy việc tối ưu hóa cho điều đó là một mục tiêu phi thực tế

Mình thấy nhiều người hỏi nên dùng eslint hay dùng đẹp hơn. Đối với tôi, chúng phục vụ các mục đích rất khác nhau và do đó nên được sử dụng kết hợp. Eslint là một kẻ nói dối truyền thống hầu hết thời gian. Nó sẽ xác định các vấn đề với mã của bạn ít liên quan đến phong cách hơn và liên quan nhiều hơn đến tính chính xác. Ví dụ: tôi sử dụng eslint với quy tắc AirBNB. Với cấu hình đó, đoạn mã sau sẽ buộc kẻ nói dối thất bại

console.log(foo("two")); // invalid TS code
6

Rõ ràng là cách eslint gia tăng giá trị cho chu kỳ phát triển của bạn. Về bản chất, nó đảm bảo bạn tuân theo các quy tắc về những gì được và không được thực hành tốt. Do đó, linters vốn cố chấp. Như với tất cả các ý kiến, hãy coi nó như một hạt muối. Kẻ nói dối có thể sai

Prettier là một trình định dạng mã. Nó ít quan tâm đến tính đúng đắn và lo lắng nhiều hơn về tính đồng nhất và nhất quán. Prettier sẽ không phàn nàn về việc sử dụng

function myAPI(someString, someNum) {
  if (someNum > 0) {
    leakCredentials();
  } else {
    console.log(someString);
  }
}
5, nhưng nó sẽ tự động căn chỉnh tất cả các dấu ngoặc trong mã của bạn. Trong quá trình phát triển cá nhân của tôi, tôi luôn chạy đẹp hơn ở bước cuối cùng trước khi đẩy mã lên Git. Trong nhiều trường hợp, thậm chí còn hợp lý hơn khi Prettier chạy tự động trên mỗi lần xác nhận vào repo. Điều này đảm bảo rằng tất cả mã đi vào kiểm soát nguồn có kiểu dáng và cấu trúc nhất quán

Kiểm tra mã của bạn

Viết bài kiểm tra là một phương pháp gián tiếp nhưng vô cùng hiệu quả để cải thiện mã JS mà bạn viết. Tôi khuyên bạn nên trở nên thoải mái với một loạt các công cụ kiểm tra. Nhu cầu thử nghiệm của bạn sẽ khác nhau và không có công cụ duy nhất nào có thể xử lý mọi thứ. Có rất nhiều công cụ kiểm tra được thiết lập tốt trong hệ sinh thái JS, vì vậy việc chọn công cụ chủ yếu tùy thuộc vào sở thích cá nhân. Như mọi khi, hãy nghĩ cho chính mình

Python có vượt qua giá trị hoặc tham chiếu không?

Python truyền các đối số không phải theo tham chiếu hay theo giá trị mà theo phép gán.

Có thể chuyển qua tham chiếu trong Python không?

Mô hình truyền đối số của Python không phải là “Truyền theo giá trị” hay “Truyền theo tham chiếu” mà là “Truyền theo tham chiếu đối tượng”