标签归档:return

在函数结束(例如,检查失败)之前,在python中退出函数(没有返回值)的最佳方法是什么?

问题:在函数结束(例如,检查失败)之前,在python中退出函数(没有返回值)的最佳方法是什么?

让我们假设一个迭代,其中我们调用一个没有返回值的函数。我认为我的程序应该表现的方式在以下伪代码中进行了解释:

for element in some_list:
    foo(element)

def foo(element):
    do something
    if check is true:
        do more (because check was succesful)
    else:
        return None
    do much much more...

如果我在python中实现此功能,则该函数返回一个None。是否有更好的方式“如果在函数主体中检查失败,则退出没有返回值的函数”?

Let’s assume an iteration in which we call a function without a return value. The way I think my program should behave is explained in this pseudocode:

for element in some_list:
    foo(element)

def foo(element):
    do something
    if check is true:
        do more (because check was succesful)
    else:
        return None
    do much much more...

If I implement this in python, it bothers me, that the function returns a None. Is there a better way for “exiting a function, that has no return value, if a check fails in the body of the function”?


回答 0

您可以简单地使用

return

与…完全相同

return None

None如果执行到达函数主体的末尾而没有命中return语句,则函数也将返回。不返回任何内容与None使用Python 返回相同。

You could simply use

return

which does exactly the same as

return None

Your function will also return None if execution reaches the end of the function body without hitting a return statement. Returning nothing is the same as returning None in Python.


回答 1

我会建议:

def foo(element):
    do something
    if not check: return
    do more (because check was succesful)
    do much much more...

I would suggest:

def foo(element):
    do something
    if not check: return
    do more (because check was succesful)
    do much much more...

回答 2

您可以使用return不带任何参数的语句退出函数

def foo(element):
    do something
    if check is true:
        do more (because check was succesful)
    else:
        return
    do much much more...

或引发异常,如果您想被告知该问题

def foo(element):
    do something
    if check is true:
        do more (because check was succesful)
    else:
        raise Exception("cause of the problem")
    do much much more...

you can use the return statement without any parameter to exit a function

def foo(element):
    do something
    if check is true:
        do more (because check was succesful)
    else:
        return
    do much much more...

or raise an exception if you want to be informed of the problem

def foo(element):
    do something
    if check is true:
        do more (because check was succesful)
    else:
        raise Exception("cause of the problem")
    do much much more...

为什么“ return list.sort()”返回None,而不返回列表?

问题:为什么“ return list.sort()”返回None,而不返回列表?

我已经能够验证findUniqueWords结果是否为sorted list。但是,它不返回列表。为什么?

def findUniqueWords(theList):
    newList = []
    words = []

    # Read a line at a time
    for item in theList:

        # Remove any punctuation from the line
        cleaned = cleanUp(item)

        # Split the line into separate words
        words = cleaned.split()

        # Evaluate each word
        for word in words:

            # Count each unique word
            if word not in newList:
                newList.append(word)

    answer = newList.sort()
    return answer

I’ve been able to verify that the findUniqueWords does result in a sorted list. However, it does not return the list. Why?

def findUniqueWords(theList):
    newList = []
    words = []

    # Read a line at a time
    for item in theList:

        # Remove any punctuation from the line
        cleaned = cleanUp(item)

        # Split the line into separate words
        words = cleaned.split()

        # Evaluate each word
        for word in words:

            # Count each unique word
            if word not in newList:
                newList.append(word)

    answer = newList.sort()
    return answer

回答 0

list.sort对列表进行适当排序,即不返回新列表。写就好了

newList.sort()
return newList

list.sort sorts the list in place, i.e. it doesn’t return a new list. Just write

newList.sort()
return newList

回答 1

问题在这里:

answer = newList.sort()

sort不返回排序列表;而是将列表排序到位。

用:

answer = sorted(newList)

The problem is here:

answer = newList.sort()

sort does not return the sorted list; rather, it sorts the list in place.

Use:

answer = sorted(newList)

回答 2

这是 Guido van Rossum在Python开发清单中的一封电子邮件,解释了为什么他选择不返回self影响该对象的操作并且不返回新对象的原因。

这来自一种编码样式(在各种其他语言中很流行,我相信尤其是Lisp令人反感),其中可以将单个对象上的一系列副作用链接成这样:

 x.compress().chop(y).sort(z)

这将与

  x.compress()
  x.chop(y)
  x.sort(z)

我发现链接对可读性构成威胁;它要求读者必须对每种方法都非常熟悉。第二种形式清楚地表明,每个调用都作用于同一对象,因此,即使您不太了解类及其方法,您也可以理解第二种和第三种调用都适用于x(并且所有呼叫都是出于副作用),而不是其他。

我想为返回新值的操作保留链接,例如字符串处理操作:

 y = x.rstrip("\n").split(":").lower()

Here is an email from Guido van Rossum in Python’s dev list explaining why he choose not to return self on operations that affects the object and don’t return a new one.

This comes from a coding style (popular in various other languages, I believe especially Lisp revels in it) where a series of side effects on a single object can be chained like this:

 x.compress().chop(y).sort(z)

which would be the same as

  x.compress()
  x.chop(y)
  x.sort(z)

I find the chaining form a threat to readability; it requires that the reader must be intimately familiar with each of the methods. The second form makes it clear that each of these calls acts on the same object, and so even if you don’t know the class and its methods very well, you can understand that the second and third call are applied to x (and that all calls are made for their side-effects), and not to something else.

I’d like to reserve chaining for operations that return new values, like string processing operations:

 y = x.rstrip("\n").split(":").lower()

回答 3

蟒习惯性地返回None从功能和变异的数据的方法,例如list.sortlist.appendrandom.shuffle,与想法是,它暗示一个事实,即它是变异。

如果要进行迭代并返回其项目的新排序列表,请使用sorted内置函数。

Python habitually returns None from functions and methods that mutate the data, such as list.sort, list.append, and random.shuffle, with the idea being that it hints to the fact that it was mutating.

If you want to take an iterable and return a new, sorted list of its items, use the sorted builtin function.


回答 4

Python有两种排序方式:sort 方法(或“成员函数”)和sort 函数。sort方法对命名对象的内容进行操作-将其视为对象要对其自身重新排序的操作。排序功能是对由对象表示的数据进行的操作,并按排序顺序返回内容相同的新对象。

给定一个名为l的整数列表,如果我们调用,则列表本身将重新排序l.sort()

>>> l = [1, 5, 2341, 467, 213, 123]
>>> l.sort()
>>> l
[1, 5, 123, 213, 467, 2341]

此方法没有返回值。但是,如果我们尝试分配的结果l.sort()呢?

>>> l = [1, 5, 2341, 467, 213, 123]
>>> r = l.sort()
>>> print(r)
None

r现在实际上等于什么。这是程序员在离开Python一段时间后很可能会忘记的那些怪异的,有些令人讨厌的细节(这就是为什么我要编写这个东西,所以不会再忘记了)。

sorted()另一方面,该函数不会对的内容做任何事情l,但会返回一个新的,排序后的列表,其内容与以下内容相同l

>>> l = [1, 5, 2341, 467, 213, 123]
>>> r = sorted(l)
>>> l
[1, 5, 2341, 467, 213, 123]
>>> r
[1, 5, 123, 213, 467, 2341]

请注意,返回的值是不是一个深拷贝,所以要谨慎了包含列表照常中的元素侧effecty操作:

>>> spam = [8, 2, 4, 7]
>>> eggs = [3, 1, 4, 5]
>>> l = [spam, eggs]
>>> r = sorted(l)
>>> l
[[8, 2, 4, 7], [3, 1, 4, 5]]
>>> r
[[3, 1, 4, 5], [8, 2, 4, 7]]
>>> spam.sort()
>>> eggs.sort()
>>> l
[[2, 4, 7, 8], [1, 3, 4, 5]]
>>> r
[[1, 3, 4, 5], [2, 4, 7, 8]]

Python has two kinds of sorts: a sort method (or “member function”) and a sort function. The sort method operates on the contents of the object named — think of it as an action that the object is taking to re-order itself. The sort function is an operation over the data represented by an object and returns a new object with the same contents in a sorted order.

Given a list of integers named l the list itself will be reordered if we call l.sort():

>>> l = [1, 5, 2341, 467, 213, 123]
>>> l.sort()
>>> l
[1, 5, 123, 213, 467, 2341]

This method has no return value. But what if we try to assign the result of l.sort()?

>>> l = [1, 5, 2341, 467, 213, 123]
>>> r = l.sort()
>>> print(r)
None

r now equals actually nothing. This is one of those weird, somewhat annoying details that a programmer is likely to forget about after a period of absence from Python (which is why I am writing this, so I don’t forget again).

The function sorted(), on the other hand, will not do anything to the contents of l, but will return a new, sorted list with the same contents as l:

>>> l = [1, 5, 2341, 467, 213, 123]
>>> r = sorted(l)
>>> l
[1, 5, 2341, 467, 213, 123]
>>> r
[1, 5, 123, 213, 467, 2341]

Be aware that the returned value is not a deep copy, so be cautious about side-effecty operations over elements contained within the list as usual:

>>> spam = [8, 2, 4, 7]
>>> eggs = [3, 1, 4, 5]
>>> l = [spam, eggs]
>>> r = sorted(l)
>>> l
[[8, 2, 4, 7], [3, 1, 4, 5]]
>>> r
[[3, 1, 4, 5], [8, 2, 4, 7]]
>>> spam.sort()
>>> eggs.sort()
>>> l
[[2, 4, 7, 8], [1, 3, 4, 5]]
>>> r
[[1, 3, 4, 5], [2, 4, 7, 8]]

回答 5

要了解为什么它不返回列表:

sort()不返回任何值,而sort()方法仅以特定顺序对给定列表的元素进行排序- 升序降序而不返回任何值。

所以问题在于answer = newList.sort()答案是否定的。

相反,您可以这样做return newList.sort()

sort()方法的语法为:

list.sort(key=..., reverse=...)

另外,您也可以出于相同目的使用Python的内置函数sorted()。

sorted(list, key=..., reverse=...)

注意:sort()和sorted()之间最简单的区别是:sort()不返回任何值,而sorted()返回可迭代的列表。

所以就你而言answer = sorted(newList)

To understand why it does not return the list:

sort() doesn’t return any value while the sort() method just sorts the elements of a given list in a specific order – ascending or descending without returning any value.

So problem is with answer = newList.sort() where answer is none.

Instead you can just do return newList.sort().

The syntax of the sort() method is:

list.sort(key=..., reverse=...)

Alternatively, you can also use Python’s in-built function sorted() for the same purpose.

sorted(list, key=..., reverse=...)

Note: The simplest difference between sort() and sorted() is: sort() doesn’t return any value while, sorted() returns an iterable list.

So in your case answer = sorted(newList).


回答 6

如果要返回排序列表,可以使用sorted()方法。比较方便

l1 = []
n = int(input())

for i in range(n):
  user = int(input())
  l1.append(user)
sorted(l1,reverse=True)

list.sort()方法就地修改列表,并返回None。

如果您仍然想使用排序,则可以执行此操作。

l1 = []
n = int(input())

for i in range(n):
  user = int(input())
  l1.append(user)
l1.sort(reverse=True)
print(l1)

you can use sorted() method if you want it to return the sorted list. It’s more convenient.

l1 = []
n = int(input())

for i in range(n):
  user = int(input())
  l1.append(user)
sorted(l1,reverse=True)

list.sort() method modifies the list in-place and returns None.

if you still want to use sort you can do this.

l1 = []
n = int(input())

for i in range(n):
  user = int(input())
  l1.append(user)
l1.sort(reverse=True)
print(l1)

如何从Python中的函数返回两个值?

问题:如何从Python中的函数返回两个值?

我想在两个单独的变量中从函数返回两个值。例如:

def select_choice():
    loop = 1
    row = 0
    while loop == 1:
        print('''Choose from the following options?:
                 1. Row 1
                 2. Row 2
                 3. Row 3''')

        row = int(input("Which row would you like to move the card from?: "))
        if row == 1:
            i = 2
            card = list_a[-1]
        elif row == 2:
            i = 1
            card = list_b[-1]
        elif row == 3:
            i = 0
            card = list_c[-1]
        return i
        return card

我希望能够分别使用这些值。当我尝试使用时return i, card,它返回a tuple,这不是我想要的。

I would like to return two values from a function in two separate variables. For example:

def select_choice():
    loop = 1
    row = 0
    while loop == 1:
        print('''Choose from the following options?:
                 1. Row 1
                 2. Row 2
                 3. Row 3''')

        row = int(input("Which row would you like to move the card from?: "))
        if row == 1:
            i = 2
            card = list_a[-1]
        elif row == 2:
            i = 1
            card = list_b[-1]
        elif row == 3:
            i = 0
            card = list_c[-1]
        return i
        return card

And I want to be able to use these values separately. When I tried to use return i, card, it returns a tuple and this is not what I want.


回答 0

您不能返回两个值,但可以返回a tuple或a list并在调用后解压缩它:

def select_choice():
    ...
    return i, card  # or [i, card]

my_i, my_card = select_choice()

在线return i, card i, card意味着创建一个元组。您也可以使用括号,例如return (i, card),但是元组是用逗号创建的,因此括号不是必需的。但是,您可以使用parens来提高代码的可读性或将元组分成多行。这同样适用于line my_i, my_card = select_choice()

如果要返回两个以上的值,请考虑使用命名的tuple。它将允许函数的调用者按名称访问返回值的字段,这样更易​​于阅读。您仍然可以按索引访问元组的项目。例如,在Schema.loadsMarshmallow框架方法中,返回的UnmarshalResult是a namedtuple。因此,您可以执行以下操作:

data, errors = MySchema.loads(request.json())
if errors:
    ...

要么

result = MySchema.loads(request.json())
if result.errors:
    ...
else:
    # use `result.data`

在其他情况下,您可以dict从函数中返回a :

def select_choice():
    ...
    return {'i': i, 'card': card, 'other_field': other_field, ...}

但是您可能要考虑返回一个实用程序类的实例,该实例包装您的数据:

class ChoiceData():
    def __init__(self, i, card, other_field, ...):
        # you can put here some validation logic
        self.i = i
        self.card = card
        self.other_field = other_field
        ...

def select_choice():
    ...
    return ChoiceData(i, card, other_field, ...)

choice_data = select_choice()
print(choice_data.i, choice_data.card)

You cannot return two values, but you can return a tuple or a list and unpack it after the call:

def select_choice():
    ...
    return i, card  # or [i, card]

my_i, my_card = select_choice()

On line return i, card i, card means creating a tuple. You can also use parenthesis like return (i, card), but tuples are created by comma, so parens are not mandatory. But you can use parens to make your code more readable or to split the tuple over multiple lines. The same applies to line my_i, my_card = select_choice().

If you want to return more than two values, consider using a named tuple. It will allow the caller of the function to access fields of the returned value by name, which is more readable. You can still access items of the tuple by index. For example in Schema.loads method Marshmallow framework returns a UnmarshalResult which is a namedtuple. So you can do:

data, errors = MySchema.loads(request.json())
if errors:
    ...

or

result = MySchema.loads(request.json())
if result.errors:
    ...
else:
    # use `result.data`

In other cases you may return a dict from your function:

def select_choice():
    ...
    return {'i': i, 'card': card, 'other_field': other_field, ...}

But you might want consider to return an instance of a utility class, which wraps your data:

class ChoiceData():
    def __init__(self, i, card, other_field, ...):
        # you can put here some validation logic
        self.i = i
        self.card = card
        self.other_field = other_field
        ...

def select_choice():
    ...
    return ChoiceData(i, card, other_field, ...)

choice_data = select_choice()
print(choice_data.i, choice_data.card)

回答 1

我想在两个单独的变量中从函数返回两个值。

您希望它在呼叫端看起来像什么?您无法编写,a = select_choice(); b = select_choice()因为那样会调用该函数两次。

值不“在变量中”返回;那不是Python的工作方式。函数返回值(对象)。变量只是给定上下文中值的名称。当您调用函数并在某处分配返回值时,您正在做的就是在调用上下文中为接收到的值命名。该函数不会为您将值“放入变量”中,赋值却会这样做(不必担心变量不是该值的“存储”,而是一个名称)。

当我尝试使用时return i, card,它返回a tuple,这不是我想要的。

实际上,这正是您想要的。您所要做的就是tuple再次分开。

而且我希望能够单独使用这些值。

因此,只需从中获取价值即可tuple

最简单的方法是打开包装:

a, b = select_choice()

I would like to return two values from a function in two separate variables.

What would you expect it to look like on the calling end? You can’t write a = select_choice(); b = select_choice() because that would call the function twice.

Values aren’t returned “in variables”; that’s not how Python works. A function returns values (objects). A variable is just a name for a value in a given context. When you call a function and assign the return value somewhere, what you’re doing is giving the received value a name in the calling context. The function doesn’t put the value “into a variable” for you, the assignment does (never mind that the variable isn’t “storage” for the value, but again, just a name).

When i tried to to use return i, card, it returns a tuple and this is not what i want.

Actually, it’s exactly what you want. All you have to do is take the tuple apart again.

And i want to be able to use these values separately.

So just grab the values out of the tuple.

The easiest way to do this is by unpacking:

a, b = select_choice()

回答 2

我认为您想要的是元组。如果使用return (i, card),则可以通过以下方式获得这两个结果:

i, card = select_choice()

I think you what you want is a tuple. If you use return (i, card), you can get these two results by:

i, card = select_choice()

回答 3

def test():
    ....
    return r1, r2, r3, ....

>> ret_val = test()
>> print ret_val
(r1, r2, r3, ....)

现在,您可以使用元组完成所有您喜欢的事情。

def test():
    ....
    return r1, r2, r3, ....

>> ret_val = test()
>> print ret_val
(r1, r2, r3, ....)

now you can do everything you like with your tuple.


回答 4

def test():
    r1 = 1
    r2 = 2
    r3 = 3
    return r1, r2, r3

x,y,z = test()
print x
print y
print z


> test.py 
1
2
3
def test():
    r1 = 1
    r2 = 2
    r3 = 3
    return r1, r2, r3

x,y,z = test()
print x
print y
print z


> test.py 
1
2
3

回答 5

这是另一种选择,如果您以列表形式返回,则很容易获得值。

def select_choice():
    ...
    return [i, card]

values = select_choice()

print values[0]
print values[1]

And this is an alternative.If you are returning as list then it is simple to get the values.

def select_choice():
    ...
    return [i, card]

values = select_choice()

print values[0]
print values[1]

回答 6

你可以试试这个

class select_choice():
    return x, y

a, b = test()

you can try this

class select_choice():
    return x, y

a, b = test()

回答 7

您还可以使用list返回多个值。检查下面的代码

def newFn():    #your function
  result = []    #defining blank list which is to be return
  r1 = 'return1'    #first value
  r2 = 'return2'    #second value
  result.append(r1)    #adding first value in list
  result.append(r2)    #adding second value in list
  return result    #returning your list

ret_val1 = newFn()[1]    #you can get any desired result from it
print ret_val1    #print/manipulate your your result

You can return more than one value using list also. Check the code below

def newFn():    #your function
  result = []    #defining blank list which is to be return
  r1 = 'return1'    #first value
  r2 = 'return2'    #second value
  result.append(r1)    #adding first value in list
  result.append(r2)    #adding second value in list
  return result    #returning your list

ret_val1 = newFn()[1]    #you can get any desired result from it
print ret_val1    #print/manipulate your your result

在Python中,如果我在“ with”块内返回文件,文件是否仍会关闭?

问题:在Python中,如果我在“ with”块内返回文件,文件是否仍会关闭?

考虑以下:

with open(path, mode) as f:
    return [line for line in f if condition]

文件将被正确关闭,还是使用return某种方式绕过上下文管理器

Consider the following:

with open(path, mode) as f:
    return [line for line in f if condition]

Will the file be closed properly, or does using return somehow bypass the context manager?


回答 0

是的,它的作用就像一个finally块接一个try块,也就是说,它总是执行(除非python进程以异常的方式终止)。

PEP-343的示例之一也提到了该with语句,它是该语句的规范:

with locked(myLock):
    # Code here executes with myLock held.  The lock is
    # guaranteed to be released when the block is left (even
    # if via return or by an uncaught exception).

但是,值得一提的是,如果open()不将整个with块放入try..except通常不是您想要的块中,就无法轻松捕获调用引发的异常。

Yes, it acts like the finally block after a try block, i.e. it always executes (unless the python process terminates in an unusual way of course).

It is also mentioned in one of the examples of PEP-343 which is the specification for the with statement:

with locked(myLock):
    # Code here executes with myLock held.  The lock is
    # guaranteed to be released when the block is left (even
    # if via return or by an uncaught exception).

Something worth mentioning is however, that you cannot easily catch exceptions thrown by the open() call without putting the whole with block inside a try..except block which is usually not what one wants.


回答 1

是。

def example(path, mode):
    with open(path, mode) as f:
        return [line for line in f if condition]

..几乎等同于:

def example(path, mode):
    f = open(path, mode)

    try:
        return [line for line in f if condition]
    finally:
        f.close()

更准确地说, __exit__总是在退出该块时调用上下文管理器中方法(无论异常,返回等如何)。文件对象的__exit__方法只是调用f.close()(例如,在CPython中

Yes.

def example(path, mode):
    with open(path, mode) as f:
        return [line for line in f if condition]

..is pretty much equivalent to:

def example(path, mode):
    f = open(path, mode)

    try:
        return [line for line in f if condition]
    finally:
        f.close()

More accurately, the __exit__ method in a context manager is always called when exiting the block (regardless of exceptions, returns etc). The file object’s __exit__ method just calls f.close() (e.g here in CPython)


回答 2

是。更一般地,如果在上下文内部发生__exit__了“ with”语句上下文管理器,该方法的确会被调用return。可以使用以下方法进行测试:

class MyResource:
    def __enter__(self):
        print('Entering context.')
        return self

    def __exit__(self, *exc):
        print('EXITING context.')

def fun():
    with MyResource():
        print('Returning inside with-statement.')
        return
    print('Returning outside with-statement.')

fun()

输出为:

Entering context.
Returning inside with-statement.
EXITING context.

上面的输出确认 __exit__尽管是早期的调用return。这样,上下文管理器不会被绕过。

Yes. More generally, the __exit__ method of a With Statement Context Manager will indeed be called in the event of a return from inside the context. This can be tested with the following:

class MyResource:
    def __enter__(self):
        print('Entering context.')
        return self

    def __exit__(self, *exc):
        print('EXITING context.')

def fun():
    with MyResource():
        print('Returning inside with-statement.')
        return
    print('Returning outside with-statement.')

fun()

The output is:

Entering context.
Returning inside with-statement.
EXITING context.

The output above confirms that __exit__ was called despite the early return. As such, the context manager is not bypassed.


回答 3

是的,但是在其他情况下可能会有一些副作用,因为它可能会在__exit__块中执行某些操作(例如刷新缓冲区)

import gzip
import io

def test(data):
    out = io.BytesIO()
    with gzip.GzipFile(fileobj=out, mode="wb") as f:
        f.write(data)
        return out.getvalue()

def test1(data):
    out = io.BytesIO()
    with gzip.GzipFile(fileobj=out, mode="wb") as f:
        f.write(data)
    return out.getvalue()

print(test(b"test"), test1(b"test"))

# b'\x1f\x8b\x08\x00\x95\x1b\xb3[\x02\xff' b'\x1f\x8b\x08\x00\x95\x1b\xb3[\x02\xff+I-.\x01\x00\x0c~\x7f\xd8\x04\x00\x00\x00'

Yes, but there may be some side effect in other cases, because it may should do something (like flushing buffer) in __exit__ block

import gzip
import io

def test(data):
    out = io.BytesIO()
    with gzip.GzipFile(fileobj=out, mode="wb") as f:
        f.write(data)
        return out.getvalue()

def test1(data):
    out = io.BytesIO()
    with gzip.GzipFile(fileobj=out, mode="wb") as f:
        f.write(data)
    return out.getvalue()

print(test(b"test"), test1(b"test"))

# b'\x1f\x8b\x08\x00\x95\x1b\xb3[\x02\xff' b'\x1f\x8b\x08\x00\x95\x1b\xb3[\x02\xff+I-.\x01\x00\x0c~\x7f\xd8\x04\x00\x00\x00'

返回,返回无,根本没有返回?

问题:返回,返回无,根本没有返回?

考虑三个功能:

def my_func1():
  print "Hello World"
  return None

def my_func2():
  print "Hello World"
  return

def my_func3():
  print "Hello World"

它们似乎都返回None。这些函数的返回值的行为方式之间有什么区别吗?是否有任何理由偏爱一个?

Consider three functions:

def my_func1():
  print "Hello World"
  return None

def my_func2():
  print "Hello World"
  return

def my_func3():
  print "Hello World"

They all appear to return None. Are there any differences between how the returned value of these functions behave? Are there any reasons to prefer one versus the other?


回答 0

在实际行为上,没有区别。他们都回来了None,就是这样。但是,所有这些都有时间和地点。以下说明基本上是应如何使用不同方法的方法(或至少应告诉我应如何使用它们的方法),但是它们不是绝对规则,因此您可以根据需要将它们混合使用。

使用 return None

这说明该函数确实是要返回一个值供以后使用,在这种情况下,它返回NoneNone然后可以在其他地方使用此值。return None如果该函数没有其他可能的返回值,则永远不要使用。

在下面的例子中,我们返回personmother,如果person给出的一个人。如果不是人类,我们将返回,None因为person它没有mother(假设它不是动物或其他东西)。

def get_mother(person):
    if is_human(person):
        return person.mother
    else:
        return None

使用 return

出于与break循环中相同的原因使用它。返回值无关紧要,您只想退出整个函数。即使您不经常使用它,它在某些地方也非常有用。

我们已经有15个人,prisoners而且我们知道其中一个拥有一把刀。我们prisoner逐个循环检查他们是否有刀。如果我们用小刀打人,则可以退出该功能,因为我们知道只有一把小刀,没有理由检查其余部分prisoners。如果找不到prisoner刀子,则会发出警报。这可以通过许多不同的方式完成,使用return可能甚至不是最好的方式,但这只是说明如何使用return退出函数的一个示例。

def find_prisoner_with_knife(prisoners):
    for prisoner in prisoners:
        if "knife" in prisoner.items:
            prisoner.move_to_inquisition()
            return # no need to check rest of the prisoners nor raise an alert
    raise_alert()

注意:绝对不要这样做var = find_prisoner_with_knife(),因为返回值不是要捕获的。

使用无return可言

这也将返回None,但是该值并不意味着要使用或捕获。这仅表示该功能已成功结束。它基本上与C ++或Java等语言return中的void函数相同。

在下面的示例中,我们设置了人的母亲的名字,然后该函数在成功完成后退出。

def set_mother(person, mother):
    if is_human(person):
        person.mother = mother

注意:绝对不要这样做var = set_mother(my_person, my_mother),因为返回值不是要捕获的。

On the actual behavior, there is no difference. They all return None and that’s it. However, there is a time and place for all of these. The following instructions are basically how the different methods should be used (or at least how I was taught they should be used), but they are not absolute rules so you can mix them up if you feel necessary to.

Using return None

This tells that the function is indeed meant to return a value for later use, and in this case it returns None. This value None can then be used elsewhere. return None is never used if there are no other possible return values from the function.

In the following example, we return person‘s mother if the person given is a human. If it’s not a human, we return None since the person doesn’t have a mother (let’s suppose it’s not an animal or something).

def get_mother(person):
    if is_human(person):
        return person.mother
    else:
        return None

Using return

This is used for the same reason as break in loops. The return value doesn’t matter and you only want to exit the whole function. It’s extremely useful in some places, even though you don’t need it that often.

We’ve got 15 prisoners and we know one of them has a knife. We loop through each prisoner one by one to check if they have a knife. If we hit the person with a knife, we can just exit the function because we know there’s only one knife and no reason the check rest of the prisoners. If we don’t find the prisoner with a knife, we raise an alert. This could be done in many different ways and using return is probably not even the best way, but it’s just an example to show how to use return for exiting a function.

def find_prisoner_with_knife(prisoners):
    for prisoner in prisoners:
        if "knife" in prisoner.items:
            prisoner.move_to_inquisition()
            return # no need to check rest of the prisoners nor raise an alert
    raise_alert()

Note: You should never do var = find_prisoner_with_knife(), since the return value is not meant to be caught.

Using no return at all

This will also return None, but that value is not meant to be used or caught. It simply means that the function ended successfully. It’s basically the same as return in void functions in languages such as C++ or Java.

In the following example, we set person’s mother’s name and then the function exits after completing successfully.

def set_mother(person, mother):
    if is_human(person):
        person.mother = mother

Note: You should never do var = set_mother(my_person, my_mother), since the return value is not meant to be caught.


回答 1

是的,它们都是一样的。

我们可以查看解释后的机器代码,以确认它们都在做完全相同的事情。

import dis

def f1():
  print "Hello World"
  return None

def f2():
  print "Hello World"
  return

def f3():
  print "Hello World"

dis.dis(f1)
    4   0 LOAD_CONST    1 ('Hello World')
        3 PRINT_ITEM
        4 PRINT_NEWLINE

    5   5 LOAD_CONST    0 (None)
        8 RETURN_VALUE

dis.dis(f2)
    9   0 LOAD_CONST    1 ('Hello World')
        3 PRINT_ITEM
        4 PRINT_NEWLINE

    10  5 LOAD_CONST    0 (None)
        8 RETURN_VALUE

dis.dis(f3)
    14  0 LOAD_CONST    1 ('Hello World')
        3 PRINT_ITEM
        4 PRINT_NEWLINE            
        5 LOAD_CONST    0 (None)
        8 RETURN_VALUE      

Yes, they are all the same.

We can review the interpreted machine code to confirm that that they’re all doing the exact same thing.

import dis

def f1():
  print "Hello World"
  return None

def f2():
  print "Hello World"
  return

def f3():
  print "Hello World"

dis.dis(f1)
    4   0 LOAD_CONST    1 ('Hello World')
        3 PRINT_ITEM
        4 PRINT_NEWLINE

    5   5 LOAD_CONST    0 (None)
        8 RETURN_VALUE

dis.dis(f2)
    9   0 LOAD_CONST    1 ('Hello World')
        3 PRINT_ITEM
        4 PRINT_NEWLINE

    10  5 LOAD_CONST    0 (None)
        8 RETURN_VALUE

dis.dis(f3)
    14  0 LOAD_CONST    1 ('Hello World')
        3 PRINT_ITEM
        4 PRINT_NEWLINE            
        5 LOAD_CONST    0 (None)
        8 RETURN_VALUE      

回答 2

它们每个都返回相同的单例None-功能上没有差异。

我认为,return除非您需要先退出该函数(在这种情况下,裸露return更为常见)或返回除以外的其他值,否则放弃该语句是很习惯的做法None。它也很有意义,并且return None在函数中具有返回除之外的其他值的函数时似乎是惯用的Nonereturn None明确地写出来是读者的视觉提示,还有另一个分支返回更有趣的内容(并且调用代码可能需要处理两种类型的返回值)。

返回的函数通常在Python None中像voidC中的函数一样使用-它们的目的通常是在适当的位置对输入参数进行操作(除非您正在使用全局数据(shudders))。None通常,返回可以使参数更加明确。这使我们更加清楚为什么return从“语言约定”的角度出发不理会该声明。

就是说,如果您正在使用已经针对这些事情设置了预设约定的代码库,那么我肯定会效仿以帮助使代码库保持一致…

They each return the same singleton None — There is no functional difference.

I think that it is reasonably idiomatic to leave off the return statement unless you need it to break out of the function early (in which case a bare return is more common), or return something other than None. It also makes sense and seems to be idiomatic to write return None when it is in a function that has another path that returns something other than None. Writing return None out explicitly is a visual cue to the reader that there’s another branch which returns something more interesting (and that calling code will probably need to handle both types of return values).

Often in Python, functions which return None are used like void functions in C — Their purpose is generally to operate on the input arguments in place (unless you’re using global data (shudders)). Returning None usually makes it more explicit that the arguments were mutated. This makes it a little more clear why it makes sense to leave off the return statement from a “language conventions” standpoint.

That said, if you’re working in a code base that already has pre-set conventions around these things, I’d definitely follow suit to help the code base stay uniform…


回答 3

正如其他人回答的那样,None在所有情况下都将返回完全相同的结果。

区别是风格上的,但请注意,PEP8要求使用时要保持一致:

在返回语句中保持一致。函数中的所有return语句应返回一个表达式,或者都不返回。如果任何return语句返回一个表达式,则不返回任何值的任何return语句应将其显式声明为return None,并且在函数的末尾(如果可访问)应存在显式return语句。

是:

def foo(x):
    if x >= 0:
        return math.sqrt(x)
    else:
        return None

def bar(x):
    if x < 0:
        return None
    return math.sqrt(x)

没有:

def foo(x):
    if x >= 0:
        return math.sqrt(x)

def bar(x):
    if x < 0:
        return
    return math.sqrt(x)

https://www.python.org/dev/peps/pep-0008/#programming-recommendations


基本上,如果您曾经非None在函数中值,则意味着返回值具有含义,并且被调用方捕获。因此,当您返回时None,它也必须是显式的,以None在这种情况下传达含义,它是可能的返回值之一。

如果您根本不需要返回,则函数基本上是作为过程而不是函数工作的,因此不要包括 return语句。

如果您正在编写类似过程的函数,并且有机会早点返回(即您已经完成了此操作,不需要执行其余的函数),则可以使用empty returns向读者发出信号这只是执行的早期完成,None隐式返回的值没有任何意义,也不意味着被捕获(类似过程的函数始终返回None)。

As other have answered, the result is exactly the same, None is returned in all cases.

The difference is stylistic, but please note that PEP8 requires the use to be consistent:

Be consistent in return statements. Either all return statements in a function should return an expression, or none of them should. If any return statement returns an expression, any return statements where no value is returned should explicitly state this as return None, and an explicit return statement should be present at the end of the function (if reachable).

Yes:

def foo(x):
    if x >= 0:
        return math.sqrt(x)
    else:
        return None

def bar(x):
    if x < 0:
        return None
    return math.sqrt(x)

No:

def foo(x):
    if x >= 0:
        return math.sqrt(x)

def bar(x):
    if x < 0:
        return
    return math.sqrt(x)

https://www.python.org/dev/peps/pep-0008/#programming-recommendations


Basically, if you ever return non-None value in a function, it means the return value has meaning and is meant to be caught by callers. So when you return None, it must also be explicit, to convey None in this case has meaning, it is one of the possible return values.

If you don’t need return at all, you function basically works as a procedure instead of a function, so just don’t include the return statement.

If you are writing a procedure-like function and there is an opportunity to return earlier (i.e. you are already done at that point and don’t need to execute the remaining of the function) you may use empty an returns to signal for the reader it is just an early finish of execution and the None value returned implicitly doesn’t have any meaning and is not meant to be caught (the procedure-like function always returns None anyway).


回答 4

就功能而言,它们都是相同的,它们之间的区别在于代码的可读性和样式(要考虑的重要因素)

In terms of functionality these are all the same, the difference between them is in code readability and style (which is important to consider)


如何从函数返回多个值?[关闭]

问题:如何从函数返回多个值?[关闭]

用支持它的语言返回多个值的规范方法通常是麻烦的

选项:使用元组

考虑下面这个简单的例子:

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

但是,随着返回值的数量增加,这很快就会成为问题。如果要返回四个或五个值怎么办?当然,您可以继续修改它们,但是很容易忘记哪个值在哪里。在任何要接收它们的地方打开它们的包装也是很丑陋的。

选项:使用字典

下一步的逻辑步骤似乎是引入某种“记录符号”。在Python中,显而易见的方法是使用dict

考虑以下:

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

(请注意,y0,y1和y2只是抽象标识符。正如所指出的,实际上,您将使用有意义的标识符。)

现在,我们有了一种机制,可以投影出返回对象的特定成员。例如,

result['y0']

选项:使用类

但是,还有另一种选择。相反,我们可以返回一个特殊的结构。我已经在Python的上下文中对此进行了框架化,但是我确信它也适用于其他语言。确实,如果您使用C语言工作,这很可能是您唯一的选择。开始:

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)

在Python中,前面的两个在管道方面可能非常相似-毕竟{ y0, y1, y2 }最终只是__dict__ReturnValue

Python提供了一项附加功能,尽管对于微小的对象,__slots__属性。该类可以表示为:

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

Python参考手册中

__slots__声明采用一系列实例变量,并在每个实例中仅保留足够的空间来容纳每个变量的值。因为__dict__未为每个实例创建空间,所以节省了空间。

选项:使用数据类(Python 3.7+)

使用Python 3.7的新数据类,返回一个具有自动添加的特殊方法,键入和其他有用工具的类:

@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)

选项:使用列表

我忽略的另一个建议来自蜥蜴人比尔:

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

这是我最不喜欢的方法。我想我对接触Haskell感到很受污染,但是混合类型列表的想法一直让我感到不舒服。在此特定示例中,列表为“非混合”类型,但可以想象是这样。

据我所知,以这种方式使用的列表实际上对元组没有任何好处。Python中列表和元组之间的唯一真正区别是列表是可变的,而元组则不是。

我个人倾向于继承函数式编程的约定:对任何数量的相同类型的元素使用列表,对固定数量的预定类型的元素使用元组。

在冗长的序言之后,出现了不可避免的问题。(您认为)哪种方法最好?

The canonical way to return multiple values in languages that support it is often tupling.

Option: Using a tuple

Consider this trivial example:

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

However, this quickly gets problematic as the number of values returned increases. What if you want to return four or five values? Sure, you could keep tupling them, but it gets easy to forget which value is where. It’s also rather ugly to unpack them wherever you want to receive them.

Option: Using a dictionary

The next logical step seems to be to introduce some sort of ‘record notation’. In Python, the obvious way to do this is by means of a dict.

Consider the following:

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

(Just to be clear, y0, y1, and y2 are just meant as abstract identifiers. As pointed out, in practice you’d use meaningful identifiers.)

Now, we have a mechanism whereby we can project out a particular member of the returned object. For example,

result['y0']

Option: Using a class

However, there is another option. We could instead return a specialized structure. I’ve framed this in the context of Python, but I’m sure it applies to other languages as well. Indeed, if you were working in C this might very well be your only option. Here goes:

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)

In Python the previous two are perhaps very similar in terms of plumbing – after all { y0, y1, y2 } just end up being entries in the internal __dict__ of the ReturnValue.

There is one additional feature provided by Python though for tiny objects, the __slots__ attribute. The class could be expressed as:

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

From the Python Reference Manual:

The __slots__ declaration takes a sequence of instance variables and reserves just enough space in each instance to hold a value for each variable. Space is saved because __dict__ is not created for each instance.

Option: Using a dataclass (Python 3.7+)

Using Python 3.7’s new dataclasses, return a class with automatically added special methods, typing and other useful tools:

@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)

Option: Using a list

Another suggestion which I’d overlooked comes from Bill the Lizard:

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

This is my least favorite method though. I suppose I’m tainted by exposure to Haskell, but the idea of mixed-type lists has always felt uncomfortable to me. In this particular example the list is -not- mixed type, but it conceivably could be.

A list used in this way really doesn’t gain anything with respect to the tuple as far as I can tell. The only real difference between lists and tuples in Python is that lists are mutable, whereas tuples are not.

I personally tend to carry over the conventions from functional programming: use lists for any number of elements of the same type, and tuples for a fixed number of elements of predetermined types.

Question

After the lengthy preamble, comes the inevitable question. Which method (do you think) is best?


回答 0

为此,在2.6中添加了命名元组。另请参见os.stat以获取类似的内置示例。

>>> 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

在最新版本的Python 3(我认为是3.6+)中,新typing库提供了NamedTuple使命名元组更易于创建和更强大的类。通过继承,typing.NamedTuple您可以使用文档字符串,默认值和类型注释。

示例(来自文档):

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

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

Named tuples were added in 2.6 for this purpose. Also see os.stat for a similar builtin example.

>>> 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

In recent versions of Python 3 (3.6+, I think), the new typing library got the NamedTuple class to make named tuples easier to create and more powerful. Inheriting from typing.NamedTuple lets you use docstrings, default values, and type annotations.

Example (From the docs):

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

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

回答 1

对于小型项目,我发现使用元组最简单。当这变得难以管理时(而不是之前),我开始将事物分组为逻辑结构,但是我认为您建议使用字典和ReturnValue对象是错误的(或者过于简单)。

返回与键的字典"y0""y1""y2"等不提供任何优势元组。返回一个ReturnValue实例与性能.y0.y1.y2等不提供任何元组过任何优势。如果您想到达任何地方,就需要开始命名事物,并且无论如何都可以使用元组来命名:

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

size, type, dimensions = get_image_data(x)

恕我直言,除元组之外,唯一好的技术是使用适当的方法和属性返回真实对象,就像您从re.match()或获取的那样open(file)

For small projects I find it easiest to work with tuples. When that gets too hard to manage (and not before) I start grouping things into logical structures, however I think your suggested use of dictionaries and ReturnValue objects is wrong (or too simplistic).

Returning a dictionary with keys "y0", "y1", "y2", etc. doesn’t offer any advantage over tuples. Returning a ReturnValue instance with properties .y0, .y1, .y2, etc. doesn’t offer any advantage over tuples either. You need to start naming things if you want to get anywhere, and you can do that using tuples anyway:

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

size, type, dimensions = get_image_data(x)

IMHO, the only good technique beyond tuples is to return real objects with proper methods and properties, like you get from re.match() or open(file).


回答 2

许多答案表明您需要返回某种类型的集合,例如字典或列表。您可以省去多余的语法,而只需写出返回值(以逗号分隔)即可。注意:从技术上讲,这将返回一个元组。

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

给出:

True
False

A lot of the answers suggest you need to return a collection of some sort, like a dictionary or a list. You could leave off the extra syntax and just write out the return values, comma-separated. Note: this technically returns a tuple.

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

gives:

True
False

回答 3

我投票给字典。

我发现,如果我创建的函数返回的变量超过2-3个,则将它们折叠成字典。否则,我往往会忘记所返回内容的顺序和内容。

另外,引入“特殊”结构会使您的代码更难以遵循。(其他人将不得不搜索代码以找出它是什么)

如果您担心类型查找,请使用描述性字典键,例如“ x值列表”。

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

I vote for the dictionary.

I find that if I make a function that returns anything more than 2-3 variables I’ll fold them up in a dictionary. Otherwise I tend to forget the order and content of what I’m returning.

Also, introducing a ‘special’ structure makes your code more difficult to follow. (Someone else will have to search through the code to find out what it is)

If your concerned about type look up, use descriptive dictionary keys, for example, ‘x-values list’.

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

回答 4

另一种选择是使用生成器:

>>> 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

尽管IMHO元组通常是最好的,除非返回的值是封装在类中的候选对象。

Another option would be using generators:

>>> 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

Although IMHO tuples are usually best, except in cases where the values being returned are candidates for encapsulation in a class.


回答 5

我更喜欢在元组感到“自然”时使用元组。坐标是一个典型示例,其中单独的对象可以独立站立,例如在单轴缩放计算中,顺序很重要。注意:如果我可以对项目进行排序或改组而不会对组的含义造成不利影响,那么我可能不应该使用元组。

仅当分组的对象并不总是相同时,我才使用字典作为返回值。考虑可选的电子邮件标题。

对于其余的情况,如果分组的对象在组内具有固有的含义,或者需要具有自己方法的成熟对象,则使用类。

I prefer to use tuples whenever a tuple feels “natural”; coordinates are a typical example, where the separate objects can stand on their own, e.g. in one-axis only scaling calculations, and the order is important. Note: if I can sort or shuffle the items without an adverse effect to the meaning of the group, then I probably shouldn’t use a tuple.

I use dictionaries as a return value only when the grouped objects aren’t always the same. Think optional email headers.

For the rest of the cases, where the grouped objects have inherent meaning inside the group or a fully-fledged object with its own methods is needed, I use a class.


回答 6

我更喜欢:

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

似乎其他所有东西只是做相同事情的额外代码。

I prefer:

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

It seems everything else is just extra code to do the same thing.


回答 7

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

回答 8

通常,“专用结构”实际上是具有其自身方法的对象的当前状态。

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

我希望在可能的地方找到匿名结构的名称。有意义的名称使事情变得更清楚。

Generally, the “specialized structure” actually IS a sensible current state of an object, with its own methods.

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

I like to find names for anonymous structures where possible. Meaningful names make things more clear.


回答 9

Python的元组,字典和对象为程序员提供了在小型数据结构(“事物”)的形式和便利之间的平滑权衡。对我而言,如何表示事物的选择主要取决于我将如何使用结构。在C ++中,即使您可以合法地将方法放在; 上,也struct仅用于纯数据项和class带有方法的对象是一种常见的约定struct。我的习惯与Python类似,用dicttuple代替struct

对于坐标集,我将使用a tuple而不是点class或a dict(并且请注意,您可以将a tuple用作字典键,因此dicts是非常好的稀疏多维数组)。

如果我要遍历所有东西,我更喜欢tuple在迭代中解包s:

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

…由于对象版本更易阅读:

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

…更不用说了dict

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

如果该事物被广泛使用,并且您发现自己在代码中的多个位置对它执行了类似的非平凡操作,那么通常值得用适当的方法将其变成一个类对象。

最后,如果我要与非Python系统组件交换数据,那么我通常会将它们放在a中,dict因为这最适合JSON序列化。

Python’s tuples, dicts, and objects offer the programmer a smooth tradeoff between formality and convenience for small data structures (“things”). For me, the choice of how to represent a thing is dictated mainly by how I’m going to use the structure. In C++, it’s a common convention to use struct for data-only items and class for objects with methods, even though you can legally put methods on a struct; my habit is similar in Python, with dict and tuple in place of struct.

For coordinate sets, I’ll use a tuple rather than a point class or a dict (and note that you can use a tuple as a dictionary key, so dicts make great sparse multidimensional arrays).

If I’m going to be iterating over a list of things, I prefer unpacking tuples on the iteration:

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

…as the object version is more cluttered to read:

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

…let alone the dict.

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

If the thing is widely used, and you find yourself doing similar non-trivial operations on it in multiple places in the code, then it’s usually worthwhile to make it a class object with appropriate methods.

Finally, if I’m going to be exchanging data with non-Python system components, I’ll most often keep them in a dict because that’s best suited to JSON serialization.


回答 10

S.Lott关于命名容器类的建议的+1。

对于Python 2.6及更高版本,命名元组提供了一种轻松创建这些容器类的有用方法,其结果是“重量轻,并且不需要比常规元组更多的内存”。

+1 on S.Lott’s suggestion of a named container class.

For Python 2.6 and up, a named tuple provides a useful way of easily creating these container classes, and the results are “lightweight and require no more memory than regular tuples”.


回答 11

在像Python这样的语言中,我通常会使用字典,因为与创建新类相比,它所涉及的开销更少。

但是,如果我发现自己不断返回相同的变量集,则可能涉及一个我要考虑的新类。

In languages like Python, I would usually use a dictionary as it involves less overhead than creating a new class.

However, if I find myself constantly returning the same set of variables, then that probably involves a new class that I’ll factor out.


回答 12

我将使用字典来传递和从函数返回值:

使用form中定义的变量form

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}

对于我和处理单元而言,这是最有效的方法。

您只需要传递一个指针并返回一个指针即可。

在代码中进行更改时,不必更改函数的参数(成千上万个)。

I would use a dict to pass and return values from a function:

Use variable form as defined in form.

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}

This is the most efficient way for me and for processing unit.

You have to pass just one pointer in and return just one pointer out.

You do not have to change functions’ (thousands of them) arguments whenever you make a change in your code.


回答 13

“最佳”是部分主观的决定。在可接受不可变的一般情况下,将元组用于小的收益集。当不需要可变性时,元组总是比列表更可取。

对于更复杂的返回值,或者对于形式化很有价值(即高价值代码)的情况,命名元组更好。对于最复杂的情​​况,对象通常是最好的。但是,实际情况才是最重要的。如果返回一个对象是有意义的,因为那是您在函数末尾自然所拥有的(例如Factory模式),则返回该对象。

正如智者所说:

过早的优化是编程中所有邪恶(或至少是大多数邪恶)的根源。

“Best” is a partially subjective decision. Use tuples for small return sets in the general case where an immutable is acceptable. A tuple is always preferable to a list when mutability is not a requirement.

For more complex return values, or for the case where formality is valuable (i.e. high value code) a named tuple is better. For the most complex case an object is usually best. However, it’s really the situation that matters. If it makes sense to return an object because that is what you naturally have at the end of the function (e.g. Factory pattern) then return the object.

As the wise man said:

Premature optimization is the root of all evil (or at least most of it) in programming.