for element in some_list:
foo(element)def foo(element):do something
if check is true:do more (because check was succesful)else:returnNonedo much much more...
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”?
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
ifnot check:returndo more (because check was succesful)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...
def findUniqueWords(theList):
newList =[]
words =[]# Read a line at a timefor item in theList:# Remove any punctuation from the line
cleaned = cleanUp(item)# Split the line into separate words
words = cleaned.split()# Evaluate each wordfor word in words:# Count each unique wordif word notin 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
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:
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.
>>> 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:
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)
def select_choice():
loop =1
row =0while 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,这不是我想要的。
classChoiceData():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():...returnChoiceData(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, cardi, 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:
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()因为那样会调用该函数两次。
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.
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 listreturn result #returning your list
ret_val1 = newFn()[1]#you can get any desired result from itprint 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
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).
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()
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)
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:
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?
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()
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.
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…
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)
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).
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.
(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:
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:
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.
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?
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
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:
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.
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’.
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 }
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.
+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”.
“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.