Làm cách nào để trả về nhiều giá trị từ một hàm? [đóng cửa]


1067

Cách chính tắc để trả về nhiều giá trị trong các ngôn ngữ hỗ trợ nó thường là tupling .

Tùy chọn: Sử dụng bộ dữ liệu

Hãy xem xét ví dụ tầm thường này:

def f(x):
  y0 = x + 1
  y1 = x * 3
  y2 = y0 ** y3
  return (y0, y1, y2)

Tuy nhiên, điều này nhanh chóng gặp vấn đề khi số lượng giá trị được trả về tăng lên. Điều gì nếu bạn muốn trả về bốn hoặc năm giá trị? Chắc chắn, bạn có thể tiếp tục sử dụng chúng, nhưng thật dễ dàng để quên giá trị đó ở đâu. Nó cũng khá xấu xí để giải nén chúng bất cứ nơi nào bạn muốn nhận chúng.

Tùy chọn: Sử dụng từ điển

Bước hợp lý tiếp theo dường như là giới thiệu một số loại 'ký hiệu hồ sơ'. Trong Python, cách rõ ràng để làm điều này là bằng cách a dict.

Hãy xem xét những điều sau đây:

def g(x):
  y0 = x + 1
  y1 = x * 3
  y2 = y0 ** y3
  return {'y0': y0, 'y1': y1 ,'y2': y2}

(Nói rõ hơn, y0, y1 và y2 chỉ có nghĩa là các định danh trừu tượng. Như đã chỉ ra, trong thực tế, bạn sử dụng các định danh có ý nghĩa.)

Bây giờ, chúng ta có một cơ chế theo đó chúng ta có thể chiếu ra một thành viên cụ thể của đối tượng được trả về. Ví dụ,

result['y0']

Tùy chọn: Sử dụng một lớp

Tuy nhiên, có một lựa chọn khác. Thay vào đó chúng ta có thể trả về một cấu trúc chuyên biệt. Tôi đã đóng khung cái này trong ngữ cảnh của Python, nhưng tôi chắc chắn nó cũng áp dụng cho các ngôn ngữ khác. Thật vậy, nếu bạn đang làm việc trong C thì đây rất có thể là lựa chọn duy nhất của bạn. Đây là:

class ReturnValue:
  def __init__(self, y0, y1, y2):
     self.y0 = y0
     self.y1 = y1
     self.y2 = y2

def g(x):
  y0 = x + 1
  y1 = x * 3
  y2 = y0 ** y3
  return ReturnValue(y0, y1, y2)

Trong Python, hai cái trước có lẽ rất giống nhau về hệ thống ống nước - sau khi tất cả { y0, y1, y2 }cuối cùng chỉ là mục trong nội bộ __dict__của ReturnValue.

Có một tính năng bổ sung được cung cấp bởi Python mặc dù đối với các đối tượng nhỏ, __slots__thuộc tính. Các lớp có thể được thể hiện như sau:

class ReturnValue(object):
  __slots__ = ["y0", "y1", "y2"]
  def __init__(self, y0, y1, y2):
     self.y0 = y0
     self.y1 = y1
     self.y2 = y2

Từ tài liệu tham khảo Python :

Các __slots__tuyên bố mất một chuỗi các biến dụ và dự trữ chỉ đủ không gian trong mỗi trường hợp để giữ giá trị cho mỗi biến. Không gian được lưu vì __dict__không được tạo cho mỗi phiên bản.

Tùy chọn: Sử dụng một dataclass (Python 3.7+)

Sử dụng các bảng dữ liệu mới của Python 3.7, trả về một lớp với các phương thức đặc biệt được thêm tự động, gõ và các công cụ hữu ích khác:

@dataclass
class Returnvalue:
    y0: int
    y1: float
    y3: int

def total_cost(x):
    y0 = x + 1
    y1 = x * 3
    y2 = y0 ** y3
    return ReturnValue(y0, y1, y2)

Tùy chọn: Sử dụng danh sách

Một đề nghị khác mà tôi đã bỏ qua đến từ Bill the Lizard:

def h(x):
  result = [x + 1]
  result.append(x * 3)
  result.append(y0 ** y3)
  return result

Đây là phương pháp ít yêu thích nhất của tôi mặc dù. Tôi cho rằng tôi đã bị vấy bẩn khi tiếp xúc với Haskell, nhưng ý tưởng về danh sách hỗn hợp luôn khiến tôi cảm thấy khó chịu. Trong ví dụ cụ thể này, danh sách là loại hỗn hợp, nhưng có thể hiểu được.

Một danh sách được sử dụng theo cách này thực sự không đạt được bất cứ điều gì liên quan đến bộ dữ liệu như tôi có thể nói. Sự khác biệt thực sự duy nhất giữa danh sách và bộ dữ liệu trong Python là danh sách có thể thay đổi , trong khi bộ dữ liệu thì không.

Cá nhân tôi có xu hướng thực hiện các quy ước từ lập trình chức năng: sử dụng danh sách cho bất kỳ số lượng phần tử nào cùng loại và bộ dữ liệu cho một số phần tử cố định của các loại được xác định trước.

Câu hỏi

Sau lời mở đầu dài, đến câu hỏi không thể tránh khỏi. Phương pháp nào (bạn nghĩ) là tốt nhất?


10
Trong các ví dụ tuyệt vời của bạn, bạn sử dụng biến y3, nhưng trừ khi y3 được khai báo toàn cầu, điều này có thể mang lại NameError: global name 'y3' is not definedchỉ là sử dụng 3?
hetepeperfan

11
Nhiều câu hỏi tuyệt vời với câu trả lời tuyệt vời đã bị đóng vì từ khóa 'ý kiến' xuất hiện. Bạn có thể tranh luận toàn bộ SO dựa trên ý kiến, nhưng ý kiến ​​đó được thông báo bởi các sự kiện, tài liệu tham khảo và chuyên môn cụ thể. Chỉ vì ai đó hỏi "bạn nghĩ điều gì là tốt nhất" không có nghĩa là họ hỏi ý kiến ​​cá nhân được trừu tượng hóa từ các sự kiện, tài liệu tham khảo và chuyên môn cụ thể trong thế giới thực. Họ gần như chắc chắn yêu cầu chính xác loại ý kiến ​​đó, loại dựa trên kỹ lưỡng và được ghi lại bằng các sự kiện, tài liệu tham khảo và chuyên môn cụ thể mà người đó sử dụng để hình thành ý kiến.
NeilG

@hetepeperfan không cần thay đổi 3 và cũng không xác định y3 trong toàn cầu, bạn cũng có thể sử dụng tên địa phương y3, điều đó cũng sẽ làm công việc tương tự.
okie

Câu trả lời:


637

Các bộ dữ liệu được đặt tên đã được thêm vào 2.6 cho mục đích này. Cũng xem os.stat cho một ví dụ dựng sẵn tương tự.

>>> import collections
>>> Point = collections.namedtuple('Point', ['x', 'y'])
>>> p = Point(1, y=2)
>>> p.x, p.y
1 2
>>> p[0], p[1]
1 2

Trong các phiên bản gần đây của Python 3 (3.6+, tôi nghĩ vậy), typingthư viện mới có NamedTuplelớp để làm cho các bộ dữ liệu được đặt tên dễ dàng hơn để tạo và mạnh hơn. Kế thừa từ typing.NamedTuplecho phép bạn sử dụng tài liệu, giá trị mặc định và chú thích loại.

Ví dụ (Từ các tài liệu):

class Employee(NamedTuple):  # inherit from typing.NamedTuple
    name: str
    id: int = 3  # default value

employee = Employee('Guido')
assert employee.id == 3

68
Đây chỉ là câu trả lời đúng vì đây là cấu trúc chính tắc duy nhất mà OP không xem xét và vì nó giải quyết vấn đề của anh ta trong việc quản lý các bộ dữ liệu dài. Nên được đánh dấu là chấp nhận.
cuộc không kích

7
Chà, lý do thiết kế cho namedtupleviệc có dung lượng bộ nhớ nhỏ hơn cho kết quả hàng loạt (danh sách dài các bộ dữ liệu, chẳng hạn như kết quả của các truy vấn DB). Đối với các mục riêng lẻ (nếu chức năng trong câu hỏi không được gọi thường xuyên) từ điển và các lớp cũng tốt. Nhưng têntuples là một giải pháp tốt đẹp / đẹp hơn trong trường hợp này là tốt.
Lutz Prechelt

8
@wom: Đừng làm điều này. Python không nỗ lực để namedtuplexác định các định nghĩa (mỗi cuộc gọi tạo ra một định nghĩa mới), tạo ra namedtuplelớp tương đối tốn kém về cả CPU và bộ nhớ và tất cả các định nghĩa lớp về bản chất đều liên quan đến các tham chiếu theo chu kỳ (vì vậy, trên CPython, bạn đang chờ chạy GC theo chu kỳ cho họ được phát hành). Nó cũng làm cho picklelớp không thể (và do đó, không thể sử dụng các thể hiện multiprocessingtrong hầu hết các trường hợp). Mỗi lần tạo lớp trên 3.6.4 x64 của tôi tiêu tốn ~ 0,337 ms và chỉ chiếm dưới 1 KB bộ nhớ, giết chết mọi khoản tiết kiệm cá thể.
ShadowRanger

3
Tôi sẽ lưu ý, Python 3.7 đã cải thiện tốc độ tạo các namedtuplelớp mới ; chi phí CPU giảm khoảng 4 lần , nhưng chúng vẫn cao hơn khoảng 1000 lần so với chi phí để tạo một cá thể và chi phí bộ nhớ cho mỗi lớp vẫn cao (tôi đã sai trong nhận xét cuối cùng của tôi về "dưới 1 KB" đối với lớp, _sourcebản thân nó thường là 1,5 KB, _sourceđược loại bỏ trong 3.7, do đó, nó có thể gần với yêu cầu ban đầu chỉ dưới 1 KB mỗi lần tạo lớp).
ShadowRanger

4
@SergeStroobandt - Đây là một phần của thư viện chuẩn, không phải là nội dung. Bạn không cần lo lắng rằng nó có thể không được cài đặt trên một hệ thống khác với Python> = 2.6. Hay bạn chỉ phản đối dòng mã bổ sung?
Justin

234

Đối với các dự án nhỏ, tôi thấy dễ dàng nhất để làm việc với bộ dữ liệu. Khi điều đó trở nên quá khó để quản lý (và không phải trước đây), tôi bắt đầu nhóm các thứ thành các cấu trúc logic, tuy nhiên tôi nghĩ rằng việc sử dụng từ điển và ReturnValueđối tượng được đề xuất của bạn là sai (hoặc quá đơn giản).

Quay trở lại một cuốn từ điển với các phím "y0", "y1", "y2"vv không cung cấp bất kỳ lợi thế hơn các bộ. Trả về một ReturnValueví dụ với các thuộc tính .y0, .y1, .y2vv không cung cấp bất kỳ lợi thế hơn các tuple một trong hai. Bạn cần bắt đầu đặt tên mọi thứ nếu bạn muốn đến bất cứ nơi nào và bạn có thể làm điều đó bằng cách sử dụng bộ dữ liệu:

def get_image_data(filename):
    [snip]
    return size, (format, version, compression), (width,height)

size, type, dimensions = get_image_data(x)

IMHO, kỹ thuật tốt duy nhất ngoài các bộ dữ liệu là trả về các đối tượng thực với các phương thức và thuộc tính phù hợp, như bạn nhận được từ re.match()hoặc open(file).


6
Câu hỏi - có sự khác biệt giữa size, type, dimensions = getImageData(x)(size, type, dimensions) = getImageData(x)? Tức là, việc bọc bên trái của một nhiệm vụ khó khăn có làm nên sự khác biệt nào không?
Reb.Cabin

11
@ Reb.Cabin Không có sự khác biệt. Tuple được xác định bằng dấu phẩy và việc sử dụng dấu ngoặc đơn chỉ để nhóm các thứ lại với nhau. Ví dụ (1)là một int trong khi (1,)hoặc 1,là một tuple.
phil

19
Re "trả lại một từ điển với các khóa y0, y1, y2, v.v. không cung cấp bất kỳ lợi thế nào cho các bộ dữ liệu": từ điển có lợi thế ở chỗ bạn có thể thêm các trường vào từ điển được trả về mà không phá vỡ mã hiện có.
Ostrokach

Re "trả lại một từ điển với các khóa y0, y1, y2, v.v. không cung cấp bất kỳ lợi thế nào cho các bộ dữ liệu": nó cũng dễ đọc hơn và ít bị lỗi hơn khi bạn truy cập dữ liệu dựa trên tên của nó thay vì vị trí.
Denis Dollfus

204

Rất nhiều câu trả lời gợi ý bạn cần trả về một bộ sưu tập nào đó, như từ điển hoặc danh sách. Bạn có thể bỏ cú pháp phụ và chỉ cần viết ra các giá trị trả về, được phân tách bằng dấu phẩy. Lưu ý: về mặt kỹ thuật này trả về một tuple.

def f():
    return True, False
x, y = f()
print(x)
print(y)

cho:

True
False

24
Bạn vẫn đang trả lại một bộ sưu tập. Đó là một tuple. Tôi thích ngoặc đơn để làm cho nó rõ ràng hơn. Hãy thử điều này: type(f())trả về <class 'tuple'>.
Igor

20
@Igor: Không có lý do để làm cho tuplekhía cạnh rõ ràng; Việc bạn trở về a không thực sự quan trọng tuple, đây là thành ngữ để trả về nhiều khoảng thời gian giá trị. Cùng một lý do bạn bỏ qua các parens với thành ngữ hoán đổi x, y = y, x, nhiều khởi tạo x, y = 0, 1, v.v.; chắc chắn, nó làm cho tuples dưới mui xe, nhưng không có lý do để làm cho rõ ràng, vì tuplenó không phải là điểm chính. Hướng dẫn Python giới thiệu nhiều bài tập dài trước khi nó chạm vào tuples.
ShadowRanger

@ShadowRanger bất kỳ chuỗi giá trị nào được phân tách bằng dấu phẩy ở phía bên phải =là một tuple trong Python có hoặc không có dấu ngoặc đơn xung quanh chúng. Vì vậy, thực sự không có rõ ràng hoặc ẩn ở đây. a, b, c là một tuple nhiều như (a, b, c). Cũng không có bộ ba "dưới mui xe" khi bạn trả về các giá trị như vậy, bởi vì nó chỉ là một bộ đơn giản đơn giản. OP đã đề cập đến các bộ dữ liệu vì vậy thực sự không có sự khác biệt giữa những gì anh ấy đề cập và những gì câu trả lời này cho thấy. Không có
Ken4schologists

2
Đây là nghĩa đen tùy chọn đầu tiên gợi ý trong câu hỏi
endolith

1
@endolith Hai lần anh chàng đặt câu hỏi ("Làm thế nào để tôi trả lại nhiều giá trị?" và "Làm thế nào để bạn trả lại nhiều giá trị?") được trả lời bằng câu trả lời này. Văn bản của câu hỏi đôi khi đã thay đổi. Và đó là một câu hỏi dựa trên ý kiến.
Joseph Hansen

74

Tôi bỏ phiếu cho từ điển.

Tôi thấy rằng nếu tôi tạo một hàm trả về bất cứ thứ gì nhiều hơn 2-3 biến tôi sẽ gấp chúng lại trong một từ điển. Nếu không, tôi có xu hướng quên thứ tự và nội dung của những gì tôi sẽ trở lại.

Ngoài ra, việc giới thiệu cấu trúc 'đặc biệt' làm cho mã của bạn khó theo dõi hơn. (Người khác sẽ phải tìm kiếm thông qua mã để tìm hiểu nó là gì)

Nếu bạn quan tâm về loại tra cứu, hãy sử dụng các khóa từ điển mô tả, ví dụ, 'danh sách giá trị x'.

def g(x):
  y0 = x + 1
  y1 = x * 3
  y2 = y0 ** y3
  return {'y0':y0, 'y1':y1 ,'y2':y2 }

5
sau nhiều năm lập trình, tôi hướng đến cấu trúc của dữ liệu và chức năng là bắt buộc. Chức năng đầu tiên, bạn luôn có thể cấu trúc lại khi cần thiết.
monkut

Làm thế nào chúng ta có được các giá trị trong từ điển mà không gọi hàm nhiều lần? Ví dụ, nếu tôi muốn sử dụng y1 và y3 trong một chức năng khác nhau?
Matt

3
gán kết quả cho một biến riêng biệt. result = g(x); other_function(result)
monkut

1
@monkut có. Cách này cũng cho phép truyền kết quả cho một số hàm, lấy các đối số khác nhau từ kết quả, mà không phải tham chiếu cụ thể các phần cụ thể của kết quả mỗi lần.
Gnudiff

38

Một lựa chọn khác sẽ là sử dụng máy phát điện:

>>> def f(x):
        y0 = x + 1
        yield y0
        yield x * 3
        yield y0 ** 4


>>> a, b, c = f(5)
>>> a
6
>>> b
15
>>> c
1296

Mặc dù các bộ dữ liệu IMHO thường là tốt nhất, ngoại trừ trong trường hợp các giá trị được trả về là các ứng cử viên để đóng gói trong một lớp.


1
Đây có vẻ là giải pháp sạch nhất và có cú pháp rõ ràng. Có bất kỳ nhược điểm này? Nếu bạn không sử dụng tất cả lợi nhuận, có những sản lượng 'chưa được biết' đang chờ để làm tổn thương bạn?
Jiminion

24
Điều này có thể là "sạch", nhưng nó dường như không trực quan chút nào. Làm thế nào một người chưa bao giờ gặp phải mô hình này trước khi biết rằng việc tự động giải nén bộ giải nén sẽ kích hoạt từng mẫu yield?
coredumperror

1
@CoreDumpError, máy phát điện chỉ là máy phát điện. Không có sự khác biệt bên ngoài giữa def f(x): …; yield b; yield a; yield rso với (g for g in [b, a, r]), và cả hai sẽ dễ dàng chuyển đổi thành danh sách hoặc bộ dữ liệu, và như vậy sẽ hỗ trợ bộ giải nén. Biểu mẫu bộ tạo tuple tuân theo cách tiếp cận chức năng, trong khi dạng hàm là bắt buộc và sẽ cho phép điều khiển luồng và gán biến.
sleblanc

30

Tôi thích sử dụng tuple bất cứ khi nào một tuple cảm thấy "tự nhiên"; tọa độ là một ví dụ điển hình, trong đó các đối tượng riêng biệt có thể tự đứng, ví dụ: trong các phép tính tỷ lệ chỉ một trục và thứ tự là quan trọng. Lưu ý: nếu tôi có thể sắp xếp hoặc xáo trộn các mục mà không ảnh hưởng xấu đến ý nghĩa của nhóm, thì có lẽ tôi không nên sử dụng một tuple.

Tôi chỉ sử dụng từ điển làm giá trị trả về khi các đối tượng được nhóm không phải lúc nào cũng giống nhau. Hãy suy nghĩ tiêu đề email tùy chọn.

Đối với các trường hợp còn lại, trong đó các đối tượng được nhóm có ý nghĩa vốn có bên trong nhóm hoặc một đối tượng chính thức với các phương thức riêng của nó là cần thiết, tôi sử dụng một lớp.


29

Tôi thích:

def g(x):
  y0 = x + 1
  y1 = x * 3
  y2 = y0 ** y3
  return {'y0':y0, 'y1':y1 ,'y2':y2 }

Dường như mọi thứ khác chỉ là mã bổ sung để làm điều tương tự.


22
Tuples dễ dàng hơn để giải nén: y0, y1, y2 = g () với một lệnh bạn phải làm: result = g () y0, y1, y2 = result.get ('y0'), result.get ('y1' ), result.get ('y2') hơi xấu xí. Mỗi giải pháp đều có 'điểm cộng' và 'điểm trừ'.
Oli

27
>>> def func():
...    return [1,2,3]
...
>>> a,b,c = func()
>>> a
1
>>> b
2
>>> c
3

@edouard Không, không, nó trả về một tuple không phải là một danh sách.
Simon Hibbs

1
destructuring là những lập luận cho trở lại danh sách theo ý kiến của tôi
semiomant

21

Nói chung, "cấu trúc chuyên biệt" thực sự là một trạng thái hiện tại hợp lý của một đối tượng, với các phương thức riêng của nó.

class Some3SpaceThing(object):
  def __init__(self,x):
    self.g(x)
  def g(self,x):
    self.y0 = x + 1
    self.y1 = x * 3
    self.y2 = y0 ** y3

r = Some3SpaceThing( x )
r.y0
r.y1
r.y2

Tôi muốn tìm tên cho các cấu trúc ẩn danh nếu có thể. Tên có ý nghĩa làm cho mọi thứ rõ ràng hơn.


20

Các tuples, dicts và object của Python cung cấp cho người lập trình một sự đánh đổi suôn sẻ giữa hình thức và sự thuận tiện cho các cấu trúc dữ liệu nhỏ ("mọi thứ"). Đối với tôi, sự lựa chọn làm thế nào để đại diện cho một thứ được quyết định chủ yếu bởi cách tôi sẽ sử dụng cấu trúc. Trong C ++, đó là quy ước chung để sử dụng structcho các mục chỉ dữ liệu và classcho các đối tượng có phương thức, mặc dù bạn có thể đặt phương thức một cách hợp pháp trên a struct; thói quen của tôi là tương tự với Python, với dicttuplethay thếstruct .

Đối với các bộ tọa độ, tôi sẽ sử dụng tuplethay vì một điểm classhoặc một dict(và lưu ý rằng bạn có thể sử dụng tuplelàm khóa từ điển, do đó dict, tạo ra các mảng đa chiều thưa thớt tuyệt vời).

Nếu tôi sẽ lặp đi lặp lại một danh sách các thứ, tôi thích giải nén tuples trên vòng lặp:

for score,id,name in scoreAllTheThings():
    if score > goodScoreThreshold:
        print "%6.3f #%6d %s"%(score,id,name)

... khi phiên bản đối tượng lộn xộn hơn để đọc:

for entry in scoreAllTheThings():
    if entry.score > goodScoreThreshold:
        print "%6.3f #%6d %s"%(entry.score,entry.id,entry.name)

... chứ chưa nói đến dict.

for entry in scoreAllTheThings():
    if entry['score'] > goodScoreThreshold:
        print "%6.3f #%6d %s"%(entry['score'],entry['id'],entry['name'])

Nếu thứ đó được sử dụng rộng rãi và bạn thấy mình thực hiện các hoạt động không tầm thường tương tự trên nó ở nhiều nơi trong mã, thì thường đáng để biến nó thành một đối tượng lớp với các phương thức thích hợp.

Cuối cùng, nếu tôi sẽ trao đổi dữ liệu với các thành phần hệ thống không phải là Python, tôi thường sẽ giữ chúng trong một dictvì nó phù hợp nhất với tuần tự hóa JSON.


19

+1 trên đề xuất của S.Lott về một lớp container có tên.

Đối với Python 2.6 trở lên, một bộ dữ liệu có tên cung cấp một cách hữu ích để dễ dàng tạo các lớp chứa này và kết quả là "nhẹ và không cần nhiều bộ nhớ hơn các bộ dữ liệu thông thường".


4

Trong các ngôn ngữ như Python, tôi thường sử dụng một từ điển vì nó liên quan đến ít chi phí hơn là tạo một lớp mới.

Tuy nhiên, nếu tôi thấy mình liên tục trả về cùng một bộ biến, thì điều đó có thể liên quan đến một lớp mới mà tôi sẽ đưa ra.


4

Tôi sẽ sử dụng một dict để truyền và trả về các giá trị từ một hàm:

Sử dụng hình thức biến như được định nghĩa trong hình thức .

form = {
    'level': 0,
    'points': 0,
    'game': {
        'name': ''
    }
}


def test(form):
    form['game']['name'] = 'My game!'
    form['level'] = 2

    return form

>>> print(test(form))
{u'game': {u'name': u'My game!'}, u'points': 0, u'level': 2}

Đây là cách hiệu quả nhất cho tôi và cho đơn vị xử lý.

Bạn phải vượt qua chỉ một con trỏ và trả lại chỉ một con trỏ.

Bạn không phải thay đổi đối số của hàm (hàng nghìn trong số chúng) bất cứ khi nào bạn thực hiện thay đổi trong mã của mình.


Dicts là đột biến. Nếu bạn truyền một lệnh cho một hàm và hàm đó chỉnh sửa chính tả, các thay đổi sẽ được phản ánh bên ngoài phạm vi của hàm đó. Có hàm trả về dict ở cuối có thể ngụ ý rằng hàm không có tác dụng phụ, do đó không nên trả về giá trị, làm rõ rằng điều đó testsẽ trực tiếp sửa đổi giá trị. So sánh điều này với dict.update, không trả về một giá trị.
sleblanc

@sleblanc "Có chức năng trả về dict ở cuối có thể ngụ ý rằng chức năng này không có tác dụng phụ". Nó không ngụ ý rằng bởi vì, như bạn đã nói, dict là có thể thay đổi. Tuy nhiên, trở lại formkhông làm tổn thương khả năng đọc và hiệu suất. Trong trường hợp bạn có thể cần định dạng lại form, việc trả lại [biểu mẫu] sẽ đảm bảo rằng lần cuối formđược trả về vì bạn sẽ không theo dõi các thay đổi của biểu mẫu ở bất cứ đâu.
Elis Byberi

3

"Tốt nhất" là một quyết định chủ quan một phần. Sử dụng bộ dữ liệu cho các bộ hoàn trả nhỏ trong trường hợp chung trong đó bất biến được chấp nhận. Một tuple luôn thích hợp hơn cho một danh sách khi tính đột biến không phải là một yêu cầu.

Đối với các giá trị trả về phức tạp hơn hoặc trong trường hợp hình thức có giá trị (nghĩa là mã giá trị cao), một bộ dữ liệu có tên là tốt hơn. Đối với trường hợp phức tạp nhất, một đối tượng thường là tốt nhất. Tuy nhiên, đó thực sự là tình huống quan trọng. Nếu nó có ý nghĩa để trả về một đối tượng bởi vì đó là những gì bạn tự nhiên có ở cuối hàm (ví dụ mẫu Factory) thì trả về đối tượng.

Như nhà thông thái đã nói:

Tối ưu hóa sớm là gốc rễ của mọi tội lỗi (hoặc ít nhất là phần lớn) trong lập trình.


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.