分类目录归档:知识问答

确定整数是否在其他两个整数之间?

问题:确定整数是否在其他两个整数之间?

如何确定给定的整数是否在其他两个整数之间(例如,大于/等于10000和小于/等于30000)?

我正在使用2.3 IDLE,到目前为止,我一直没有尝试:

if number >= 10000 and number >= 30000:
    print ("you have to pay 5% taxes")

How do I determine whether a given integer is between two other integers (e.g. greater than/equal to 10000 and less than/equal to 30000)?

I’m using 2.3 IDLE and what I’ve attempted so far is not working:

if number >= 10000 and number >= 30000:
    print ("you have to pay 5% taxes")

回答 0

if 10000 <= number <= 30000:
    pass
if 10000 <= number <= 30000:
    pass

回答 1

>>> r = range(1, 4)
>>> 1 in r
True
>>> 2 in r
True
>>> 3 in r
True
>>> 4 in r
False
>>> 5 in r
False
>>> 0 in r
False
>>> r = range(1, 4)
>>> 1 in r
True
>>> 2 in r
True
>>> 3 in r
True
>>> 4 in r
False
>>> 5 in r
False
>>> 0 in r
False

回答 2

您的操作员不正确。应该是if number >= 10000 and number <= 30000:。此外,Python的缩写是if 10000 <= number <= 30000:

Your operator is incorrect. Should be if number >= 10000 and number <= 30000:. Additionally, Python has a shorthand for this sort of thing, if 10000 <= number <= 30000:.


回答 3

您的代码段,

if number >= 10000 and number >= 30000:
    print ("you have to pay 5% taxes")

实际检查数字是否同时大于10000和30000。

假设您要检查数字范围在10000-30000之间,可以使用Python间隔比较:

if 10000 <= number <= 30000:
    print ("you have to pay 5% taxes")

Python文档中进一步描述此Python功能。

Your code snippet,

if number >= 10000 and number >= 30000:
    print ("you have to pay 5% taxes")

actually checks if number is larger than both 10000 and 30000.

Assuming you want to check that the number is in the range 10000 – 30000, you could use the Python interval comparison:

if 10000 <= number <= 30000:
    print ("you have to pay 5% taxes")

This Python feature is further described in the Python documentation.


回答 4

if number >= 10000 and number <= 30000:
    print ("you have to pay 5% taxes")
if number >= 10000 and number <= 30000:
    print ("you have to pay 5% taxes")

回答 5

比较的麻烦在于,当您将一个>=应该放置在<=

#                             v---------- should be <
if number >= 10000 and number >= 30000:
    print ("you have to pay 5% taxes")

Python使您可以用语言写下您的意思

if number in xrange(10000, 30001): # ok you have to remember 30000 + 1 here :)

在Python3中,您需要使用range代替xrange

编辑:人们似乎更关注微基准标记以及如何进行酷链接操作。我的答案是关于防御性(错误的攻击面更少)的编程。

由于评论中有声明,因此我在此处为Python3.5.2添加了微型基准测试

$ python3.5 -m timeit "5 in range(10000, 30000)"
1000000 loops, best of 3: 0.266 usec per loop
$ python3.5 -m timeit "10000 <= 5 < 30000"
10000000 loops, best of 3: 0.0327 usec per loop

如果您担心性能,可以一次计算范围

$ python3.5 -m timeit -s "R=range(10000, 30000)" "5 in R"
10000000 loops, best of 3: 0.0551 usec per loop

The trouble with comparisons is that they can be difficult to debug when you put a >= where there should be a <=

#                             v---------- should be <
if number >= 10000 and number >= 30000:
    print ("you have to pay 5% taxes")

Python lets you just write what you mean in words

if number in xrange(10000, 30001): # ok you have to remember 30000 + 1 here :)

In Python3, you need to use range instead of xrange.

edit: People seem to be more concerned with microbench marks and how cool chaining operations. My answer is about defensive (less attack surface for bugs) programming.

As a result of a claim in the comments, I’ve added the micro benchmark here for Python3.5.2

$ python3.5 -m timeit "5 in range(10000, 30000)"
1000000 loops, best of 3: 0.266 usec per loop
$ python3.5 -m timeit "10000 <= 5 < 30000"
10000000 loops, best of 3: 0.0327 usec per loop

If you are worried about performance, you could compute the range once

$ python3.5 -m timeit -s "R=range(10000, 30000)" "5 in R"
10000000 loops, best of 3: 0.0551 usec per loop

回答 6

定义数字之间的范围:

r = range(1,10)

然后使用它:

if num in r:
    print("All right!")

Define the range between the numbers:

r = range(1,10)

Then use it:

if num in r:
    print("All right!")

回答 7

两种比较三个整数并检查b是否在ac之间的方法

if a < b < c:
    pass

if a < b and b < c:
    pass

第一个看起来更易读,但是第二个运行得更快

让我们使用dis.dis进行比较:

    >>> dis.dis('a < b and b < c')
  1           0 LOAD_NAME                0 (a)
              2 LOAD_NAME                1 (b)
              4 COMPARE_OP               0 (<)
              6 JUMP_IF_FALSE_OR_POP    14
              8 LOAD_NAME                1 (b)
             10 LOAD_NAME                2 (c)
             12 COMPARE_OP               0 (<)
        >>   14 RETURN_VALUE
>>> dis.dis('a < b < c')
  1           0 LOAD_NAME                0 (a)
              2 LOAD_NAME                1 (b)
              4 DUP_TOP
              6 ROT_THREE
              8 COMPARE_OP               0 (<)
             10 JUMP_IF_FALSE_OR_POP    18
             12 LOAD_NAME                2 (c)
             14 COMPARE_OP               0 (<)
             16 RETURN_VALUE
        >>   18 ROT_TWO
             20 POP_TOP
             22 RETURN_VALUE
>>>

并使用timeit

~$ python3 -m timeit "1 < 2 and 2 < 3"
10000000 loops, best of 3: 0.0366 usec per loop

~$ python3 -m timeit "1 < 2 < 3"
10000000 loops, best of 3: 0.0396 usec per loop

此外,您可以按照之前的建议使用range,但是它要慢得多。

There are two ways to compare three integers and check whether b is between a and c:

if a < b < c:
    pass

and

if a < b and b < c:
    pass

The first one looks like more readable, but the second one runs faster.

Let’s compare using dis.dis:

    >>> dis.dis('a < b and b < c')
  1           0 LOAD_NAME                0 (a)
              2 LOAD_NAME                1 (b)
              4 COMPARE_OP               0 (<)
              6 JUMP_IF_FALSE_OR_POP    14
              8 LOAD_NAME                1 (b)
             10 LOAD_NAME                2 (c)
             12 COMPARE_OP               0 (<)
        >>   14 RETURN_VALUE
>>> dis.dis('a < b < c')
  1           0 LOAD_NAME                0 (a)
              2 LOAD_NAME                1 (b)
              4 DUP_TOP
              6 ROT_THREE
              8 COMPARE_OP               0 (<)
             10 JUMP_IF_FALSE_OR_POP    18
             12 LOAD_NAME                2 (c)
             14 COMPARE_OP               0 (<)
             16 RETURN_VALUE
        >>   18 ROT_TWO
             20 POP_TOP
             22 RETURN_VALUE
>>>

and using timeit:

~$ python3 -m timeit "1 < 2 and 2 < 3"
10000000 loops, best of 3: 0.0366 usec per loop

~$ python3 -m timeit "1 < 2 < 3"
10000000 loops, best of 3: 0.0396 usec per loop

also, you may use range, as suggested before, however it is much more slower.


回答 8

假设有3个非负整数:ab,和c。从数学上讲,如果我们想确定是否c介于a和之间b,可以使用以下公式:

(c-a)*(b-c)> = 0

或在Python中:

> print((c - a) * (b - c) >= 0)
True

Suppose there are 3 non-negative integers: a, b, and c. Mathematically speaking, if we want to determine if c is between a and b, inclusively, one can use this formula:

(c – a) * (b – c) >= 0

or in Python:

> print((c - a) * (b - c) >= 0)
True

回答 9

仅当数字介于10,000和30,000之间时,您才希望输出打印给定语句。

代码应该是;

if number >= 10000 and number <= 30000:
    print("you have to pay 5% taxes")

You want the output to print the given statement if and only if the number falls between 10,000 and 30,000.

Code should be;

if number >= 10000 and number <= 30000:
    print("you have to pay 5% taxes")

回答 10

条件应该是

if number == 10000 and number <= 30000:
     print("5% tax payable")

使用的原因number == 10000是,如果number的值是50000,并且我们使用number >= 10000该条件,那么条件将过去,这不是您想要的。

The condition should be,

if number == 10000 and number <= 30000:
     print("5% tax payable")

reason for using number == 10000 is that if number’s value is 50000 and if we use number >= 10000 the condition will pass, which is not what you want.


Python:检查“字典”是否为空似乎不起作用

问题:Python:检查“字典”是否为空似乎不起作用

我正在尝试检查字典是否为空,但是行为不正常。它只是跳过它并显示“ 联机”,除了显示消息外没有任何其他内容。有什么主意吗?

 def isEmpty(self, dictionary):
   for element in dictionary:
     if element:
       return True
     return False

 def onMessage(self, socket, message):
  if self.isEmpty(self.users) == False:
     socket.send("Nobody is online, please use REGISTER command" \
                 " in order to register into the server")
  else:
     socket.send("ONLINE " + ' ' .join(self.users.keys())) 

I am trying to check if a dictionary is empty but it doesn’t behave properly. It just skips it and displays ONLINE without anything except of display the message. Any ideas why ?

 def isEmpty(self, dictionary):
   for element in dictionary:
     if element:
       return True
     return False

 def onMessage(self, socket, message):
  if self.isEmpty(self.users) == False:
     socket.send("Nobody is online, please use REGISTER command" \
                 " in order to register into the server")
  else:
     socket.send("ONLINE " + ' ' .join(self.users.keys())) 

回答 0

空字典在Python中的计算结果为False

>>> dct = {}
>>> bool(dct)
False
>>> not dct
True
>>>

因此,您的isEmpty功能是不必要的。您需要做的只是:

def onMessage(self, socket, message):
    if not self.users:
        socket.send("Nobody is online, please use REGISTER command" \
                    " in order to register into the server")
    else:
        socket.send("ONLINE " + ' ' .join(self.users.keys()))

Empty dictionaries evaluate to False in Python:

>>> dct = {}
>>> bool(dct)
False
>>> not dct
True
>>>

Thus, your isEmpty function is unnecessary. All you need to do is:

def onMessage(self, socket, message):
    if not self.users:
        socket.send("Nobody is online, please use REGISTER command" \
                    " in order to register into the server")
    else:
        socket.send("ONLINE " + ' ' .join(self.users.keys()))

回答 1

您可以通过以下三种方法检查dict是否为空。我更喜欢只使用第一种方法。其他两种方式过于罗y。

test_dict = {}

if not test_dict:
    print "Dict is Empty"


if not bool(test_dict):
    print "Dict is Empty"


if len(test_dict) == 0:
    print "Dict is Empty"

Here are three ways you can check if dict is empty. I prefer using the first way only though. The other two ways are way too wordy.

test_dict = {}

if not test_dict:
    print "Dict is Empty"


if not bool(test_dict):
    print "Dict is Empty"


if len(test_dict) == 0:
    print "Dict is Empty"

回答 2

dict = {}
print(len(dict.keys()))

如果length为零,则表示dict为空

dict = {}
print(len(dict.keys()))

if length is zero means that dict is empty


回答 3

检查空字典的简单方法如下:

        a= {}

    1. if a == {}:
           print ('empty dict')
    2. if not a:
           print ('empty dict')

尽管方法1st在a = None时更为严格,但方法1将提供正确的结果,而方法2将提供不正确的结果。

Simple ways to check an empty dict are below:

        a= {}

    1. if a == {}:
           print ('empty dict')
    2. if not a:
           print ('empty dict')

Although method 1st is more strict as when a = None, method 1 will provide correct result but method 2 will give an incorrect result.


回答 4

字典可以自动转换为布尔值,布尔值为False空字典和True非空字典。

if myDictionary: non_empty_clause()
else: empty_clause()

如果这看起来太惯用了,您还可以测试len(myDictionary)零,或测试set(myDictionary.keys())一个空集,或仅测试的相等性{}

isEmpty函数不仅是不必要的,而且您的实现还存在多个我可以发现表面现象的问题。

  1. return False语句缩进太深了一层。它应该在for循环之外,并且与该for语句处于同一级别。如此一来,您的代码将只处理一个任意选择的密钥(如果存在一个密钥)。如果键不存在,则该函数将返回None,并将其强制转换为布尔False。哎哟! 所有空字典将被归类为假阴性。
  2. 如果字典不为空,则代码将仅处理一个键,并将其值强制转换为布尔值。您甚至不能假设每次调用都对同一个键进行评估。因此会有误报。
  3. 假设您更正了return False语句的缩进并将其移出for循环。然后,您得到的是所有键的布尔值OR,或者False如果字典为空。仍然会有误报和误报。进行更正并针对以下词典进行测试以获取证据。

myDictionary={0:'zero', '':'Empty string', None:'None value', False:'Boolean False value', ():'Empty tuple'}

A dictionary can be automatically cast to boolean which evaluates to False for empty dictionary and True for non-empty dictionary.

if myDictionary: non_empty_clause()
else: empty_clause()

If this looks too idiomatic, you can also test len(myDictionary) for zero, or set(myDictionary.keys()) for an empty set, or simply test for equality with {}.

The isEmpty function is not only unnecessary but also your implementation has multiple issues that I can spot prima-facie.

  1. The return False statement is indented one level too deep. It should be outside the for loop and at the same level as the for statement. As a result, your code will process only one, arbitrarily selected key, if a key exists. If a key does not exist, the function will return None, which will be cast to boolean False. Ouch! All the empty dictionaries will be classified as false-nagatives.
  2. If the dictionary is not empty, then the code will process only one key and return its value cast to boolean. You cannot even assume that the same key is evaluated each time you call it. So there will be false positives.
  3. Let us say you correct the indentation of the return False statement and bring it outside the for loop. Then what you get is the boolean OR of all the keys, or False if the dictionary empty. Still you will have false positives and false negatives. Do the correction and test against the following dictionary for an evidence.

myDictionary={0:'zero', '':'Empty string', None:'None value', False:'Boolean False value', ():'Empty tuple'}


回答 5

您也可以使用get()。最初,我认为它只能检查密钥是否存在。

>>> d = { 'a':1, 'b':2, 'c':{}}
>>> bool(d.get('c'))
False
>>> d['c']['e']=1
>>> bool(d.get('c'))
True

我喜欢get的是它不会触发异常,因此可以轻松遍历大型结构。

You can also use get(). Initially I believed it to only check if key existed.

>>> d = { 'a':1, 'b':2, 'c':{}}
>>> bool(d.get('c'))
False
>>> d['c']['e']=1
>>> bool(d.get('c'))
True

What I like with get is that it does not trigger an exception, so it makes it easy to traverse large structures.


回答 6

为什么不使用平等测试?

def is_empty(my_dict):
    """
    Print true if given dictionary is empty
    """
    if my_dict == {}:
        print("Dict is empty !")

Why not use equality test?

def is_empty(my_dict):
    """
    Print true if given dictionary is empty
    """
    if my_dict == {}:
        print("Dict is empty !")

回答 7

使用“任何”

dict = {}

if any(dict) :

     # true
     # dictionary is not empty 

else :

     # false 
     # dictionary is empty

use ‘any’

dict = {}

if any(dict) :

     # true
     # dictionary is not empty 

else :

     # false 
     # dictionary is empty

通过整数索引选择一行熊猫系列/数据框

问题:通过整数索引选择一行熊猫系列/数据框

我很好奇,为什么df[2]不支持,而df.ix[2]df[2:3]这两个工作。

In [26]: df.ix[2]
Out[26]: 
A    1.027680
B    1.514210
C   -1.466963
D   -0.162339
Name: 2000-01-03 00:00:00

In [27]: df[2:3]
Out[27]: 
                  A        B         C         D
2000-01-03  1.02768  1.51421 -1.466963 -0.162339

我希望df[2]df[2:3]与Python索引约定一致的方式进行工作。是否有设计原因不支持按单个整数索引行?

I am curious as to why df[2] is not supported, while df.ix[2] and df[2:3] both work.

In [26]: df.ix[2]
Out[26]: 
A    1.027680
B    1.514210
C   -1.466963
D   -0.162339
Name: 2000-01-03 00:00:00

In [27]: df[2:3]
Out[27]: 
                  A        B         C         D
2000-01-03  1.02768  1.51421 -1.466963 -0.162339

I would expect df[2] to work the same way as df[2:3] to be consistent with Python indexing convention. Is there a design reason for not supporting indexing row by single integer?


回答 0

回显@HYRY,请参阅0.11中的新文档

http://pandas.pydata.org/pandas-docs/stable/indexing.html

在这里,我们有了新的运算符,.iloc以明确支持仅整数索引,并且.loc明确支持仅标签索引

例如,想象这种情况

In [1]: df = pd.DataFrame(np.random.rand(5,2),index=range(0,10,2),columns=list('AB'))

In [2]: df
Out[2]: 
          A         B
0  1.068932 -0.794307
2 -0.470056  1.192211
4 -0.284561  0.756029
6  1.037563 -0.267820
8 -0.538478 -0.800654

In [5]: df.iloc[[2]]
Out[5]: 
          A         B
4 -0.284561  0.756029

In [6]: df.loc[[2]]
Out[6]: 
          A         B
2 -0.470056  1.192211

[] 仅对行进行切片(按标签位置)

echoing @HYRY, see the new docs in 0.11

http://pandas.pydata.org/pandas-docs/stable/indexing.html

Here we have new operators, .iloc to explicity support only integer indexing, and .loc to explicity support only label indexing

e.g. imagine this scenario

In [1]: df = pd.DataFrame(np.random.rand(5,2),index=range(0,10,2),columns=list('AB'))

In [2]: df
Out[2]: 
          A         B
0  1.068932 -0.794307
2 -0.470056  1.192211
4 -0.284561  0.756029
6  1.037563 -0.267820
8 -0.538478 -0.800654

In [5]: df.iloc[[2]]
Out[5]: 
          A         B
4 -0.284561  0.756029

In [6]: df.loc[[2]]
Out[6]: 
          A         B
2 -0.470056  1.192211

[] slices the rows (by label location) only


回答 1

DataFrame索引运算符的主要目的[]是选择列。

当索引运算符传递字符串或整数时,它将尝试查找具有该特定名称的列并将其作为Series返回。

因此,在上述问题中:df[2]搜索与整数值匹配的列名2。该列不存在,并且KeyError引发a。


使用切片符号时,DataFrame索引运算符完全更改行为以选择行

奇怪的是,当给定切片时,DataFrame索引运算符选择行,并且可以按整数位置或按索引标签来选择行。

df[2:3]

这将从整数位置为2的行开始切为3,最后一个元素除外。因此,只需一行。下面的代码选择从整数位置6开始的行,直到每第三行从20开始但不包括20的行。

df[6:20:3]

如果DataFrame索引中包含字符串,则还可以使用由字符串标签组成的切片。有关更多详细信息,请参见.iloc与.loc上的此解决方案

我几乎从未将这种切片符号与索引运算符一起使用,因为它不是显式的,而且几乎从未使用过。按行切片时,请坚持使用.loc/.iloc

The primary purpose of the DataFrame indexing operator, [] is to select columns.

When the indexing operator is passed a string or integer, it attempts to find a column with that particular name and return it as a Series.

So, in the question above: df[2] searches for a column name matching the integer value 2. This column does not exist and a KeyError is raised.


The DataFrame indexing operator completely changes behavior to select rows when slice notation is used

Strangely, when given a slice, the DataFrame indexing operator selects rows and can do so by integer location or by index label.

df[2:3]

This will slice beginning from the row with integer location 2 up to 3, exclusive of the last element. So, just a single row. The following selects rows beginning at integer location 6 up to but not including 20 by every third row.

df[6:20:3]

You can also use slices consisting of string labels if your DataFrame index has strings in it. For more details, see this solution on .iloc vs .loc.

I almost never use this slice notation with the indexing operator as its not explicit and hardly ever used. When slicing by rows, stick with .loc/.iloc.


回答 2

您可以将DataFrame视为Series的字典。df[key]尝试通过选择列索引key并返回Series对象。

但是,在[]内切片会对行进行切片,因为这是非常常见的操作。

您可以阅读文档以了解详细信息:

http://pandas.pydata.org/pandas-docs/stable/indexing.html#basics

You can think DataFrame as a dict of Series. df[key] try to select the column index by key and returns a Series object.

However slicing inside of [] slices the rows, because it’s a very common operation.

You can read the document for detail:

http://pandas.pydata.org/pandas-docs/stable/indexing.html#basics


回答 3

要基于索引访问熊猫表,还可以考虑使用numpy.as_array选项将表转换为Numpy数组,方法如下:

np_df = df.as_matrix()

然后

np_df[i] 

会工作。

To index-based access to the pandas table, one can also consider numpy.as_array option to convert the table to Numpy array as

np_df = df.as_matrix()

and then

np_df[i] 

would work.


回答 4

您可以看一下源代码

DataFrame具有对_slice()进行切片的私有函数DataFrame,并且它允许参数axis确定要切片的轴。在__getitem__()DataFrame不设置轴,同时调用_slice()。因此_slice(),默认情况下将其切片为轴0。

您可以进行一个简单的实验,这可能对您有所帮助:

print df._slice(slice(0, 2))
print df._slice(slice(0, 2), 0)
print df._slice(slice(0, 2), 1)

You can take a look at the source code .

DataFrame has a private function _slice() to slice the DataFrame, and it allows the parameter axis to determine which axis to slice. The __getitem__() for DataFrame doesn’t set the axis while invoking _slice(). So the _slice() slice it by default axis 0.

You can take a simple experiment, that might help you:

print df._slice(slice(0, 2))
print df._slice(slice(0, 2), 0)
print df._slice(slice(0, 2), 1)

回答 5

您可以像这样遍历数据帧。

for ad in range(1,dataframe_c.size):
    print(dataframe_c.values[ad])

you can loop through the data frame like this .

for ad in range(1,dataframe_c.size):
    print(dataframe_c.values[ad])

Python中是否存在“不相等”运算符?

问题:Python中是否存在“不相等”运算符?

你怎么说不等于?

喜欢

if hi == hi:
    print "hi"
elif hi (does not equal) bye:
    print "no hi"

是否有等同于==“不平等”的东西?

How would you say does not equal?

Like

if hi == hi:
    print "hi"
elif hi (does not equal) bye:
    print "no hi"

Is there something equivalent to == that means “not equal”?


回答 0

使用!=。请参阅比较运算符。为了比较对象身份,可以使用关键字is及其否定词is not

例如

1 == 1 #  -> True
1 != 1 #  -> False
[] is [] #-> False (distinct objects)
a = b = []; a is b # -> True (same object)

Use !=. See comparison operators. For comparing object identities, you can use the keyword is and its negation is not.

e.g.

1 == 1 #  -> True
1 != 1 #  -> False
[] is [] #-> False (distinct objects)
a = b = []; a is b # -> True (same object)

回答 1

不等于 != (vs等于==

您是否在问这样的事情?

answer = 'hi'

if answer == 'hi':     # equal
   print "hi"
elif answer != 'hi':   # not equal
   print "no hi"

Python-基本运算符图表可能会有所帮助。

Not equal != (vs equal ==)

Are you asking about something like this?

answer = 'hi'

if answer == 'hi':     # equal
   print "hi"
elif answer != 'hi':   # not equal
   print "no hi"

This Python – Basic Operators chart might be helpful.


回答 2

当两个值不同时,有一个!=(不相等)运算符返回True,尽管要小心类型,因为"1" != 1"1" == 1由于类型不同,它将始终返回True,并且始终返回False。Python是动态的但是强类型的,而其他静态类型的语言会抱怨比较不同的类型。

还有else子句:

# This will always print either "hi" or "no hi" unless something unforeseen happens.
if hi == "hi":     # The variable hi is being compared to the string "hi", strings are immutable in Python, so you could use the 'is' operator.
    print "hi"     # If indeed it is the string "hi" then print "hi"
else:              # hi and "hi" are not the same
    print "no hi"

is运算符是对象标识运算符,用于检查两个对象实际上是否相同:

a = [1, 2]
b = [1, 2]
print a == b # This will print True since they have the same values
print a is b # This will print False since they are different objects.

There’s the != (not equal) operator that returns True when two values differ, though be careful with the types because "1" != 1. This will always return True and "1" == 1 will always return False, since the types differ. Python is dynamically, but strongly typed, and other statically typed languages would complain about comparing different types.

There’s also the else clause:

# This will always print either "hi" or "no hi" unless something unforeseen happens.
if hi == "hi":     # The variable hi is being compared to the string "hi", strings are immutable in Python, so you could use the 'is' operator.
    print "hi"     # If indeed it is the string "hi" then print "hi"
else:              # hi and "hi" are not the same
    print "no hi"

The is operator is the object identity operator used to check if two objects in fact are the same:

a = [1, 2]
b = [1, 2]
print a == b # This will print True since they have the same values
print a is b # This will print False since they are different objects.

回答 3

您可以同时使用!=<>

但是,请注意,不建议!=<>不推荐的地方使用它。

You can use both != or <>.

However, note that != is preferred where <> is deprecated.


回答 4

看到其他所有人都已经列出了大多数其他方式来表示不平等,我将添加:

if not (1) == (1): # This will eval true then false
    # (ie: 1 == 1 is true but the opposite(not) is false)
    print "the world is ending" # This will only run on a if true
elif (1+1) != (2): #second if
    print "the world is ending"
    # This will only run if the first if is false and the second if is true
else: # this will only run if the if both if's are false
    print "you are good for another day"

在这种情况下,很容易将正==(true)的检查切换为负,反之亦然…

Seeing as everyone else has already listed most of the other ways to say not equal I will just add:

if not (1) == (1): # This will eval true then false
    # (ie: 1 == 1 is true but the opposite(not) is false)
    print "the world is ending" # This will only run on a if true
elif (1+1) != (2): #second if
    print "the world is ending"
    # This will only run if the first if is false and the second if is true
else: # this will only run if the if both if's are false
    print "you are good for another day"

in this case it is simple switching the check of positive == (true) to negative and vise versa…


回答 5

您可以将“不等于”用于“不等于”或“!=“。请参见以下示例:

a = 2
if a == 2:
   print("true")
else:
   print("false")

上面的代码将在“ if”条件之前将“ true”打印为a = 2。现在,请参见下面的“不等于”代码

a = 2
if a is not 3:
   print("not equal")
else:
   print("equal")

上面的代码将打印“不等于”,即早先分配的a = 2。

You can use “is not” for “not equal” or “!=”. Please see the example below:

a = 2
if a == 2:
   print("true")
else:
   print("false")

The above code will print “true” as a = 2 assigned before the “if” condition. Now please see the code below for “not equal”

a = 2
if a is not 3:
   print("not equal")
else:
   print("equal")

The above code will print “not equal” as a = 2 as assigned earlier.


回答 6

Python中有两个用于“不相等”条件的运算符-

a。)!=如果两个操作数的值不相等,则条件变为true。(a!= b)是正确的。

b。)<>如果两个操作数的值不相等,则条件变为true。(a <> b)是正确的。这类似于!=运算符。

There are two operators in Python for the “not equal” condition –

a.) != If values of the two operands are not equal, then the condition becomes true. (a != b) is true.

b.) <> If values of the two operands are not equal, then the condition becomes true. (a <> b) is true. This is similar to the != operator.


回答 7

使用!=<>。两者代表不平等。

比较运算符<>!=是相同运算符的替代拼写。!=是首选拼写;<>是过时的。[参考:Python语言参考]

Use != or <>. Both stands for not equal.

The comparison operators <> and != are alternate spellings of the same operator. != is the preferred spelling; <> is obsolescent. [Reference: Python language reference]


回答 8

您可以简单地执行以下操作:

if hi == hi:
    print "hi"
elif hi != bye:
     print "no hi"

You can simply do:

if hi == hi:
    print "hi"
elif hi != bye:
     print "no hi"

Python和JavaScript之间的JSON日期时间

问题:Python和JavaScript之间的JSON日期时间

我想使用JSON从Python发送序列化形式的datetime.datetime对象,并使用JSON在JavaScript中反序列化。做这个的最好方式是什么?

I want to send a datetime.datetime object in serialized form from Python using JSON and de-serialize in JavaScript using JSON. What is the best way to do this?


回答 0

您可以在json.dumps中添加“默认”参数来处理此问题:

date_handler = lambda obj: (
    obj.isoformat()
    if isinstance(obj, (datetime.datetime, datetime.date))
    else None
)
json.dumps(datetime.datetime.now(), default=date_handler)
'"2010-04-20T20:08:21.634121"'

这是ISO 8601格式。

更全面的默认处理程序功能:

def handler(obj):
    if hasattr(obj, 'isoformat'):
        return obj.isoformat()
    elif isinstance(obj, ...):
        return ...
    else:
        raise TypeError, 'Object of type %s with value of %s is not JSON serializable' % (type(obj), repr(obj))

更新:添加了类型和值的输出。
更新:还处理日期

You can add the ‘default’ parameter to json.dumps to handle this:

date_handler = lambda obj: (
    obj.isoformat()
    if isinstance(obj, (datetime.datetime, datetime.date))
    else None
)
json.dumps(datetime.datetime.now(), default=date_handler)
'"2010-04-20T20:08:21.634121"'

Which is ISO 8601 format.

A more comprehensive default handler function:

def handler(obj):
    if hasattr(obj, 'isoformat'):
        return obj.isoformat()
    elif isinstance(obj, ...):
        return ...
    else:
        raise TypeError, 'Object of type %s with value of %s is not JSON serializable' % (type(obj), repr(obj))

Update: Added output of type as well as value.
Update: Also handle date


回答 1

对于跨语言项目,我发现包含RfC 3339日期的字符串是最好的选择。RfC 3339日期如下所示:

  1985-04-12T23:20:50.52Z

我认为大多数格式都是显而易见的。唯一有点不寻常的事情可能是结尾处的“ Z”。它代表GMT / UTC。您还可以为CEST添加夏令时偏移,例如+02:00(德国夏季)。我个人更喜欢将所有内容保留在UTC中,直到显示为止。

为了显示,比较和存储,您可以将其保留为所有语言的字符串格式。如果您需要日期进行计算,可以轻松将其转换为大多数语言的原始日期对象。

因此,生成这样的JSON:

  json.dump(datetime.now().strftime('%Y-%m-%dT%H:%M:%SZ'))

不幸的是,Javascript的Date构造函数不接受RfC 3339字符串,但是Internet上有很多解析器

huTools.hujson会尝试处理Python代码中可能遇到的最常见的编码问题,包括日期/日期时间对象,同时正确处理时区。

For cross-language projects, I found out that strings containing RfC 3339 dates are the best way to go. An RfC 3339 date looks like this:

  1985-04-12T23:20:50.52Z

I think most of the format is obvious. The only somewhat unusual thing may be the “Z” at the end. It stands for GMT/UTC. You could also add a timezone offset like +02:00 for CEST (Germany in summer). I personally prefer to keep everything in UTC until it is displayed.

For displaying, comparisons and storage you can leave it in string format across all languages. If you need the date for calculations easy to convert it back to a native date object in most language.

So generate the JSON like this:

  json.dump(datetime.now().strftime('%Y-%m-%dT%H:%M:%SZ'))

Unfortunately, Javascript’s Date constructor doesn’t accept RfC 3339 strings but there are many parsers available on the Internet.

huTools.hujson tries to handle the most common encoding issues you might come across in Python code including date/datetime objects while handling timezones correctly.


回答 2

我已经解决了。

假设您有一个使用datetime.now()创建的Python datetime对象d。其值为:

datetime.datetime(2011, 5, 25, 13, 34, 5, 787000)

您可以将其序列化为JSON作为ISO 8601日期时间字符串:

import json    
json.dumps(d.isoformat())

日期时间对象示例将序列化为:

'"2011-05-25T13:34:05.787000"'

一旦在Javascript层中收到此值,就可以构造一个Date对象:

var d = new Date("2011-05-25T13:34:05.787000");

从Javascript 1.8.5开始,Date对象具有toJSON方法,该方法返回标准格式的字符串。要将上述Javascript对象序列化回JSON,命令将是:

d.toJSON()

这会给你:

'2011-05-25T20:34:05.787Z'

一旦在Python中收到此字符串,就可以将其反序列化为datetime对象:

datetime.strptime('2011-05-25T20:34:05.787Z', '%Y-%m-%dT%H:%M:%S.%fZ')

这将导致以下日期时间对象,该对象与您开始时使用的对象相同,因此是正确的:

datetime.datetime(2011, 5, 25, 20, 34, 5, 787000)

I’ve worked it out.

Let’s say you have a Python datetime object, d, created with datetime.now(). Its value is:

datetime.datetime(2011, 5, 25, 13, 34, 5, 787000)

You can serialize it to JSON as an ISO 8601 datetime string:

import json    
json.dumps(d.isoformat())

The example datetime object would be serialized as:

'"2011-05-25T13:34:05.787000"'

This value, once received in the Javascript layer, can construct a Date object:

var d = new Date("2011-05-25T13:34:05.787000");

As of Javascript 1.8.5, Date objects have a toJSON method, which returns a string in a standard format. To serialize the above Javascript object back to JSON, therefore, the command would be:

d.toJSON()

Which would give you:

'2011-05-25T20:34:05.787Z'

This string, once received in Python, could be deserialized back to a datetime object:

datetime.strptime('2011-05-25T20:34:05.787Z', '%Y-%m-%dT%H:%M:%S.%fZ')

This results in the following datetime object, which is the same one you started with and therefore correct:

datetime.datetime(2011, 5, 25, 20, 34, 5, 787000)

回答 3

使用json,您可以子类化JSONEncoder并重写default()方法以提供自己的自定义序列化程序:

import json
import datetime

class DateTimeJSONEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, datetime.datetime):
            return obj.isoformat()
        else:
            return super(DateTimeJSONEncoder, self).default(obj)

然后,您可以这样称呼它:

>>> DateTimeJSONEncoder().encode([datetime.datetime.now()])
'["2010-06-15T14:42:28"]'

Using json, you can subclass JSONEncoder and override the default() method to provide your own custom serializers:

import json
import datetime

class DateTimeJSONEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, datetime.datetime):
            return obj.isoformat()
        else:
            return super(DateTimeJSONEncoder, self).default(obj)

Then, you can call it like this:

>>> DateTimeJSONEncoder().encode([datetime.datetime.now()])
'["2010-06-15T14:42:28"]'

回答 4

这是一个使用标准库json模块递归编码和解码datetime.datetime和datetime.date对象的完整解决方案。此后需要Python> = 2.6,因为从那时起%f仅支持datetime.datetime.strptime()格式字符串中的格式代码。对于Python 2.5支持,%f在尝试转换之前,请从ISO日期字符串中删除和除去微秒,但是,您当然会降低微秒的精度。为了与其他来源的ISO日期字符串互操作,其中可能包括时区名称或UTC偏移量,您可能还需要在转换之前剥离日期字符串的某些部分。有关ISO日期字符串(和许多其他日期格式)的完整解析器,请参见第三方dateutil模块。

仅当ISO日期字符串是JavaScript文字对象表示法中的值或对象中嵌套结构中的值时,才起作用。作为顶级数组项目的ISO日期字符串将不会被解码。

即这有效:

date = datetime.datetime.now()
>>> json = dumps(dict(foo='bar', innerdict=dict(date=date)))
>>> json
'{"innerdict": {"date": "2010-07-15T13:16:38.365579"}, "foo": "bar"}'
>>> loads(json)
{u'innerdict': {u'date': datetime.datetime(2010, 7, 15, 13, 16, 38, 365579)},
u'foo': u'bar'}

这也是:

>>> json = dumps(['foo', 'bar', dict(date=date)])
>>> json
'["foo", "bar", {"date": "2010-07-15T13:16:38.365579"}]'
>>> loads(json)
[u'foo', u'bar', {u'date': datetime.datetime(2010, 7, 15, 13, 16, 38, 365579)}]

但这不能按预期工作:

>>> json = dumps(['foo', 'bar', date])
>>> json
'["foo", "bar", "2010-07-15T13:16:38.365579"]'
>>> loads(json)
[u'foo', u'bar', u'2010-07-15T13:16:38.365579']

这是代码:

__all__ = ['dumps', 'loads']

import datetime

try:
    import json
except ImportError:
    import simplejson as json

class JSONDateTimeEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, (datetime.date, datetime.datetime)):
            return obj.isoformat()
        else:
            return json.JSONEncoder.default(self, obj)

def datetime_decoder(d):
    if isinstance(d, list):
        pairs = enumerate(d)
    elif isinstance(d, dict):
        pairs = d.items()
    result = []
    for k,v in pairs:
        if isinstance(v, basestring):
            try:
                # The %f format code is only supported in Python >= 2.6.
                # For Python <= 2.5 strip off microseconds
                # v = datetime.datetime.strptime(v.rsplit('.', 1)[0],
                #     '%Y-%m-%dT%H:%M:%S')
                v = datetime.datetime.strptime(v, '%Y-%m-%dT%H:%M:%S.%f')
            except ValueError:
                try:
                    v = datetime.datetime.strptime(v, '%Y-%m-%d').date()
                except ValueError:
                    pass
        elif isinstance(v, (dict, list)):
            v = datetime_decoder(v)
        result.append((k, v))
    if isinstance(d, list):
        return [x[1] for x in result]
    elif isinstance(d, dict):
        return dict(result)

def dumps(obj):
    return json.dumps(obj, cls=JSONDateTimeEncoder)

def loads(obj):
    return json.loads(obj, object_hook=datetime_decoder)

if __name__ == '__main__':
    mytimestamp = datetime.datetime.utcnow()
    mydate = datetime.date.today()
    data = dict(
        foo = 42,
        bar = [mytimestamp, mydate],
        date = mydate,
        timestamp = mytimestamp,
        struct = dict(
            date2 = mydate,
            timestamp2 = mytimestamp
        )
    )

    print repr(data)
    jsonstring = dumps(data)
    print jsonstring
    print repr(loads(jsonstring))

Here’s a fairly complete solution for recursively encoding and decoding datetime.datetime and datetime.date objects using the standard library json module. This needs Python >= 2.6 since the %f format code in the datetime.datetime.strptime() format string is only supported in since then. For Python 2.5 support, drop the %f and strip the microseconds from the ISO date string before trying to convert it, but you’ll loose microseconds precision, of course. For interoperability with ISO date strings from other sources, which may include a time zone name or UTC offset, you may also need to strip some parts of the date string before the conversion. For a complete parser for ISO date strings (and many other date formats) see the third-party dateutil module.

Decoding only works when the ISO date strings are values in a JavaScript literal object notation or in nested structures within an object. ISO date strings, which are items of a top-level array will not be decoded.

I.e. this works:

date = datetime.datetime.now()
>>> json = dumps(dict(foo='bar', innerdict=dict(date=date)))
>>> json
'{"innerdict": {"date": "2010-07-15T13:16:38.365579"}, "foo": "bar"}'
>>> loads(json)
{u'innerdict': {u'date': datetime.datetime(2010, 7, 15, 13, 16, 38, 365579)},
u'foo': u'bar'}

And this too:

>>> json = dumps(['foo', 'bar', dict(date=date)])
>>> json
'["foo", "bar", {"date": "2010-07-15T13:16:38.365579"}]'
>>> loads(json)
[u'foo', u'bar', {u'date': datetime.datetime(2010, 7, 15, 13, 16, 38, 365579)}]

But this doesn’t work as expected:

>>> json = dumps(['foo', 'bar', date])
>>> json
'["foo", "bar", "2010-07-15T13:16:38.365579"]'
>>> loads(json)
[u'foo', u'bar', u'2010-07-15T13:16:38.365579']

Here’s the code:

__all__ = ['dumps', 'loads']

import datetime

try:
    import json
except ImportError:
    import simplejson as json

class JSONDateTimeEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, (datetime.date, datetime.datetime)):
            return obj.isoformat()
        else:
            return json.JSONEncoder.default(self, obj)

def datetime_decoder(d):
    if isinstance(d, list):
        pairs = enumerate(d)
    elif isinstance(d, dict):
        pairs = d.items()
    result = []
    for k,v in pairs:
        if isinstance(v, basestring):
            try:
                # The %f format code is only supported in Python >= 2.6.
                # For Python <= 2.5 strip off microseconds
                # v = datetime.datetime.strptime(v.rsplit('.', 1)[0],
                #     '%Y-%m-%dT%H:%M:%S')
                v = datetime.datetime.strptime(v, '%Y-%m-%dT%H:%M:%S.%f')
            except ValueError:
                try:
                    v = datetime.datetime.strptime(v, '%Y-%m-%d').date()
                except ValueError:
                    pass
        elif isinstance(v, (dict, list)):
            v = datetime_decoder(v)
        result.append((k, v))
    if isinstance(d, list):
        return [x[1] for x in result]
    elif isinstance(d, dict):
        return dict(result)

def dumps(obj):
    return json.dumps(obj, cls=JSONDateTimeEncoder)

def loads(obj):
    return json.loads(obj, object_hook=datetime_decoder)

if __name__ == '__main__':
    mytimestamp = datetime.datetime.utcnow()
    mydate = datetime.date.today()
    data = dict(
        foo = 42,
        bar = [mytimestamp, mydate],
        date = mydate,
        timestamp = mytimestamp,
        struct = dict(
            date2 = mydate,
            timestamp2 = mytimestamp
        )
    )

    print repr(data)
    jsonstring = dumps(data)
    print jsonstring
    print repr(loads(jsonstring))

回答 5

如果您确定只有Javascript将使用JSON,则我更喜欢Date直接传递Javascript 对象。

对象ctime()上的方法datetime将返回Javascript Date对象可以理解的字符串。

import datetime
date = datetime.datetime.today()
json = '{"mydate":new Date("%s")}' % date.ctime()

Javascript将很乐意将其用作对象文字,并且您已经内置了Date对象。

If you’re certain that only Javascript will be consuming the JSON, I prefer to pass Javascript Date objects directly.

The ctime() method on datetime objects will return a string that the Javascript Date object can understand.

import datetime
date = datetime.datetime.today()
json = '{"mydate":new Date("%s")}' % date.ctime()

Javascript will happily use that as an object literal, and you’ve got your Date object built right in.


回答 6

比赛后期… :)

一个非常简单的解决方案是修补json模块的默认值。例如:

import json
import datetime

json.JSONEncoder.default = lambda self,obj: (obj.isoformat() if isinstance(obj, datetime.datetime) else None)

现在,您可以使用json.dumps(),就好像它一直支持日期时间一样。

json.dumps({'created':datetime.datetime.now()})

如果您需要始终对json模块进行此扩展,并且希望不更改您或其他人使用json序列化的方式(无论是否使用现有代码),则这是有道理的。

请注意,有些人可能认为以这种方式对库进行修补是不好的做法。如果您可能希望以多种方式扩展应用程序,则需要格外小心-在这种情况下,我建议使用ramen或JT解决方案,并在每种情况下选择合适的json扩展名。

Late in the game… :)

A very simple solution is to patch the json module default. For example:

import json
import datetime

json.JSONEncoder.default = lambda self,obj: (obj.isoformat() if isinstance(obj, datetime.datetime) else None)

Now, you can use json.dumps() as if it had always supported datetime…

json.dumps({'created':datetime.datetime.now()})

This makes sense if you require this extension to the json module to always kick in and wish to not change the way you or others use json serialization (either in existing code or not).

Note that some may consider patching libraries in that way as bad practice. Special care need to be taken in case you may wish to extend your application in more than one way – is such a case, I suggest to use the solution by ramen or JT and choose the proper json extension in each case.


回答 7

除了时间戳,没有什么可添加到社区Wiki答案中了!

Javascript使用以下格式:

new Date().toJSON() // "2016-01-08T19:00:00.123Z"

Python端(有关json.dumps处理程序,请参见其他答案):

>>> from datetime import datetime
>>> d = datetime.strptime('2016-01-08T19:00:00.123Z', '%Y-%m-%dT%H:%M:%S.%fZ')
>>> d
datetime.datetime(2016, 1, 8, 19, 0, 0, 123000)
>>> d.isoformat() + 'Z'
'2016-01-08T19:00:00.123000Z'

如果将Z保留在外,那么诸如angular的前端框架将无法在浏览器本地时区中显示日期:

> $filter('date')('2016-01-08T19:00:00.123000Z', 'yyyy-MM-dd HH:mm:ss')
"2016-01-08 20:00:00"
> $filter('date')('2016-01-08T19:00:00.123000', 'yyyy-MM-dd HH:mm:ss')
"2016-01-08 19:00:00"

Not much to add to the community wiki answer, except for timestamp!

Javascript uses the following format:

new Date().toJSON() // "2016-01-08T19:00:00.123Z"

Python side (for the json.dumps handler, see the other answers):

>>> from datetime import datetime
>>> d = datetime.strptime('2016-01-08T19:00:00.123Z', '%Y-%m-%dT%H:%M:%S.%fZ')
>>> d
datetime.datetime(2016, 1, 8, 19, 0, 0, 123000)
>>> d.isoformat() + 'Z'
'2016-01-08T19:00:00.123000Z'

If you leave that Z out, frontend frameworks like angular can not display the date in browser-local timezone:

> $filter('date')('2016-01-08T19:00:00.123000Z', 'yyyy-MM-dd HH:mm:ss')
"2016-01-08 20:00:00"
> $filter('date')('2016-01-08T19:00:00.123000', 'yyyy-MM-dd HH:mm:ss')
"2016-01-08 19:00:00"

回答 8

在python方面:

import time, json
from datetime import datetime as dt
your_date = dt.now()
data = json.dumps(time.mktime(your_date.timetuple())*1000)
return data # data send to javascript

在JavaScript方面:

var your_date = new Date(data)

数据来自python的地方

On python side:

import time, json
from datetime import datetime as dt
your_date = dt.now()
data = json.dumps(time.mktime(your_date.timetuple())*1000)
return data # data send to javascript

On javascript side:

var your_date = new Date(data)

where data is result from python


回答 9

我的建议是使用一个库。pypi.org上有几个可用的。

我使用这个,它很好用:https : //pypi.python.org/pypi/asjson

My advice is to use a library. There are several available at pypi.org.

I use this one, it it works good: https://pypi.python.org/pypi/asjson


回答 10

显然,“正确的” JSON(很好的JavaScript)日期格式是2012-04-23T18:25:43.511Z-UTC和“ Z”。如果没有此功能,则从字符串创建Date()对象时,JavaScript将使用Web浏览器的本地时区。

对于“天真的”时间(Python称没有时区的时间,并且假定是本地时间),以下内容将强制使用本地时区,以便随后可以将其正确转换为UTC:

def default(obj):
    if hasattr(obj, "json") and callable(getattr(obj, "json")):
        return obj.json()
    if hasattr(obj, "isoformat") and callable(getattr(obj, "isoformat")):
        # date/time objects
        if not obj.utcoffset():
            # add local timezone to "naive" local time
            # /programming/2720319/python-figure-out-local-timezone
            tzinfo = datetime.now(timezone.utc).astimezone().tzinfo
            obj = obj.replace(tzinfo=tzinfo)
        # convert to UTC
        obj = obj.astimezone(timezone.utc)
        # strip the UTC offset
        obj = obj.replace(tzinfo=None)
        return obj.isoformat() + "Z"
    elif hasattr(obj, "__str__") and callable(getattr(obj, "__str__")):
        return str(obj)
    else:
        print("obj:", obj)
        raise TypeError(obj)

def dump(j, io):
    json.dump(j, io, indent=2, default=default)

为什么这么难。

Apparently The “right” JSON (well JavaScript) date format is 2012-04-23T18:25:43.511Z – UTC and “Z”. Without this JavaScript will use the web browser’s local timezone when creating a Date() object from the string.

For a “naive” time (what Python calls a time with no timezone and this assumes is local) the below will force local timezone so that it can then be correctly converted to UTC:

def default(obj):
    if hasattr(obj, "json") and callable(getattr(obj, "json")):
        return obj.json()
    if hasattr(obj, "isoformat") and callable(getattr(obj, "isoformat")):
        # date/time objects
        if not obj.utcoffset():
            # add local timezone to "naive" local time
            # https://stackoverflow.com/questions/2720319/python-figure-out-local-timezone
            tzinfo = datetime.now(timezone.utc).astimezone().tzinfo
            obj = obj.replace(tzinfo=tzinfo)
        # convert to UTC
        obj = obj.astimezone(timezone.utc)
        # strip the UTC offset
        obj = obj.replace(tzinfo=None)
        return obj.isoformat() + "Z"
    elif hasattr(obj, "__str__") and callable(getattr(obj, "__str__")):
        return str(obj)
    else:
        print("obj:", obj)
        raise TypeError(obj)

def dump(j, io):
    json.dump(j, io, indent=2, default=default)

why is this so hard.


回答 11

对于从Python到JavaScript的日期转换,日期对象必须采用特定的ISO格式,即ISO格式或UNIX数字。如果ISO格式缺少某些信息,则可以先使用Date.parse转换为Unix数字。此外,Date.parse也可以与React一起使用,而新的Date可能会触发异常。

如果您有一个不带毫秒的DateTime对象,则需要考虑以下因素。:

  var unixDate = Date.parse('2016-01-08T19:00:00') 
  var desiredDate = new Date(unixDate).toLocaleDateString();

在API调用之后,示例日期也可以是result.data对象中的变量。

有关以所需格式显示日期的选项(例如,显示较长的工作日),请查看MDN文档

For the Python to JavaScript date conversion, the date object needs to be in specific ISO format, i.e. ISO format or UNIX number. If the ISO format lacks some info, then you can convert to the Unix number with Date.parse first. Moreover, Date.parse works with React as well while new Date might trigger an exception.

In case you have a DateTime object without milliseconds, the following needs to be considered. :

  var unixDate = Date.parse('2016-01-08T19:00:00') 
  var desiredDate = new Date(unixDate).toLocaleDateString();

The example date could equally be a variable in the result.data object after an API call.

For options to display the date in the desired format (e.g. to display long weekdays) check out the MDN doc.


如何使用pass语句?

问题:如何使用pass语句?

我正在学习Python,并且已经到达有关该pass语句的部分。我正在使用的指南将其定义Null为通常用作占位符的语句。

我仍然不完全明白那是什么意思。有人可以告诉我一个简单/基本的情况下使用该pass语句以及为什么需要该语句吗?

I am in the process of learning Python and I have reached the section about the pass statement. The guide I’m using defines it as being a Null statement that is commonly used as a placeholder.

I still don’t fully understand what that means though. Can someone show me a simple/basic situation where the pass statement would be used and why it is needed?


回答 0

假设您正在使用尚未实现的某些方法设计一个新类。

class MyClass(object):
    def meth_a(self):
        pass

    def meth_b(self):
        print "I'm meth_b"

如果您不使用pass,则代码将无法运行。

然后,您将获得:

IndentationError: expected an indented block

总而言之,该pass语句没有什么特别的,但是可以充当占位符,如此处所示。

Suppose you are designing a new class with some methods that you don’t want to implement, yet.

class MyClass(object):
    def meth_a(self):
        pass

    def meth_b(self):
        print "I'm meth_b"

If you were to leave out the pass, the code wouldn’t run.

You would then get an:

IndentationError: expected an indented block

To summarize, the pass statement does nothing particular, but it can act as a placeholder, as demonstrated here.


回答 1

Python有句法的要求,即代码块(后ifexceptdefclass等等)不能为空。但是,空代码块在各种不同的上下文中都很有用,例如下面的示例,这是我见过的最常见的用例。

因此,如果在代码块中什么也不会发生,pass则需要a 来使该块不产生IndentationError。或者,可以使用任何语句(仅包括要求值的术语,如Ellipsis文字...或字符串,通常是文档字符串),但要说明的pass是,实际上不应该发生任何事情,不需要实际求值,并且(至少暂时)存储在内存中。

  • 忽略(全部或)某种类型的Exception(例如来自xml):

    try:
        self.version = "Expat %d.%d.%d" % expat.version_info
    except AttributeError:
        pass # unknown
    

    注意:忽略所有类型的加薪,如下面的示例中所示pandas,通常被认为是不好的做法,因为它还会捕获可能应该传递给调用者的异常,例如KeyboardInterruptor SystemExit(或HardwareIsOnFireError– 甚至您如何知道自己不是在定义了特定错误的自定义框上运行,某些调用应用程序可能想知道这些错误?)。

    try:
        os.unlink(filename_larry)
    except:
        pass
    

    替代地,至少except Error:或在这种情况下优选地except OSError:被认为是更好的实践。快速分析我安装的所有python模块后,我发现所有except ...: pass语句中有10%以上会捕获所有异常,因此在python编程中它仍然是常见的模式。

  • 派生不会添加新行为的异常类(例如scipy):

    class CompileError(Exception):
        pass
    

    同样,用作抽象基类的类通常具有显式的空值__init__或子类应该派生的其他方法。(例如pebl

    class _BaseSubmittingController(_BaseController):
        def submit(self, tasks): pass
        def retrieve(self, deferred_results): pass
    
  • 测试该代码可以针对一些测试值正确运行,而无需关心结果(来自mpmath):

    for x, error in MDNewton(mp, f, (1,-2), verbose=0,
                             norm=lambda x: norm(x, inf)):
        pass
    
  • 在类或函数定义中,通常已经有一个文档字符串,作为强制性语句要作为块中唯一的内容执行。在这种情况下,该块可能包含pass 文档字符串之外的其他内容,以便说“这确实是无所事事。”,例如pebl

    class ParsingError(Exception): 
        """Error encountered while parsing an ill-formed datafile."""
        pass
    
  • 在某些情况下,pass用作占位符时说“此方法/类/ if-block / …尚未实现,但这将是执行此操作的地方”,尽管我个人更喜欢该Ellipsis文字...,以便在前面的示例中,请严格区分此内容和故意的“无操作”。(请注意,省略号文字仅在Python 3中才是有效的表达式。
    例如,如果我用粗笔写出一个模型,我可能会写

    def update_agent(agent):
        ... 
    

    其他人可能有的地方

    def update_agent(agent):
        pass
    

    之前

    def time_step(agents):
        for agent in agents:
            update_agent(agent)
    

    提醒您update_agent稍后再填写该功能,但已经运行了一些测试以查看其余代码是否按预期运行。(这种情况的第三个选项是raise NotImplementedError。这在两种情况下特别有用:“每个子类都应实现此抽象方法,在此基类中没有定义它的通用方法”,或“此函数具有此名称尚未在此版本中实现,但这是其签名将显示为的样子”

Python has the syntactical requirement that code blocks (after if, except, def, class etc.) cannot be empty. Empty code blocks are however useful in a variety of different contexts, such as in examples below, which are the most frequent use cases I have seen.

Therefore, if nothing is supposed to happen in a code block, a pass is needed for such a block to not produce an IndentationError. Alternatively, any statement (including just a term to be evaluated, like the Ellipsis literal ... or a string, most often a docstring) can be used, but the pass makes clear that indeed nothing is supposed to happen, and does not need to be actually evaluated and (at least temporarily) stored in memory.

  • Ignoring (all or) a certain type of Exception (example from xml):

    try:
        self.version = "Expat %d.%d.%d" % expat.version_info
    except AttributeError:
        pass # unknown
    

    Note: Ignoring all types of raises, as in the following example from pandas, is generally considered bad practice, because it also catches exceptions that should probably be passed on to the caller, e.g. KeyboardInterrupt or SystemExit (or even HardwareIsOnFireError – How do you know you aren’t running on a custom box with specific errors defined, which some calling application would want to know about?).

    try:
        os.unlink(filename_larry)
    except:
        pass
    

    Instead using at least except Error: or in this case preferably except OSError: is considered much better practice. A quick analysis of all python modules I have installed gave me that more than 10% of all except ...: pass statements catch all exceptions, so it’s still a frequent pattern in python programming.

  • Deriving an exception class that does not add new behaviour (e.g. in scipy):

    class CompileError(Exception):
        pass
    

    Similarly, classes intended as abstract base class often have an explicit empty __init__ or other methods that subclasses are supposed to derive. (e.g. pebl)

    class _BaseSubmittingController(_BaseController):
        def submit(self, tasks): pass
        def retrieve(self, deferred_results): pass
    
  • Testing that code runs properly for a few test values, without caring about the results (from mpmath):

    for x, error in MDNewton(mp, f, (1,-2), verbose=0,
                             norm=lambda x: norm(x, inf)):
        pass
    
  • In class or function definitions, often a docstring is already in place as the obligatory statement to be executed as the only thing in the block. In such cases, the block may contain pass in addition to the docstring in order to say “This is indeed intended to do nothing.”, for example in pebl:

    class ParsingError(Exception): 
        """Error encountered while parsing an ill-formed datafile."""
        pass
    
  • In some cases, pass is used as a placeholder to say “This method/class/if-block/… has not been implemented yet, but this will be the place to do it”, although I personally prefer the Ellipsis literal ... in order to strictly differentiate between this and the intentional “no-op” in the previous example. (Note that the Ellipsis literal is a valid expression only in Python 3)
    For example, if I write a model in broad strokes, I might write

    def update_agent(agent):
        ... 
    

    where others might have

    def update_agent(agent):
        pass
    

    before

    def time_step(agents):
        for agent in agents:
            update_agent(agent)
    

    as a reminder to fill in the update_agent function at a later point, but run some tests already to see if the rest of the code behaves as intended. (A third option for this case is raise NotImplementedError. This is useful in particular for two cases: Either “This abstract method should be implemented by every subclass, there is no generic way to define it in this base class”, or “This function, with this name, is not yet implemented in this release, but this is what its signature will look like”)


回答 2

除了将其用作未实现函数的占位符外,它pass还可用于填充if-else语句(“显式优于隐式。”)

def some_silly_transform(n):
    # Even numbers should be divided by 2
    if n % 2 == 0:
        n /= 2
        flag = True
    # Negative odd numbers should return their absolute value
    elif n < 0:
        n = -n
        flag = True
    # Otherwise, number should remain unchanged
    else:
        pass

当然,在这种情况下,可能会使用return而不是分配,但是在需要突变的情况下,这种方法效果最佳。

使用passhere对警告将来的维护者(包括您自己!)不要在条件语句之外放置多余的步骤特别有用。在上面的示例中,flag在两个具体提到的情况下设置了,但在else-case中没有设置。如果不使用pass,将来的程序员可能会转移flag = True到该条件之外,因此flag所有情况下都应如此。


另一种情况是通常在文件底部看到样板函数:

if __name__ == "__main__":
    pass

在某些文件中,最好保留其中的内容pass,以便以后进行更轻松的编辑,并明确表明在单独运行文件时不会发生任何事情。


最后,如其他答案中所述,捕获异常时不执行任何操作可能很有用:

try:
    n[i] = 0
except IndexError:
    pass

Besides its use as a placeholder for unimplemented functions, pass can be useful in filling out an if-else statement (“Explicit is better than implicit.”)

def some_silly_transform(n):
    # Even numbers should be divided by 2
    if n % 2 == 0:
        n /= 2
        flag = True
    # Negative odd numbers should return their absolute value
    elif n < 0:
        n = -n
        flag = True
    # Otherwise, number should remain unchanged
    else:
        pass

Of course, in this case, one would probably use return instead of assignment, but in cases where mutation is desired, this works best.

The use of pass here is especially useful to warn future maintainers (including yourself!) not to put redundant steps outside of the conditional statements. In the example above, flag is set in the two specifically mentioned cases, but not in the else-case. Without using pass, a future programmer might move flag = True to outside the condition—thus setting flag in all cases.


Another case is with the boilerplate function often seen at the bottom of a file:

if __name__ == "__main__":
    pass

In some files, it might be nice to leave that there with pass to allow for easier editing later, and to make explicit that nothing is expected to happen when the file is run on its own.


Finally, as mentioned in other answers, it can be useful to do nothing when an exception is caught:

try:
    n[i] = 0
except IndexError:
    pass

回答 3

最好和最准确的思考pass方式是明确告诉解释器不执行任何操作的方式。以同样的方式执行以下代码:

def foo(x,y):
    return x+y

意思是“如果我调用函数foo(x,y),将标签x和y代表的两个数字相加并返回结果”,

def bar():
    pass

表示“如果我调用函数bar(),则绝对不执行任何操作。”

其他答案非常正确,但是对于一些不涉及占位的事情也很有用。

例如,在我最近使用的一些代码中,有必要将两个变量相除,并且除数可能为零。

c = a / b

如果b为零,显然会产生ZeroDivisionError。在这种特殊情况下,在b为零的情况下,将c保留为零是理想的行为,因此我使用以下代码:

try:
    c = a / b
except ZeroDivisionError:
    pass

另一个较少使用的标准用法是为调试器放置断点的方便位置。例如,我想在for … in语句的第20次迭代中将一些代码插入调试器。所以:

for t in range(25):
    do_a_thing(t)
    if t == 20:
        pass

断点通过。

The best and most accurate way to think of pass is as a way to explicitly tell the interpreter to do nothing. In the same way the following code:

def foo(x,y):
    return x+y

means “if I call the function foo(x, y), sum the two numbers the labels x and y represent and hand back the result”,

def bar():
    pass

means “If I call the function bar(), do absolutely nothing.”

The other answers are quite correct, but it’s also useful for a few things that don’t involve place-holding.

For example, in a bit of code I worked on just recently, it was necessary to divide two variables, and it was possible for the divisor to be zero.

c = a / b

will, obviously, produce a ZeroDivisionError if b is zero. In this particular situation, leaving c as zero was the desired behavior in the case that b was zero, so I used the following code:

try:
    c = a / b
except ZeroDivisionError:
    pass

Another, less standard usage is as a handy place to put a breakpoint for your debugger. For example, I wanted a bit of code to break into the debugger on the 20th iteration of a for… in statement. So:

for t in range(25):
    do_a_thing(t)
    if t == 20:
        pass

with the breakpoint on pass.


回答 4

可以“按原样”使用的常见用例是重写类,仅是为了创建类型(否则与超类相同),例如

class Error(Exception):
    pass

因此,您可以引发并捕获Error异常。这里重要的是异常的类型,而不是内容。

A common use case where it can be used ‘as is’ is to override a class just to create a type (which is otherwise the same as the superclass), e.g.

class Error(Exception):
    pass

So you can raise and catch Error exceptions. What matters here is the type of exception, rather than the content.


回答 5

pass在Python中基本上不执行任何操作,但是与注释不同,解释器不会忽略它。因此,可以通过将其设置为占位符来在很多地方利用它:

1:可以在课堂上使用

   class TestClass: 
      pass

2:可以在循环和条件语句中使用:

   if (something == true):  # used in conditional statement
       pass

   while (some condition is true):  # user is not sure about the body of the loop
       pass

3:可用于功能:

   def testFunction(args): # programmer wants to implement the body of the function later
       pass

pass通常在程序员不愿提供实现但仍希望创建某个类/函数/条件语句(以后可以使用)时使用。由于Python解释器不允许空白或未实现的类/函数/条件语句,因此会产生错误:

IndentationError:应缩进的块

pass 可以在这种情况下使用。

pass in Python basically does nothing, but unlike a comment it is not ignored by interpreter. So you can take advantage of it in a lot of places by making it a place holder:

1: Can be used in class

   class TestClass: 
      pass

2: Can be use in loop and conditional statements:

   if (something == true):  # used in conditional statement
       pass

   while (some condition is true):  # user is not sure about the body of the loop
       pass

3: Can be used in function :

   def testFunction(args): # programmer wants to implement the body of the function later
       pass

pass is mostly used when programmer does not want to give implementation at the moment but still wants to create a certain class/function/conditional statement which can be used later on. Since the Python interpreter does not allow for blank or unimplemented class/function/conditional statement it gives an error:

IndentationError: expected an indented block

pass can be used in such scenarios.


回答 6

可以说,通过表示NOP(无操作)操作。在此示例后,您将获得清晰的图片:

C程序

#include<stdio.h>

void main()
{
    int age = 12;

    if( age < 18 )
    {
         printf("You are not adult, so you can't do that task ");
    }
    else if( age >= 18 && age < 60)
    {
        // I will add more code later inside it 
    }
    else
    {
         printf("You are too old to do anything , sorry ");
    }
}

现在,您将如何在Python中编写它:-

age = 12

if age < 18:

    print "You are not adult, so you can't do that task"

elif age >= 18 and age < 60:

else:

    print "You are too old to do anything , sorry "

但是您的代码会出错,因为它需要在elif之后缩进一个块。这是pass关键字的作用。

age = 12

if age < 18:

    print "You are not adult, so you can't do that task"

elif age >= 18 and age < 60:

    pass

else:

    print "You are too old to do anything , sorry "

现在,我认为这很清楚。

You can say that pass means NOP (No Operation) operation. You will get a clear picture after this example :-

C Program

#include<stdio.h>

void main()
{
    int age = 12;

    if( age < 18 )
    {
         printf("You are not adult, so you can't do that task ");
    }
    else if( age >= 18 && age < 60)
    {
        // I will add more code later inside it 
    }
    else
    {
         printf("You are too old to do anything , sorry ");
    }
}

Now how you will write that in Python :-

age = 12

if age < 18:

    print "You are not adult, so you can't do that task"

elif age >= 18 and age < 60:

else:

    print "You are too old to do anything , sorry "

But your code will give error because it required an indented block after elif . Here is the role of pass keyword.

age = 12

if age < 18:

    print "You are not adult, so you can't do that task"

elif age >= 18 and age < 60:

    pass

else:

    print "You are too old to do anything , sorry "

Now I think its clear to you.


回答 7

我喜欢在进行测试时使用它。我经常知道自己想测试什么,但不太了解该怎么做。测试示例看起来像sebastian_oe所建议的

class TestFunctions(unittest.TestCase):

   def test_some_feature(self):
      pass

   def test_some_other_feature(self):
      pass

I like to use it when stubbing out tests. I often times am aware of what i would like to test but don’t quite know how to do it. Testing example looks like what sebastian_oe suggested

class TestFunctions(unittest.TestCase):

   def test_some_feature(self):
      pass

   def test_some_other_feature(self):
      pass

回答 8

pass语句不执行任何操作。当在语法上需要一条语句但该程序不需要任何操作时,可以使用它。

The pass statement does nothing. It can be used when a statement is required syntactically but the program requires no action.


回答 9

老实说,我认为Python官方文档对此进行了很好的描述并提供了一些示例:

语句什么也不做。当在语法上需要一条语句但该程序不需要任何操作时,可以使用它。例如:

>>> while True: ... pass # Busy-wait for keyboard interrupt (Ctrl+C) ...

这通常用于创建最少的类:

>>> class MyEmptyClass: ... pass ...

当您在处理新代码时,可以使用另一个地方通行证作为函数或条件主体的占位符,从而使您可以继续进行更抽象的思考。该被自动忽略:

>>> def initlog(*args): ... pass # Remember to implement this! ...

Honestly, I think the official Python docs describe it quite well and provide some examples:

The pass statement does nothing. It can be used when a statement is required syntactically but the program requires no action. For example:

>>> while True: ... pass # Busy-wait for keyboard interrupt (Ctrl+C) ...

This is commonly used for creating minimal classes:

>>> class MyEmptyClass: ... pass ...

Another place pass can be used is as a place-holder for a function or conditional body when you are working on new code, allowing you to keep thinking at a more abstract level. The pass is silently ignored:

>>> def initlog(*args): ... pass # Remember to implement this! ...


回答 10

如书中所述,我只曾将其用作临时占位符,即

# code that does something to to a variable, var
if var == 2000:
    pass
else:
    var += 1

然后填写场景 var == 2000

as the book said, I only ever use it as a temporary placeholder, ie,

# code that does something to to a variable, var
if var == 2000:
    pass
else:
    var += 1

and then later fill in the scenario where var == 2000


回答 11

传递是指忽略…。就这么简单….如果给定条件为真,并且下一条语句通过,它将忽略该值或迭代并继续执行下一行…..示例

For i in range (1,100):
    If i%2==0:
                  Pass 
    Else:
                  Print(i)

输出:打印1-100中的所有奇数

这是因为偶数的模数等于零,因此它忽略该数并继续到下一个数字,因为奇数模数不等于零,则执行循环的其他部分并将其打印出来

Pass refers to ignore….as simple as it is ….if the given condition is true and the next statement is pass it ignores that value or iteration and proceed to the next line ….. Example

For i in range (1,100):
    If i%2==0:
                  Pass 
    Else:
                  Print(i)

Output: Prints all the odd numbers from 1-100

This is because modulus of even number is equal to zero ,hence it ignores the number and proceeds to next number ,since odd numbers modulus is not equal to zero the Else part of the loop is executed and its printed


回答 12

这是一个示例,其中我从具有多种数据类型的列表中提取特定数据(这就是我在R中所称的名称,如果命名错误,对不起),我只想提取整数/数字和非字符数据。

数据如下:

>>> a = ['1', 'env', '2', 'gag', '1.234', 'nef']
>>> data = []
>>> type(a)
<class 'list'>
>>> type(a[1])
<class 'str'>
>>> type(a[0])
<class 'str'>

我想删除所有字母字符,所以我让机器通过设置数据子集并“传递”字母数据来做到这一点:

a = ['1', 'env', '2', 'gag', '1.234', 'nef']
data = []
for i in range(0, len(a)):
    if a[i].isalpha():
        pass
    else:
        data.append(a[i])
print(data)
['1', '2', '1.234']

Here’s an example where I was extracting particular data from a list where I had multiple data types (that’s what I’d call it in R– sorry if it’s the wrong nomenclature) and I wanted to extract only integers/numeric and NOT character data.

The data looked like:

>>> a = ['1', 'env', '2', 'gag', '1.234', 'nef']
>>> data = []
>>> type(a)
<class 'list'>
>>> type(a[1])
<class 'str'>
>>> type(a[0])
<class 'str'>

I wanted to remove all alphabetical characters, so I had the machine do it by subsetting the data, and “passing” over the alphabetical data:

a = ['1', 'env', '2', 'gag', '1.234', 'nef']
data = []
for i in range(0, len(a)):
    if a[i].isalpha():
        pass
    else:
        data.append(a[i])
print(data)
['1', '2', '1.234']

回答 13

在语法上需要语句但您不希望执行任何命令或代码时,使用Python中的pass语句。

pass语句是一个空操作;执行时没有任何反应。在您的代码最终可以使用但尚未编写的地方(例如,在存根中),该传递也是有用的:

`示例:

#!/usr/bin/python

for letter in 'Python': 
   if letter == 'h':
      pass
      print 'This is pass block'
   print 'Current Letter :', letter

print "Good bye!"

这将产生以下结果:

Current Letter : P
Current Letter : y
Current Letter : t
This is pass block
Current Letter : h
Current Letter : o
Current Letter : n
Good bye!

如果字母的值为“ h”,则前面的代码不执行任何语句或代码。当您创建了代码块后,pass语句很有用,但不再需要。

然后,您可以删除该块内的语句,但让该块与pass语句一起保留,以免干扰代码的其他部分。

The pass statement in Python is used when a statement is required syntactically but you do not want any command or code to execute.

The pass statement is a null operation; nothing happens when it executes. The pass is also useful in places where your code will eventually go, but has not been written yet (e.g., in stubs for example):

`Example:

#!/usr/bin/python

for letter in 'Python': 
   if letter == 'h':
      pass
      print 'This is pass block'
   print 'Current Letter :', letter

print "Good bye!"

This will produce following result:

Current Letter : P
Current Letter : y
Current Letter : t
This is pass block
Current Letter : h
Current Letter : o
Current Letter : n
Good bye!

The preceding code does not execute any statement or code if the value of letter is ‘h’. The pass statement is helpful when you have created a code block but it is no longer required.

You can then remove the statements inside the block but let the block remain with a pass statement so that it doesn’t interfere with other parts of the code.


回答 14

pass用于避免python中的缩进错误如果我们采用c,c ++,java之类的语言,则它们具有大括号,例如

 if(i==0)
 {}
 else
 {//some code}

但是在python中,它使用缩进而不是花括号,因此为了避免此类错误,我们使用pass。在玩测验时记得

 if(dont_know_the_answer)
      pass

示例程序

  for letter in 'geeksforgeeks':
        pass
  print 'Last Letter :', letter

pass is used to avoid indentation error in python If we take languages like c,c++,java they have braces like

 if(i==0)
 {}
 else
 {//some code}

But in python it used indentation instead of braces so to avoid such errors we use pass. Remembered as you were playing a quiz and

 if(dont_know_the_answer)
      pass

Example program,

  for letter in 'geeksforgeeks':
        pass
  print 'Last Letter :', letter

如何使用datetime Python模块计算从当前日期起六个月的日期?

问题:如何使用datetime Python模块计算从当前日期起六个月的日期?

我正在使用datetime Python模块。我想计算从当前日期起6个月的日期。有人可以给我一点帮助吗?

我要从当前日期起6个月生成日期的原因是要产生一个审阅日期。如果用户将数据输入到系统中,则其输入日期为6个月。

I am using the datetime Python module. I am looking to calculate the date 6 months from the current date. Could someone give me a little help doing this?

The reason I want to generate a date 6 months from the current date is to produce a review date. If the user enters data into the system it will have a review date of 6 months from the date they entered the data.


回答 0

我发现此解决方案很好。(这使用python-dateutil扩展名

from datetime import date
from dateutil.relativedelta import relativedelta

six_months = date.today() + relativedelta(months=+6)

这种方法的优点是可以处理28、30、31天等问题。这在处理业务规则和业务情景(例如生成发票等)时非常有用。

$ date(2010,12,31)+relativedelta(months=+1)
  datetime.date(2011, 1, 31)

$ date(2010,12,31)+relativedelta(months=+2)
  datetime.date(2011, 2, 28)

I found this solution to be good. (This uses the python-dateutil extension)

from datetime import date
from dateutil.relativedelta import relativedelta

six_months = date.today() + relativedelta(months=+6)

The advantage of this approach is that it takes care of issues with 28, 30, 31 days etc. This becomes very useful in handling business rules and scenarios (say invoice generation etc.)

$ date(2010,12,31)+relativedelta(months=+1)
  datetime.date(2011, 1, 31)

$ date(2010,12,31)+relativedelta(months=+2)
  datetime.date(2011, 2, 28)

回答 1

好吧,这取决于您从当前日期算起的6个月的意思。

  1. 使用自然月份:

    (day, month, year) = (day, (month + 5) % 12 + 1, year + (month + 5)/12)
  2. 使用银行家的定义6 * 30:

    date += datetime.timedelta(6 * 30)

Well, that depends what you mean by 6 months from the current date.

  1. Using natural months:

    (day, month, year) = (day, (month + 5) % 12 + 1, year + (month + 5)/12)
    
  2. Using a banker’s definition, 6*30:

    date += datetime.timedelta(6 * 30)
    

回答 2

使用Python 3.x,您可以这样做:

from datetime import datetime, timedelta
from dateutil.relativedelta import *

date = datetime.now()
print(date)
# 2018-09-24 13:24:04.007620

date = date + relativedelta(months=+6)
print(date)
# 2019-03-24 13:24:04.007620

但您将需要安装python-dateutil模块:

pip install python-dateutil

With Python 3.x you can do it like this:

from datetime import datetime, timedelta
from dateutil.relativedelta import *

date = datetime.now()
print(date)
# 2018-09-24 13:24:04.007620

date = date + relativedelta(months=+6)
print(date)
# 2019-03-24 13:24:04.007620

but you will need to install python-dateutil module:

pip install python-dateutil

回答 3

对于月初的计算:

from datetime import timedelta
from dateutil.relativedelta import relativedelta

end_date = start_date + relativedelta(months=delta_period) + timedelta(days=-delta_period)

For beginning of month to month calculation:

from datetime import timedelta
from dateutil.relativedelta import relativedelta

end_date = start_date + relativedelta(months=delta_period) + timedelta(days=-delta_period)

回答 4

“ 6个月”是什么意思?

是2009-02-13 + 6个月== 2009-08-13吗?还是2009-02-13 + 6 * 30天?

import mx.DateTime as dt

#6 Months
dt.now()+dt.RelativeDateTime(months=6)
#result is '2009-08-13 16:28:00.84'

#6*30 days
dt.now()+dt.RelativeDateTime(days=30*6)
#result is '2009-08-12 16:30:03.35'

有关mx.DateTime的更多信息

What do you mean by “6 months”?

Is 2009-02-13 + 6 months == 2009-08-13? Or is it 2009-02-13 + 6*30 days?

import mx.DateTime as dt

#6 Months
dt.now()+dt.RelativeDateTime(months=6)
#result is '2009-08-13 16:28:00.84'

#6*30 days
dt.now()+dt.RelativeDateTime(days=30*6)
#result is '2009-08-12 16:30:03.35'

More info about mx.DateTime


回答 5

因此,这是一个示例dateutil.relativedelta,我发现该示例可用于遍历过去的一年,每次都跳过一个月到当前日期:

>>> import datetime
>>> from dateutil.relativedelta import relativedelta
>>> today = datetime.datetime.today()
>>> month_count = 0
>>> while month_count < 12:
...  day = today - relativedelta(months=month_count)
...  print day
...  month_count += 1
... 
2010-07-07 10:51:45.187968
2010-06-07 10:51:45.187968
2010-05-07 10:51:45.187968
2010-04-07 10:51:45.187968
2010-03-07 10:51:45.187968
2010-02-07 10:51:45.187968
2010-01-07 10:51:45.187968
2009-12-07 10:51:45.187968
2009-11-07 10:51:45.187968
2009-10-07 10:51:45.187968
2009-09-07 10:51:45.187968
2009-08-07 10:51:45.187968

与其他答案一样,您必须弄清楚“从现在起6个月后”的实际含义。如果您的意思是“未来六年的每月的当日”,则可以这样做:

datetime.datetime.now() + relativedelta(months=6)

So, here is an example of the dateutil.relativedelta which I found useful for iterating through the past year, skipping a month each time to the present date:

>>> import datetime
>>> from dateutil.relativedelta import relativedelta
>>> today = datetime.datetime.today()
>>> month_count = 0
>>> while month_count < 12:
...  day = today - relativedelta(months=month_count)
...  print day
...  month_count += 1
... 
2010-07-07 10:51:45.187968
2010-06-07 10:51:45.187968
2010-05-07 10:51:45.187968
2010-04-07 10:51:45.187968
2010-03-07 10:51:45.187968
2010-02-07 10:51:45.187968
2010-01-07 10:51:45.187968
2009-12-07 10:51:45.187968
2009-11-07 10:51:45.187968
2009-10-07 10:51:45.187968
2009-09-07 10:51:45.187968
2009-08-07 10:51:45.187968

As with the other answers, you have to figure out what you actually mean by “6 months from now.” If you mean “today’s day of the month in the month six years in the future” then this would do:

datetime.datetime.now() + relativedelta(months=6)

回答 6

此解决方案在12月正确运行,而此页面上的大多数答案都无效。在使用模数(%)或整数除法(//)之前,您需要首先将月份从基数1(即Jan = 1)转换为基数0(即Jan = 0),否则11月(11)加1个月为您提供12 ,当找到余数(12%12)时得到0。

(也不要建议“((月%12)+ 1”或10月+1 = 12月!)

def AddMonths(d,x):
    newmonth = ((( d.month - 1) + x ) % 12 ) + 1
    newyear  = int(d.year + ((( d.month - 1) + x ) / 12 ))
    return datetime.date( newyear, newmonth, d.day)

但是…这不能解决1月31日+一个月之类的问题。因此,我们回到OP-您增加一个月意味着什么?一种解决方案是回溯到有效的一天,因为大多数人会假设jan的最后一天加上一个月等于2月的最后一天。这也适用于负数个月。证明:

>>> import datetime
>>> AddMonths(datetime.datetime(2010,8,25),1)
datetime.date(2010, 9, 25)
>>> AddMonths(datetime.datetime(2010,8,25),4)
datetime.date(2010, 12, 25)
>>> AddMonths(datetime.datetime(2010,8,25),5)
datetime.date(2011, 1, 25)
>>> AddMonths(datetime.datetime(2010,8,25),13)
datetime.date(2011, 9, 25)
>>> AddMonths(datetime.datetime(2010,8,25),24)
datetime.date(2012, 8, 25)
>>> AddMonths(datetime.datetime(2010,8,25),-1)
datetime.date(2010, 7, 25)
>>> AddMonths(datetime.datetime(2010,8,25),0)
datetime.date(2010, 8, 25)
>>> AddMonths(datetime.datetime(2010,8,25),-12)
datetime.date(2009, 8, 25)
>>> AddMonths(datetime.datetime(2010,8,25),-8)
datetime.date(2009, 12, 25)
>>> AddMonths(datetime.datetime(2010,8,25),-7)
datetime.date(2010, 1, 25)>>> 

This solution works correctly for December, which most of the answers on this page do not. You need to first shift the months from base 1 (ie Jan = 1) to base 0 (ie Jan = 0) before using modulus ( % ) or integer division ( // ), otherwise November (11) plus 1 month gives you 12, which when finding the remainder ( 12 % 12 ) gives 0.

(And dont suggest “(month % 12) + 1” or Oct + 1 = december!)

def AddMonths(d,x):
    newmonth = ((( d.month - 1) + x ) % 12 ) + 1
    newyear  = int(d.year + ((( d.month - 1) + x ) / 12 ))
    return datetime.date( newyear, newmonth, d.day)

However … This doesnt account for problem like Jan 31 + one month. So we go back to the OP – what do you mean by adding a month? One solution is to backtrack until you get to a valid day, given that most people would presume the last day of jan, plus one month, equals the last day of Feb. This will work on negative numbers of months too. Proof:

>>> import datetime
>>> AddMonths(datetime.datetime(2010,8,25),1)
datetime.date(2010, 9, 25)
>>> AddMonths(datetime.datetime(2010,8,25),4)
datetime.date(2010, 12, 25)
>>> AddMonths(datetime.datetime(2010,8,25),5)
datetime.date(2011, 1, 25)
>>> AddMonths(datetime.datetime(2010,8,25),13)
datetime.date(2011, 9, 25)
>>> AddMonths(datetime.datetime(2010,8,25),24)
datetime.date(2012, 8, 25)
>>> AddMonths(datetime.datetime(2010,8,25),-1)
datetime.date(2010, 7, 25)
>>> AddMonths(datetime.datetime(2010,8,25),0)
datetime.date(2010, 8, 25)
>>> AddMonths(datetime.datetime(2010,8,25),-12)
datetime.date(2009, 8, 25)
>>> AddMonths(datetime.datetime(2010,8,25),-8)
datetime.date(2009, 12, 25)
>>> AddMonths(datetime.datetime(2010,8,25),-7)
datetime.date(2010, 1, 25)>>> 

回答 7

我知道这是6个月,但是如果您要添加一个月,答案就会在Google中显示为“在python中添加月份”:

import calendar

date = datetime.date.today()    //Or your date

datetime.timedelta(days=calendar.monthrange(date.year,date.month)[1])

这将计算当月的天数并将其添加到当前日期,使用365/12表示一年的1/12会导致短/长月份的问题(如果您对该日期进行迭代)。

I know this was for 6 months, however the answer shows in google for “adding months in python” if you are adding one month:

import calendar

date = datetime.date.today()    //Or your date

datetime.timedelta(days=calendar.monthrange(date.year,date.month)[1])

this would count the days in the current month and add them to the current date, using 365/12 would ad 1/12 of a year can causes issues for short / long months if your iterating over the date.


回答 8

没有直接的方法可以使用Python的日期时间。

python-dateutil处检查relativedelta类型。它允许您指定以月为单位的时间增量。

There’s no direct way to do it with Python’s datetime.

Check out the relativedelta type at python-dateutil. It allows you to specify a time delta in months.


回答 9

只需使用timetuple方法提取月份,添加月份并构建一个新的dateobject。如果有一个已经存在的方法,我不知道。

import datetime

def in_the_future(months=1):
    year, month, day = datetime.date.today().timetuple()[:3]
    new_month = month + months
    return datetime.date(year + (new_month / 12), (new_month % 12) or 12, day)

该API有点笨拙,但仅作为示例。显然也不适用于2008-01-31 + 1个月等极端情况。:)

Just use the timetuple method to extract the months, add your months and build a new dateobject. If there is a already existing method for this I do not know it.

import datetime

def in_the_future(months=1):
    year, month, day = datetime.date.today().timetuple()[:3]
    new_month = month + months
    return datetime.date(year + (new_month / 12), (new_month % 12) or 12, day)

The API is a bit clumsy, but works as an example. Will also obviously not work on corner-cases like 2008-01-31 + 1 month. :)


回答 10

Dateutil软件包具有此类功能的实现。但是请注意,正如其他人已经指出的那样,这将是幼稚的

Dateutil package has implementation of such functionality. But be aware, that this will be naive, as others pointed already.


回答 11

使用Python标准库(即不使用dateutil或不使用其他库)并解决“ 2月31日”问题:

import datetime
import calendar

def add_months(date, months):
    months_count = date.month + months

    # Calculate the year
    year = date.year + int(months_count / 12)

    # Calculate the month
    month = (months_count % 12)
    if month == 0:
        month = 12

    # Calculate the day
    day = date.day
    last_day_of_month = calendar.monthrange(year, month)[1]
    if day > last_day_of_month:
        day = last_day_of_month

    new_date = datetime.date(year, month, day)
    return new_date

测试:

>>>date = datetime.date(2018, 11, 30)

>>>print(date, add_months(date, 3))
(datetime.date(2018, 11, 30), datetime.date(2019, 2, 28))

>>>print(date, add_months(date, 14))
(datetime.date(2018, 12, 31), datetime.date(2020, 2, 29))

Using Python standard libraries, i.e. without dateutil or others, and solving the ‘February 31st’ problem:

import datetime
import calendar

def add_months(date, months):
    months_count = date.month + months

    # Calculate the year
    year = date.year + int(months_count / 12)

    # Calculate the month
    month = (months_count % 12)
    if month == 0:
        month = 12

    # Calculate the day
    day = date.day
    last_day_of_month = calendar.monthrange(year, month)[1]
    if day > last_day_of_month:
        day = last_day_of_month

    new_date = datetime.date(year, month, day)
    return new_date

Testing:

>>>date = datetime.date(2018, 11, 30)

>>>print(date, add_months(date, 3))
(datetime.date(2018, 11, 30), datetime.date(2019, 2, 28))

>>>print(date, add_months(date, 14))
(datetime.date(2018, 12, 31), datetime.date(2020, 2, 29))

回答 12

我有一个更好的方法来解决“ 2月31日”问题:

def add_months(start_date, months):
    import calendar

    year = start_date.year + (months / 12)
    month = start_date.month + (months % 12)
    day = start_date.day

    if month > 12:
        month = month % 12
        year = year + 1

    days_next = calendar.monthrange(year, month)[1]
    if day > days_next:
        day = days_next

    return start_date.replace(year, month, day)

我认为它也可以使用负数(减去数月),但是我还没有对此进行太多测试。

I have a better way to solve the ‘February 31st’ problem:

def add_months(start_date, months):
    import calendar

    year = start_date.year + (months / 12)
    month = start_date.month + (months % 12)
    day = start_date.day

    if month > 12:
        month = month % 12
        year = year + 1

    days_next = calendar.monthrange(year, month)[1]
    if day > days_next:
        day = days_next

    return start_date.replace(year, month, day)

I think that it also works with negative numbers (to subtract months), but I haven’t tested this very much.


回答 13

PyQt4的QDate类具有addmonths函数。

>>>from PyQt4.QtCore import QDate  
>>>dt = QDate(2009,12,31)  
>>>required = dt.addMonths(6) 

>>>required
PyQt4.QtCore.QDate(2010, 6, 30)

>>>required.toPyDate()
datetime.date(2010, 6, 30)

The QDate class of PyQt4 has an addmonths function.

>>>from PyQt4.QtCore import QDate  
>>>dt = QDate(2009,12,31)  
>>>required = dt.addMonths(6) 

>>>required
PyQt4.QtCore.QDate(2010, 6, 30)

>>>required.toPyDate()
datetime.date(2010, 6, 30)

回答 14

这个怎么样?不使用其他库(dateutil)或timedelta?在vartec的答案的基础上,我做到了,并且我相信它是有效的:

import datetime

today = datetime.date.today()
six_months_from_today = datetime.date(today.year + (today.month + 6)/12, (today.month + 6) % 12, today.day)

我尝试使用timedelta,但是因为它是在计算天数,365/2或者6*356/12并不总是转换为6个月,而是182天。例如

day = datetime.date(2015, 3, 10)
print day
>>> 2015-03-10

print (day + datetime.timedelta(6*365/12))
>>> 2015-09-08

我相信我们通常会假设从某天起的6个月会在该月的同一天,但会在6个月后(即2015-03-10-> 2015-09-10,不是2015-09-08

我希望你觉得这有帮助。

How about this? Not using another library (dateutil) or timedelta? building on vartec‘s answer I did this and I believe it works:

import datetime

today = datetime.date.today()
six_months_from_today = datetime.date(today.year + (today.month + 6)/12, (today.month + 6) % 12, today.day)

I tried using timedelta, but because it is counting the days, 365/2 or 6*356/12 does not always translate to 6 months, but rather 182 days. e.g.

day = datetime.date(2015, 3, 10)
print day
>>> 2015-03-10

print (day + datetime.timedelta(6*365/12))
>>> 2015-09-08

I believe that we usually assume that 6 month’s from a certain day will land on the same day of the month but 6 months later (i.e. 2015-03-10 –> 2015-09-10, Not 2015-09-08)

I hope you find this helpful.


回答 15

这不能回答特定的问题(datetime仅使用),但是,鉴于其他人建议使用不同的模块,此处提供了一个解决方案using pandas

import datetime as dt
import pandas as pd

date = dt.date.today() - \
       pd.offsets.DateOffset(months=6)

print(date)

2019-05-04 00:00:00

在leap年中可以正常工作

date = dt.datetime(2019,8,29) - \
       pd.offsets.DateOffset(months=6)
print(date)

2019-02-28 00:00:00

This doesn’t answer the specific question (using datetime only) but, given that others suggested the use of different modules, here there is a solution using pandas.

import datetime as dt
import pandas as pd

date = dt.date.today() - \
       pd.offsets.DateOffset(months=6)

print(date)

2019-05-04 00:00:00

Which works as expected in leap years

date = dt.datetime(2019,8,29) - \
       pd.offsets.DateOffset(months=6)
print(date)

2019-02-28 00:00:00

回答 16

修改了AddMonths()以在Zope中使用并处理无效的天数:

def AddMonths(d,x):
    days_of_month = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
    newmonth = ((( d.month() - 1) + x ) % 12 ) + 1
    newyear  = d.year() + ((( d.month() - 1) + x ) // 12 ) 
    if d.day() > days_of_month[newmonth-1]:
      newday = days_of_month[newmonth-1]
    else:
      newday = d.day() 
    return DateTime( newyear, newmonth, newday)

Modified the AddMonths() for use in Zope and handling invalid day numbers:

def AddMonths(d,x):
    days_of_month = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
    newmonth = ((( d.month() - 1) + x ) % 12 ) + 1
    newyear  = d.year() + ((( d.month() - 1) + x ) // 12 ) 
    if d.day() > days_of_month[newmonth-1]:
      newday = days_of_month[newmonth-1]
    else:
      newday = d.day() 
    return DateTime( newyear, newmonth, newday)

回答 17

import time

def add_month(start_time, months):  

        ret = time.strptime(start_time, '%Y-%m-%d')
        t = list(ret)

        t[1] += months

        if t[1] > 12:
            t[0] += 1 + int(months / 12)

            t[1] %= 12

        return int(time.mktime(tuple(t)))
import time

def add_month(start_time, months):  

        ret = time.strptime(start_time, '%Y-%m-%d')
        t = list(ret)

        t[1] += months

        if t[1] > 12:
            t[0] += 1 + int(months / 12)

            t[1] %= 12

        return int(time.mktime(tuple(t)))

回答 18

import datetime


'''
Created on 2011-03-09

@author: tonydiep
'''

def add_business_months(start_date, months_to_add):
    """
    Add months in the way business people think of months. 
    Jan 31, 2011 + 1 month = Feb 28, 2011 to business people
    Method: Add the number of months, roll back the date until it becomes a valid date
    """
    # determine year
    years_change = months_to_add / 12

    # determine if there is carryover from adding months
    if (start_date.month + (months_to_add % 12) > 12 ):
        years_change = years_change + 1

    new_year = start_date.year + years_change

    # determine month
    work = months_to_add % 12
    if 0 == work:
        new_month = start_date.month
    else:
        new_month = (start_date.month + (work % 12)) % 12

    if 0 == new_month:
        new_month = 12 

    # determine day of the month
    new_day = start_date.day
    if(new_day in [31, 30, 29, 28]):
        #user means end of the month
        new_day = 31


    new_date = None
    while (None == new_date and 27 < new_day):
        try:
            new_date = start_date.replace(year=new_year, month=new_month, day=new_day)
        except:
            new_day = new_day - 1   #wind down until we get to a valid date

    return new_date


if __name__ == '__main__':
    #tests
    dates = [datetime.date(2011, 1, 31),
             datetime.date(2011, 2, 28),
             datetime.date(2011, 3, 28),
             datetime.date(2011, 4, 28),
             datetime.date(2011, 5, 28),
             datetime.date(2011, 6, 28),
             datetime.date(2011, 7, 28),
             datetime.date(2011, 8, 28),
             datetime.date(2011, 9, 28),
             datetime.date(2011, 10, 28),
             datetime.date(2011, 11, 28),
             datetime.date(2011, 12, 28),
             ]
    months = range(1, 24)
    for start_date in dates:
        for m in months:
            end_date = add_business_months(start_date, m)
            print("%s\t%s\t%s" %(start_date, end_date, m))
import datetime


'''
Created on 2011-03-09

@author: tonydiep
'''

def add_business_months(start_date, months_to_add):
    """
    Add months in the way business people think of months. 
    Jan 31, 2011 + 1 month = Feb 28, 2011 to business people
    Method: Add the number of months, roll back the date until it becomes a valid date
    """
    # determine year
    years_change = months_to_add / 12

    # determine if there is carryover from adding months
    if (start_date.month + (months_to_add % 12) > 12 ):
        years_change = years_change + 1

    new_year = start_date.year + years_change

    # determine month
    work = months_to_add % 12
    if 0 == work:
        new_month = start_date.month
    else:
        new_month = (start_date.month + (work % 12)) % 12

    if 0 == new_month:
        new_month = 12 

    # determine day of the month
    new_day = start_date.day
    if(new_day in [31, 30, 29, 28]):
        #user means end of the month
        new_day = 31


    new_date = None
    while (None == new_date and 27 < new_day):
        try:
            new_date = start_date.replace(year=new_year, month=new_month, day=new_day)
        except:
            new_day = new_day - 1   #wind down until we get to a valid date

    return new_date


if __name__ == '__main__':
    #tests
    dates = [datetime.date(2011, 1, 31),
             datetime.date(2011, 2, 28),
             datetime.date(2011, 3, 28),
             datetime.date(2011, 4, 28),
             datetime.date(2011, 5, 28),
             datetime.date(2011, 6, 28),
             datetime.date(2011, 7, 28),
             datetime.date(2011, 8, 28),
             datetime.date(2011, 9, 28),
             datetime.date(2011, 10, 28),
             datetime.date(2011, 11, 28),
             datetime.date(2011, 12, 28),
             ]
    months = range(1, 24)
    for start_date in dates:
        for m in months:
            end_date = add_business_months(start_date, m)
            print("%s\t%s\t%s" %(start_date, end_date, m))

回答 19

在1new_month = 121的情况下修改了Johannes Wei的答案。这对我来说非常有效。月份可以是正数或负数。

def addMonth(d,months=1):
    year, month, day = d.timetuple()[:3]
    new_month = month + months
    return datetime.date(year + ((new_month-1) / 12), (new_month-1) % 12 +1, day)

Modified Johannes Wei’s answer in the case 1new_month = 121. This works perfectly for me. The months could be positive or negative.

def addMonth(d,months=1):
    year, month, day = d.timetuple()[:3]
    new_month = month + months
    return datetime.date(year + ((new_month-1) / 12), (new_month-1) % 12 +1, day)

回答 20

另一个解决方案-希望有人会喜欢它:

def add_months(d, months):
    return d.replace(year=d.year+months//12).replace(month=(d.month+months)%12)

此解决方案在所有情况下都无法正常工作29,30,31天,因此需要更强大的解决方案(现在不再那么好了:)):

def add_months(d, months):
    for i in range(4):
        day = d.day - i
        try:
            return d.replace(day=day).replace(year=d.year+int(months)//12).replace(month=(d.month+int(months))%12)
        except:
            pass
    raise Exception("should not happen")

Yet another solution – hope someone will like it:

def add_months(d, months):
    return d.replace(year=d.year+months//12).replace(month=(d.month+months)%12)

This solution doesn’t work for days 29,30,31 for all cases, so more robust solution is needed (which is not so nice anymore :) ):

def add_months(d, months):
    for i in range(4):
        day = d.day - i
        try:
            return d.replace(day=day).replace(year=d.year+int(months)//12).replace(month=(d.month+int(months))%12)
        except:
            pass
    raise Exception("should not happen")

回答 21

这个答案,看到parsedatetime。代码示例如下。更多详细信息:单元测试包含许多自然语言-> YYYY-MM-DD转换示例,以及明显的parsedatetime转换挑战/错误

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import time, calendar
from datetime import date

# from https://github.com/bear/parsedatetime
import parsedatetime as pdt

def print_todays_date():
    todays_day_of_week = calendar.day_name[date.today().weekday()]
    print "today's date = " + todays_day_of_week + ', ' + \
                              time.strftime('%Y-%m-%d')

def convert_date(natural_language_date):
    cal = pdt.Calendar()
    (struct_time_date, success) = cal.parse(natural_language_date)
    if success:
        formal_date = time.strftime('%Y-%m-%d', struct_time_date)
    else:
        formal_date = '(conversion failed)'
    print '{0:12s} -> {1:10s}'.format(natural_language_date, formal_date)

print_todays_date()
convert_date('6 months')

上面的代码从MacOSX计算机生成以下代码:

$ ./parsedatetime_simple.py 
today's date = Wednesday, 2015-05-13
6 months     -> 2015-11-13
$ 

From this answer, see parsedatetime. Code example follows. More details: unit test with many natural-language -> YYYY-MM-DD conversion examples, and apparent parsedatetime conversion challenges/bugs.

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import time, calendar
from datetime import date

# from https://github.com/bear/parsedatetime
import parsedatetime as pdt

def print_todays_date():
    todays_day_of_week = calendar.day_name[date.today().weekday()]
    print "today's date = " + todays_day_of_week + ', ' + \
                              time.strftime('%Y-%m-%d')

def convert_date(natural_language_date):
    cal = pdt.Calendar()
    (struct_time_date, success) = cal.parse(natural_language_date)
    if success:
        formal_date = time.strftime('%Y-%m-%d', struct_time_date)
    else:
        formal_date = '(conversion failed)'
    print '{0:12s} -> {1:10s}'.format(natural_language_date, formal_date)

print_todays_date()
convert_date('6 months')

The above code generates the following from a MacOSX machine:

$ ./parsedatetime_simple.py 
today's date = Wednesday, 2015-05-13
6 months     -> 2015-11-13
$ 

回答 22

这是一个示例,它使用户可以决定如何返回日期大于月份中天数的日期。

def add_months(date, months, endOfMonthBehaviour='RoundUp'):
    assert endOfMonthBehaviour in ['RoundDown', 'RoundIn', 'RoundOut', 'RoundUp'], \
        'Unknown end of month behaviour'
    year = date.year + (date.month + months - 1) / 12
    month = (date.month + months - 1) % 12 + 1
    day = date.day
    last = monthrange(year, month)[1]
    if day > last:
        if endOfMonthBehaviour == 'RoundDown' or \
            endOfMonthBehaviour == 'RoundOut' and months < 0 or \
            endOfMonthBehaviour == 'RoundIn' and months > 0:
            day = last
        elif endOfMonthBehaviour == 'RoundUp' or \
            endOfMonthBehaviour == 'RoundOut' and months > 0 or \
            endOfMonthBehaviour == 'RoundIn' and months < 0:
            # we don't need to worry about incrementing the year
            # because there will never be a day in December > 31
            month += 1
            day = 1
    return datetime.date(year, month, day)


>>> from calendar import monthrange
>>> import datetime
>>> add_months(datetime.datetime(2016, 1, 31), 1)
datetime.date(2016, 3, 1)
>>> add_months(datetime.datetime(2016, 1, 31), -2)
datetime.date(2015, 12, 1)
>>> add_months(datetime.datetime(2016, 1, 31), -2, 'RoundDown')
datetime.date(2015, 11, 30)

Here’s a example which allows the user to decide how to return a date where the day is greater than the number of days in the month.

def add_months(date, months, endOfMonthBehaviour='RoundUp'):
    assert endOfMonthBehaviour in ['RoundDown', 'RoundIn', 'RoundOut', 'RoundUp'], \
        'Unknown end of month behaviour'
    year = date.year + (date.month + months - 1) / 12
    month = (date.month + months - 1) % 12 + 1
    day = date.day
    last = monthrange(year, month)[1]
    if day > last:
        if endOfMonthBehaviour == 'RoundDown' or \
            endOfMonthBehaviour == 'RoundOut' and months < 0 or \
            endOfMonthBehaviour == 'RoundIn' and months > 0:
            day = last
        elif endOfMonthBehaviour == 'RoundUp' or \
            endOfMonthBehaviour == 'RoundOut' and months > 0 or \
            endOfMonthBehaviour == 'RoundIn' and months < 0:
            # we don't need to worry about incrementing the year
            # because there will never be a day in December > 31
            month += 1
            day = 1
    return datetime.date(year, month, day)


>>> from calendar import monthrange
>>> import datetime
>>> add_months(datetime.datetime(2016, 1, 31), 1)
datetime.date(2016, 3, 1)
>>> add_months(datetime.datetime(2016, 1, 31), -2)
datetime.date(2015, 12, 1)
>>> add_months(datetime.datetime(2016, 1, 31), -2, 'RoundDown')
datetime.date(2015, 11, 30)

回答 23

假设您的datetime变量称为date:

date=datetime.datetime(year=date.year+int((date.month+6)/12),
                       month=(date.month+6)%13 + (1 if (date.month + 
                       months>12) else 0), day=date.day)

given that your datetime variable is called date:

date=datetime.datetime(year=date.year+int((date.month+6)/12),
                       month=(date.month+6)%13 + (1 if (date.month + 
                       months>12) else 0), day=date.day)

回答 24

获取x个月之后/之前的下一个日期的常规功能。

从日期时间导入日期

def after_month(给定日期,月份):
    yyyy = int((((给定日期。年* 12 +给定日期。月)+月)/ 12)
    mm = int((((给定日期。年* 12 +给定日期。月)+月)%12)

    如果mm == 0:
        yyyy-= 1
        毫米= 12
    返回给定的date.replace(年= yyyy,月= mm)


如果__name__ ==“ __main__”:
    今天= date.today()
    打印(今天)

    对于[-12,-1,0,1,2,12,20]中的mm:
        next_date = after_month(今天,毫米)
        打印(下一个日期)

General function to get next date after/before x months.

from datetime import date

def after_month(given_date, month):
    yyyy = int(((given_date.year * 12 + given_date.month) + month)/12)
    mm = int(((given_date.year * 12 + given_date.month) + month)%12)

    if mm == 0:
        yyyy -= 1
        mm = 12
    return given_date.replace(year=yyyy, month=mm)


if __name__ == "__main__":
    today = date.today()
    print(today)

    for mm in [-12, -1, 0, 1, 2, 12, 20 ]:
        next_date = after_month(today, mm)
        print(next_date)

回答 25

一个快速的建议是箭头

点安装箭头

>>> import arrow

>>> arrow.now().date()
datetime.date(2019, 6, 28)
>>> arrow.now().shift(months=6).date()
datetime.date(2019, 12, 28)

A quick suggestion is Arrow

pip install arrow

>>> import arrow

>>> arrow.now().date()
datetime.date(2019, 6, 28)
>>> arrow.now().shift(months=6).date()
datetime.date(2019, 12, 28)

回答 26

使用python datetime模块将六个月的时间增量添加到datetime.today()。

http://docs.python.org/library/datetime.html

当然,你将要解决什么约翰内斯Weiß–提出的问题你6个月意味着什么呢?

Use the python datetime module to add a timedelta of six months to datetime.today() .

http://docs.python.org/library/datetime.html

You will of course have to solve the issue raised by Johannes Weiß– what do you mean by 6 months?


回答 27

这就是我想出的。它可以移动正确的月数和年数,但会忽略天数(这是我当时所需要的)。

import datetime

month_dt = 4
today = datetime.date.today()
y,m = today.year, today.month
m += month_dt-1
year_dt = m//12
new_month = m%12
new_date = datetime.date(y+year_dt, new_month+1, 1)

This is what I came up with. It moves the correct number of months and years but ignores days (which was what I needed in my situation).

import datetime

month_dt = 4
today = datetime.date.today()
y,m = today.year, today.month
m += month_dt-1
year_dt = m//12
new_month = m%12
new_date = datetime.date(y+year_dt, new_month+1, 1)

回答 28

我使用此功能更改年份和月份,但保留日期:

def replace_month_year(date1, year2, month2):
    try:
        date2 = date1.replace(month = month2, year = year2)
    except:
        date2 = datetime.date(year2, month2 + 1, 1) - datetime.timedelta(days=1)
    return date2

您应该写:

new_year = my_date.year + (my_date.month + 6) / 12
new_month = (my_date.month + 6) % 12
new_date = replace_month_year(my_date, new_year, new_month)

I use this function to change year and month but keep day:

def replace_month_year(date1, year2, month2):
    try:
        date2 = date1.replace(month = month2, year = year2)
    except:
        date2 = datetime.date(year2, month2 + 1, 1) - datetime.timedelta(days=1)
    return date2

You should write:

new_year = my_date.year + (my_date.month + 6) / 12
new_month = (my_date.month + 6) % 12
new_date = replace_month_year(my_date, new_year, new_month)

回答 29

我认为这样做比手动添加天数更安全:

import datetime
today = datetime.date.today()

def addMonths(dt, months = 0):
    new_month = months + dt.month
    year_inc = 0
    if new_month>12:
        year_inc +=1
        new_month -=12
    return dt.replace(month = new_month, year = dt.year+year_inc)

newdate = addMonths(today, 6)

I think it would be safer to do something like this instead of manually adding days:

import datetime
today = datetime.date.today()

def addMonths(dt, months = 0):
    new_month = months + dt.month
    year_inc = 0
    if new_month>12:
        year_inc +=1
        new_month -=12
    return dt.replace(month = new_month, year = dt.year+year_inc)

newdate = addMonths(today, 6)

“ with”语句中有多个变量?

问题:“ with”语句中有多个变量?

使用withPython中的语句可以声明多个变量吗?

就像是:

from __future__ import with_statement

with open("out.txt","wt"), open("in.txt") as file_out, file_in:
    for line in file_in:
        file_out.write(line)

…还是同时清理两个资源是问题吗?

Is it possible to declare more than one variable using a with statement in Python?

Something like:

from __future__ import with_statement

with open("out.txt","wt"), open("in.txt") as file_out, file_in:
    for line in file_in:
        file_out.write(line)

… or is cleaning up two resources at the same time the problem?


回答 0

从v3.1Python 2.7 开始,Python 3中是可能的。新with语法支持多个上下文管理器:

with A() as a, B() as b, C() as c:
    doSomething(a,b,c)

不同于contextlib.nested,这保证了即使或方法引发异常,ab__exit__()调用C()__enter__()

您也可以在较新的定义中使用较早的变量(以下为h / t Ahmad):

with A() as a, B(a) as b, C(a, b) as c:
    doSomething(a, c)

It is possible in Python 3 since v3.1 and Python 2.7. The new with syntax supports multiple context managers:

with A() as a, B() as b, C() as c:
    doSomething(a,b,c)

Unlike the contextlib.nested, this guarantees that a and b will have their __exit__()‘s called even if C() or it’s __enter__() method raises an exception.

You can also use earlier variables in later definitions (h/t Ahmad below):

with A() as a, B(a) as b, C(a, b) as c:
    doSomething(a, c)

回答 1

contextlib.nested 支持这一点:

import contextlib

with contextlib.nested(open("out.txt","wt"), open("in.txt")) as (file_out, file_in):

   ...

更新:
要引用有关contextlib.nested以下内容的文档:

从2.7版开始不推荐使用:with语句现在直接支持此功能(不存在容易出错的易错问题)。

有关更多信息,请参见RafałDowgird的答案

contextlib.nested supports this:

import contextlib

with contextlib.nested(open("out.txt","wt"), open("in.txt")) as (file_out, file_in):

   ...

Update:
To quote the documentation, regarding contextlib.nested:

Deprecated since version 2.7: The with-statement now supports this functionality directly (without the confusing error prone quirks).

See Rafał Dowgird’s answer for more information.


回答 2

请注意,如果将变量分成几行,则必须使用反斜杠来包装换行符。

with A() as a, \
     B() as b, \
     C() as c:
    doSomething(a,b,c)

括号无效,因为Python会创建一个元组。

with (A(),
      B(),
      C()):
    doSomething(a,b,c)

由于元组缺少__enter__属性,因此会出现错误(描述性不够,并且无法标识类类型):

AttributeError: __enter__

如果尝试as在括号内使用,Python会在解析时捕获错误:

with (A() as a,
      B() as b,
      C() as c):
    doSomething(a,b,c)

SyntaxError:语法无效

https://bugs.python.org/issue12782似乎与此问题有关。

Note that if you split the variables into lines, you must use backslashes to wrap the newlines.

with A() as a, \
     B() as b, \
     C() as c:
    doSomething(a,b,c)

Parentheses don’t work, since Python creates a tuple instead.

with (A(),
      B(),
      C()):
    doSomething(a,b,c)

Since tuples lack a __enter__ attribute, you get an error (undescriptive and does not identify class type):

AttributeError: __enter__

If you try to use as within parentheses, Python catches the mistake at parse time:

with (A() as a,
      B() as b,
      C() as c):
    doSomething(a,b,c)

SyntaxError: invalid syntax

https://bugs.python.org/issue12782 seems to be related to this issue.


回答 3

我认为您想这样做:

from __future__ import with_statement

with open("out.txt","wt") as file_out:
    with open("in.txt") as file_in:
        for line in file_in:
            file_out.write(line)

I think you want to do this instead:

from __future__ import with_statement

with open("out.txt","wt") as file_out:
    with open("in.txt") as file_in:
        for line in file_in:
            file_out.write(line)

回答 4

因为Python 3.3,你可以使用类ExitStackcontextlib模块。

它可以管理动态数量的上下文感知对象,这意味着如果您不知道要处理多少文件,它将证明特别有用。

文档中提到的规范用例正在管理动态文件数量。

with ExitStack() as stack:
    files = [stack.enter_context(open(fname)) for fname in filenames]
    # All opened files will automatically be closed at the end of
    # the with statement, even if attempts to open files later
    # in the list raise an exception

这是一个通用示例:

from contextlib import ExitStack

class X:
    num = 1

    def __init__(self):
        self.num = X.num
        X.num += 1

    def __repr__(self):
        cls = type(self)
        return '{cls.__name__}{self.num}'.format(cls=cls, self=self)

    def __enter__(self):
        print('enter {!r}'.format(self))
        return self.num

    def __exit__(self, exc_type, exc_value, traceback):
        print('exit {!r}'.format(self))
        return True

xs = [X() for _ in range(3)]

with ExitStack() as stack:
    print(stack._exit_callbacks)
    nums = [stack.enter_context(x) for x in xs]
    print(stack._exit_callbacks)
print(stack._exit_callbacks)
print(nums)

输出:

deque([])
enter X1
enter X2
enter X3
deque([<function ExitStack._push_cm_exit.<locals>._exit_wrapper at 0x7f5c95f86158>, <function ExitStack._push_cm_exit.<locals>._exit_wrapper at 0x7f5c95f861e0>, <function ExitStack._push_cm_exit.<locals>._exit_wrapper at 0x7f5c95f86268>])
exit X3
exit X2
exit X1
deque([])
[1, 2, 3]

Since Python 3.3, you can use the class ExitStack from the contextlib module.

It can manage a dynamic number of context-aware objects, which means that it will prove especially useful if you don’t know how many files you are going to handle.

The canonical use-case that is mentioned in the documentation is managing a dynamic number of files.

with ExitStack() as stack:
    files = [stack.enter_context(open(fname)) for fname in filenames]
    # All opened files will automatically be closed at the end of
    # the with statement, even if attempts to open files later
    # in the list raise an exception

Here is a generic example:

from contextlib import ExitStack

class X:
    num = 1

    def __init__(self):
        self.num = X.num
        X.num += 1

    def __repr__(self):
        cls = type(self)
        return '{cls.__name__}{self.num}'.format(cls=cls, self=self)

    def __enter__(self):
        print('enter {!r}'.format(self))
        return self.num

    def __exit__(self, exc_type, exc_value, traceback):
        print('exit {!r}'.format(self))
        return True

xs = [X() for _ in range(3)]

with ExitStack() as stack:
    print(stack._exit_callbacks)
    nums = [stack.enter_context(x) for x in xs]
    print(stack._exit_callbacks)
print(stack._exit_callbacks)
print(nums)

Output:

deque([])
enter X1
enter X2
enter X3
deque([<function ExitStack._push_cm_exit.<locals>._exit_wrapper at 0x7f5c95f86158>, <function ExitStack._push_cm_exit.<locals>._exit_wrapper at 0x7f5c95f861e0>, <function ExitStack._push_cm_exit.<locals>._exit_wrapper at 0x7f5c95f86268>])
exit X3
exit X2
exit X1
deque([])
[1, 2, 3]

回答 5

在Python 3.1+中,您可以指定多个上下文表达式,它们将像with嵌套了多个语句一样进行处理:

with A() as a, B() as b:
    suite

相当于

with A() as a:
    with B() as b:
        suite

这也意味着您可以在第二个表达式中使用第一个表达式的别名(在使用数据库连接/游标时很有用):

with get_conn() as conn, conn.cursor() as cursor:
    cursor.execute(sql)

In Python 3.1+ you can specify multiple context expressions, and they will be processed as if multiple with statements were nested:

with A() as a, B() as b:
    suite

is equivalent to

with A() as a:
    with B() as b:
        suite

This also means that you can use the alias from the first expression in the second (useful when working with db connections/cursors):

with get_conn() as conn, conn.cursor() as cursor:
    cursor.execute(sql)

有没有一种简单的方法来删除字符串中的多个空格?

问题:有没有一种简单的方法来删除字符串中的多个空格?

假设此字符串:

The   fox jumped   over    the log.

转变为:

The fox jumped over the log.

什么是最简单的方法(1-2行),而无需拆分并进入列表?

Suppose this string:

The   fox jumped   over    the log.

Turning into:

The fox jumped over the log.

What is the simplest (1-2 lines) to achieve this, without splitting and going into lists?


回答 0

>>> import re
>>> re.sub(' +', ' ', 'The     quick brown    fox')
'The quick brown fox'
>>> import re
>>> re.sub(' +', ' ', 'The     quick brown    fox')
'The quick brown fox'

回答 1

foo 是您的字符串:

" ".join(foo.split())

请注意,尽管这样做会删除“所有空白字符(空格,制表符,换行符,返回符,换页符)”(由于hhsaffar,请参见注释)。即,"this is \t a test\n"将有效地终止为"this is a test"

foo is your string:

" ".join(foo.split())

Be warned though this removes “all whitespace characters (space, tab, newline, return, formfeed)” (thanks to hhsaffar, see comments). I.e., "this is \t a test\n" will effectively end up as "this is a test".


回答 2

import re
s = "The   fox jumped   over    the log."
re.sub("\s\s+" , " ", s)

要么

re.sub("\s\s+", " ", s)

正如使用者Martin Thoma在评论中所提到的,因为逗号前的空格在PEP 8中被列为“ 宠儿”

import re
s = "The   fox jumped   over    the log."
re.sub("\s\s+" , " ", s)

or

re.sub("\s\s+", " ", s)

since the space before comma is listed as a pet peeve in PEP 8, as mentioned by user Martin Thoma in the comments.


回答 3

将正则表达式与“ \ s”一起使用并执行简单的string.split()也会删除其他空格,例如换行符,回车符,制表符。除非需要这样做,否则我只介绍多个示例。

我使用11个段落,1000个单词,6665字节的Lorem Ipsum进行了真实的时间测试,并在整个过程中使用了随机长度的额外空间:

original_string = ''.join(word + (' ' * random.randint(1, 10)) for word in lorem_ipsum.split(' '))

一衬垫将基本上做任何前/后间隔的条带,并且它保留一个前/后空间(但只ONE ;-)。

# setup = '''

import re

def while_replace(string):
    while '  ' in string:
        string = string.replace('  ', ' ')

    return string

def re_replace(string):
    return re.sub(r' {2,}' , ' ', string)

def proper_join(string):
    split_string = string.split(' ')

    # To account for leading/trailing spaces that would simply be removed
    beg = ' ' if not split_string[ 0] else ''
    end = ' ' if not split_string[-1] else ''

    # versus simply ' '.join(item for item in string.split(' ') if item)
    return beg + ' '.join(item for item in split_string if item) + end

original_string = """Lorem    ipsum        ... no, really, it kept going...          malesuada enim feugiat.         Integer imperdiet    erat."""

assert while_replace(original_string) == re_replace(original_string) == proper_join(original_string)

#'''

# while_replace_test
new_string = original_string[:]

new_string = while_replace(new_string)

assert new_string != original_string

# re_replace_test
new_string = original_string[:]

new_string = re_replace(new_string)

assert new_string != original_string

# proper_join_test
new_string = original_string[:]

new_string = proper_join(new_string)

assert new_string != original_string

注意: while版本”制作了的副本original_string,因为我相信一旦在第一次运行中对其进行了修改,后续运行就会更快(如果只是一点点的话)。随着时间的增加,我将此字符串副本添加到其他两个字符串中,以便时间仅显示逻辑上的差异。 请记住,主要stmttimeit情况下,将只执行一次 ; 我执行此操作的原始方式是,while循环在相同的标签上工作original_string,因此第二次运行将无事可做。现在设置的方式,使用两个不同的标签调用函数,这没有问题。我assert向所有工作人员添加了语句,以验证我们在每次迭代中都对某些内容进行了更改(对于那些可能令人怀疑的人)。例如,更改为它并中断:

# while_replace_test
new_string = original_string[:]

new_string = while_replace(new_string)

assert new_string != original_string # will break the 2nd iteration

while '  ' in original_string:
    original_string = original_string.replace('  ', ' ')

Tests run on a laptop with an i5 processor running Windows 7 (64-bit).

timeit.Timer(stmt = test, setup = setup).repeat(7, 1000)

test_string = 'The   fox jumped   over\n\t    the log.' # trivial

Python 2.7.3, 32-bit, Windows
                test |      minum |    maximum |    average |     median
---------------------+------------+------------+------------+-----------
  while_replace_test |   0.001066 |   0.001260 |   0.001128 |   0.001092
     re_replace_test |   0.003074 |   0.003941 |   0.003357 |   0.003349
    proper_join_test |   0.002783 |   0.004829 |   0.003554 |   0.003035

Python 2.7.3, 64-bit, Windows
                test |      minum |    maximum |    average |     median
---------------------+------------+------------+------------+-----------
  while_replace_test |   0.001025 |   0.001079 |   0.001052 |   0.001051
     re_replace_test |   0.003213 |   0.004512 |   0.003656 |   0.003504
    proper_join_test |   0.002760 |   0.006361 |   0.004626 |   0.004600

Python 3.2.3, 32-bit, Windows
                test |      minum |    maximum |    average |     median
---------------------+------------+------------+------------+-----------
  while_replace_test |   0.001350 |   0.002302 |   0.001639 |   0.001357
     re_replace_test |   0.006797 |   0.008107 |   0.007319 |   0.007440
    proper_join_test |   0.002863 |   0.003356 |   0.003026 |   0.002975

Python 3.3.3, 64-bit, Windows
                test |      minum |    maximum |    average |     median
---------------------+------------+------------+------------+-----------
  while_replace_test |   0.001444 |   0.001490 |   0.001460 |   0.001459
     re_replace_test |   0.011771 |   0.012598 |   0.012082 |   0.011910
    proper_join_test |   0.003741 |   0.005933 |   0.004341 |   0.004009

test_string = lorem_ipsum
# Thanks to http://www.lipsum.com/
# "Generated 11 paragraphs, 1000 words, 6665 bytes of Lorem Ipsum"

Python 2.7.3, 32-bit
                test |      minum |    maximum |    average |     median
---------------------+------------+------------+------------+-----------
  while_replace_test |   0.342602 |   0.387803 |   0.359319 |   0.356284
     re_replace_test |   0.337571 |   0.359821 |   0.348876 |   0.348006
    proper_join_test |   0.381654 |   0.395349 |   0.388304 |   0.388193    

Python 2.7.3, 64-bit
                test |      minum |    maximum |    average |     median
---------------------+------------+------------+------------+-----------
  while_replace_test |   0.227471 |   0.268340 |   0.240884 |   0.236776
     re_replace_test |   0.301516 |   0.325730 |   0.308626 |   0.307852
    proper_join_test |   0.358766 |   0.383736 |   0.370958 |   0.371866    

Python 3.2.3, 32-bit
                test |      minum |    maximum |    average |     median
---------------------+------------+------------+------------+-----------
  while_replace_test |   0.438480 |   0.463380 |   0.447953 |   0.446646
     re_replace_test |   0.463729 |   0.490947 |   0.472496 |   0.468778
    proper_join_test |   0.397022 |   0.427817 |   0.406612 |   0.402053    

Python 3.3.3, 64-bit
                test |      minum |    maximum |    average |     median
---------------------+------------+------------+------------+-----------
  while_replace_test |   0.284495 |   0.294025 |   0.288735 |   0.289153
     re_replace_test |   0.501351 |   0.525673 |   0.511347 |   0.508467
    proper_join_test |   0.422011 |   0.448736 |   0.436196 |   0.440318

对于琐碎的字符串,似乎while循环是最快的,其次是Pythonic字符串拆分/连接,而regex则拉到后面。

对于非平凡的字符串,似乎还有更多需要考虑的地方。32位2.7?正则表达式可以解救!2.7 64位?一while环是最好的,通过一个体面的保证金。32位3.2,使用“ proper” join。64位3.3,进行while循环。再次。

最后,如果需要/在哪里/何时需要,人们可以提高性能,但始终最好记住这一口头禅

  1. 让它起作用
  2. 改正它
  3. 快一点

IANAL,YMMV,警告加油站!

Using regexes with “\s” and doing simple string.split()’s will also remove other whitespace – like newlines, carriage returns, tabs. Unless this is desired, to only do multiple spaces, I present these examples.

I used 11 paragraphs, 1000 words, 6665 bytes of Lorem Ipsum to get realistic time tests and used random-length extra spaces throughout:

original_string = ''.join(word + (' ' * random.randint(1, 10)) for word in lorem_ipsum.split(' '))

The one-liner will essentially do a strip of any leading/trailing spaces, and it preserves a leading/trailing space (but only ONE ;-).

# setup = '''

import re

def while_replace(string):
    while '  ' in string:
        string = string.replace('  ', ' ')

    return string

def re_replace(string):
    return re.sub(r' {2,}' , ' ', string)

def proper_join(string):
    split_string = string.split(' ')

    # To account for leading/trailing spaces that would simply be removed
    beg = ' ' if not split_string[ 0] else ''
    end = ' ' if not split_string[-1] else ''

    # versus simply ' '.join(item for item in string.split(' ') if item)
    return beg + ' '.join(item for item in split_string if item) + end

original_string = """Lorem    ipsum        ... no, really, it kept going...          malesuada enim feugiat.         Integer imperdiet    erat."""

assert while_replace(original_string) == re_replace(original_string) == proper_join(original_string)

#'''

# while_replace_test
new_string = original_string[:]

new_string = while_replace(new_string)

assert new_string != original_string

# re_replace_test
new_string = original_string[:]

new_string = re_replace(new_string)

assert new_string != original_string

# proper_join_test
new_string = original_string[:]

new_string = proper_join(new_string)

assert new_string != original_string

NOTE: The “while version” made a copy of the original_string, as I believe once modified on the first run, successive runs would be faster (if only by a bit). As this adds time, I added this string copy to the other two so that the times showed the difference only in the logic. Keep in mind that the main stmt on timeit instances will only be executed once; the original way I did this, the while loop worked on the same label, original_string, thus the second run, there would be nothing to do. The way it’s set up now, calling a function, using two different labels, that isn’t a problem. I’ve added assert statements to all the workers to verify we change something every iteration (for those who may be dubious). E.g., change to this and it breaks:

# while_replace_test
new_string = original_string[:]

new_string = while_replace(new_string)

assert new_string != original_string # will break the 2nd iteration

while '  ' in original_string:
    original_string = original_string.replace('  ', ' ')

Tests run on a laptop with an i5 processor running Windows 7 (64-bit).

timeit.Timer(stmt = test, setup = setup).repeat(7, 1000)

test_string = 'The   fox jumped   over\n\t    the log.' # trivial

Python 2.7.3, 32-bit, Windows
                test |      minum |    maximum |    average |     median
---------------------+------------+------------+------------+-----------
  while_replace_test |   0.001066 |   0.001260 |   0.001128 |   0.001092
     re_replace_test |   0.003074 |   0.003941 |   0.003357 |   0.003349
    proper_join_test |   0.002783 |   0.004829 |   0.003554 |   0.003035

Python 2.7.3, 64-bit, Windows
                test |      minum |    maximum |    average |     median
---------------------+------------+------------+------------+-----------
  while_replace_test |   0.001025 |   0.001079 |   0.001052 |   0.001051
     re_replace_test |   0.003213 |   0.004512 |   0.003656 |   0.003504
    proper_join_test |   0.002760 |   0.006361 |   0.004626 |   0.004600

Python 3.2.3, 32-bit, Windows
                test |      minum |    maximum |    average |     median
---------------------+------------+------------+------------+-----------
  while_replace_test |   0.001350 |   0.002302 |   0.001639 |   0.001357
     re_replace_test |   0.006797 |   0.008107 |   0.007319 |   0.007440
    proper_join_test |   0.002863 |   0.003356 |   0.003026 |   0.002975

Python 3.3.3, 64-bit, Windows
                test |      minum |    maximum |    average |     median
---------------------+------------+------------+------------+-----------
  while_replace_test |   0.001444 |   0.001490 |   0.001460 |   0.001459
     re_replace_test |   0.011771 |   0.012598 |   0.012082 |   0.011910
    proper_join_test |   0.003741 |   0.005933 |   0.004341 |   0.004009

test_string = lorem_ipsum
# Thanks to http://www.lipsum.com/
# "Generated 11 paragraphs, 1000 words, 6665 bytes of Lorem Ipsum"

Python 2.7.3, 32-bit
                test |      minum |    maximum |    average |     median
---------------------+------------+------------+------------+-----------
  while_replace_test |   0.342602 |   0.387803 |   0.359319 |   0.356284
     re_replace_test |   0.337571 |   0.359821 |   0.348876 |   0.348006
    proper_join_test |   0.381654 |   0.395349 |   0.388304 |   0.388193    

Python 2.7.3, 64-bit
                test |      minum |    maximum |    average |     median
---------------------+------------+------------+------------+-----------
  while_replace_test |   0.227471 |   0.268340 |   0.240884 |   0.236776
     re_replace_test |   0.301516 |   0.325730 |   0.308626 |   0.307852
    proper_join_test |   0.358766 |   0.383736 |   0.370958 |   0.371866    

Python 3.2.3, 32-bit
                test |      minum |    maximum |    average |     median
---------------------+------------+------------+------------+-----------
  while_replace_test |   0.438480 |   0.463380 |   0.447953 |   0.446646
     re_replace_test |   0.463729 |   0.490947 |   0.472496 |   0.468778
    proper_join_test |   0.397022 |   0.427817 |   0.406612 |   0.402053    

Python 3.3.3, 64-bit
                test |      minum |    maximum |    average |     median
---------------------+------------+------------+------------+-----------
  while_replace_test |   0.284495 |   0.294025 |   0.288735 |   0.289153
     re_replace_test |   0.501351 |   0.525673 |   0.511347 |   0.508467
    proper_join_test |   0.422011 |   0.448736 |   0.436196 |   0.440318

For the trivial string, it would seem that a while-loop is the fastest, followed by the Pythonic string-split/join, and regex pulling up the rear.

For non-trivial strings, seems there’s a bit more to consider. 32-bit 2.7? It’s regex to the rescue! 2.7 64-bit? A while loop is best, by a decent margin. 32-bit 3.2, go with the “proper” join. 64-bit 3.3, go for a while loop. Again.

In the end, one can improve performance if/where/when needed, but it’s always best to remember the mantra:

  1. Make It Work
  2. Make It Right
  3. Make It Fast

IANAL, YMMV, Caveat Emptor!


回答 4

我必须同意保罗·麦圭尔的评论。对我来说,

' '.join(the_string.split())

比使用正则表达式要好得多。

我的测量结果(Linux和Python 2.5)显示split-then-join几乎比执行“ re.sub(…)”快五倍,如果预编译一次regex并执行操作,则快三倍。多次。它是比较容易理解的任何措施- 很多更Python。

I have to agree with Paul McGuire’s comment. To me,

' '.join(the_string.split())

is vastly preferable to whipping out a regex.

My measurements (Linux and Python 2.5) show the split-then-join to be almost five times faster than doing the “re.sub(…)”, and still three times faster if you precompile the regex once and do the operation multiple times. And it is by any measure easier to understand — much more Pythonic.


回答 5

与以前的解决方案类似,但更具体:用一个替换两个或多个空格:

>>> import re
>>> s = "The   fox jumped   over    the log."
>>> re.sub('\s{2,}', ' ', s)
'The fox jumped over the log.'

Similar to the previous solutions, but more specific: replace two or more spaces with one:

>>> import re
>>> s = "The   fox jumped   over    the log."
>>> re.sub('\s{2,}', ' ', s)
'The fox jumped over the log.'

回答 6

一个简单的灵魂

>>> import re
>>> s="The   fox jumped   over    the log."
>>> print re.sub('\s+',' ', s)
The fox jumped over the log.

A simple soultion

>>> import re
>>> s="The   fox jumped   over    the log."
>>> print re.sub('\s+',' ', s)
The fox jumped over the log.

回答 7

您也可以在Pandas DataFrame中使用字符串拆分技术,而无需使用.apply(..),如果您需要对大量字符串快速执行操作,此方法将非常有用。这是一行:

df['message'] = (df['message'].str.split()).str.join(' ')

You can also use the string splitting technique in a Pandas DataFrame without needing to use .apply(..), which is useful if you need to perform the operation quickly on a large number of strings. Here it is on one line:

df['message'] = (df['message'].str.split()).str.join(' ')

回答 8

import re
string = re.sub('[ \t\n]+', ' ', 'The     quick brown                \n\n             \t        fox')

这将删除所有选项卡,换行和带有单个空格的多个空格。

import re
string = re.sub('[ \t\n]+', ' ', 'The     quick brown                \n\n             \t        fox')

This will remove all the tabs, new lines and multiple white spaces with single white space.


回答 9

我尝试了以下方法,甚至可以在极端情况下使用:

str1='          I   live    on    earth           '

' '.join(str1.split())

但是,如果您更喜欢正则表达式,则可以通过以下方式完成:

re.sub('\s+', ' ', str1)

尽管必须进行一些预处理才能删除尾随和结尾的空间。

I have tried the following method and it even works with the extreme case like:

str1='          I   live    on    earth           '

' '.join(str1.split())

But if you prefer a regular expression it can be done as:

re.sub('\s+', ' ', str1)

Although some preprocessing has to be done in order to remove the trailing and ending space.


回答 10

这似乎也可行:

while "  " in s:
    s = s.replace("  ", " ")

其中变量s代表您的字符串。

This also seems to work:

while "  " in s:
    s = s.replace("  ", " ")

Where the variable s represents your string.


回答 11

在某些情况下,它是希望用的单个实例来代替每个空格字符的连续出现字符。您将使用带有反向引用的正则表达式来执行此操作。

(\s)\1{1,}匹配任何空白字符,后跟一个或多个该字符。现在,您所需要做的就是指定第一个组(\1)作为匹配项的替换。

将其包装在函数中:

import re

def normalize_whitespace(string):
    return re.sub(r'(\s)\1{1,}', r'\1', string)
>>> normalize_whitespace('The   fox jumped   over    the log.')
'The fox jumped over the log.'
>>> normalize_whitespace('First    line\t\t\t \n\n\nSecond    line')
'First line\t \nSecond line'

In some cases it’s desirable to replace consecutive occurrences of every whitespace character with a single instance of that character. You’d use a regular expression with backreferences to do that.

(\s)\1{1,} matches any whitespace character, followed by one or more occurrences of that character. Now, all you need to do is specify the first group (\1) as the replacement for the match.

Wrapping this in a function:

import re

def normalize_whitespace(string):
    return re.sub(r'(\s)\1{1,}', r'\1', string)
>>> normalize_whitespace('The   fox jumped   over    the log.')
'The fox jumped over the log.'
>>> normalize_whitespace('First    line\t\t\t \n\n\nSecond    line')
'First line\t \nSecond line'

回答 12

另一种选择:

>>> import re
>>> str = 'this is a            string with    multiple spaces and    tabs'
>>> str = re.sub('[ \t]+' , ' ', str)
>>> print str
this is a string with multiple spaces and tabs

Another alternative:

>>> import re
>>> str = 'this is a            string with    multiple spaces and    tabs'
>>> str = re.sub('[ \t]+' , ' ', str)
>>> print str
this is a string with multiple spaces and tabs

回答 13

一行代码删除句子之前,之后和之内的所有多余空格:

sentence = "  The   fox jumped   over    the log.  "
sentence = ' '.join(filter(None,sentence.split(' ')))

说明:

  1. 将整个字符串拆分为一个列表。
  2. 从列表中过滤空元素。
  3. 用一个空格重新合并其余元素*

*其余元素应该是单词或带有标点符号的单词等。我没有对此进行广泛的测试,但这应该是一个很好的起点。祝一切顺利!

One line of code to remove all extra spaces before, after, and within a sentence:

sentence = "  The   fox jumped   over    the log.  "
sentence = ' '.join(filter(None,sentence.split(' ')))

Explanation:

  1. Split the entire string into a list.
  2. Filter empty elements from the list.
  3. Rejoin the remaining elements* with a single space

*The remaining elements should be words or words with punctuations, etc. I did not test this extensively, but this should be a good starting point. All the best!


回答 14

适用于Python开发人员的解决方案:

import re

text1 = 'Python      Exercises    Are   Challenging Exercises'
print("Original string: ", text1)
print("Without extra spaces: ", re.sub(' +', ' ', text1))

输出:
Original string: Python Exercises Are Challenging Exercises Without extra spaces: Python Exercises Are Challenging Exercises

Solution for Python developers:

import re

text1 = 'Python      Exercises    Are   Challenging Exercises'
print("Original string: ", text1)
print("Without extra spaces: ", re.sub(' +', ' ', text1))

Output:
Original string: Python Exercises Are Challenging Exercises Without extra spaces: Python Exercises Are Challenging Exercises


回答 15

def unPretty(S):
   # Given a dictionary, JSON, list, float, int, or even a string...
   # return a string stripped of CR, LF replaced by space, with multiple spaces reduced to one.
   return ' '.join(str(S).replace('\n', ' ').replace('\r', '').split())
def unPretty(S):
   # Given a dictionary, JSON, list, float, int, or even a string...
   # return a string stripped of CR, LF replaced by space, with multiple spaces reduced to one.
   return ' '.join(str(S).replace('\n', ' ').replace('\r', '').split())

回答 16

用户生成的字符串最快的速度是:

if '  ' in text:
    while '  ' in text:
        text = text.replace('  ', ' ')

短路使其比pythonlarry的综合答案要快一些。如果您追求效率,并严格寻求除掉单个空间种类的多余空白,则可以这样做

The fastest you can get for user-generated strings is:

if '  ' in text:
    while '  ' in text:
        text = text.replace('  ', ' ')

The short circuiting makes it slightly faster than pythonlarry’s comprehensive answer. Go for this if you’re after efficiency and are strictly looking to weed out extra whitespaces of the single space variety.


回答 17

非常令人惊讶-没有人发布过简单的功能,它会比所有其他发布的解决方案快得多。它去了:

def compactSpaces(s):
    os = ""
    for c in s:
        if c != " " or os[-1] != " ":
            os += c 
    return os

Quite surprising – no one posted simple function which will be much faster than ALL other posted solutions. Here it goes:

def compactSpaces(s):
    os = ""
    for c in s:
        if c != " " or os[-1] != " ":
            os += c 
    return os

回答 18

如果您要处理的是空格,则在None上分割将不会在返回值中包含空字符串。

5.6.1。字符串方法,str.split()

If it’s whitespace you’re dealing with, splitting on None will not include an empty string in the returned value.

5.6.1. String Methods, str.split()


回答 19

string = 'This is a             string full of spaces          and taps'
string = string.split(' ')
while '' in string:
    string.remove('')
string = ' '.join(string)
print(string)

结果

这是一个充满空格和水龙头的字符串

string = 'This is a             string full of spaces          and taps'
string = string.split(' ')
while '' in string:
    string.remove('')
string = ' '.join(string)
print(string)

Results:

This is a string full of spaces and taps


回答 20

要删除空格,请考虑单词之间的前导,尾随和多余的空格,请使用:

(?<=\s) +|^ +(?=\s)| (?= +[\n\0])

第一个or处理前导空白,第二个or处理字符串前导空白的开始,最后一个处理尾随空白。

为了使用证明,此链接将为您提供测试。

https://regex101.com/r/meBYli/4

这将与re.split函数一起使用。

To remove white space, considering leading, trailing and extra white space in between words, use:

(?<=\s) +|^ +(?=\s)| (?= +[\n\0])

The first or deals with leading white space, the second or deals with start of string leading white space, and the last one deals with trailing white space.

For proof of use, this link will provide you with a test.

https://regex101.com/r/meBYli/4

This is to be used with the re.split function.


回答 21

我有我在大学中使用过的简单方法。

line = "I     have            a       nice    day."

end = 1000
while end != 0:
    line.replace("  ", " ")
    end -= 1

这会将每个双倍空格替换为一个空格并将执行1000次。这意味着您可以有2000个额外空间,并且仍然可以使用。:)

I have my simple method which I have used in college.

line = "I     have            a       nice    day."

end = 1000
while end != 0:
    line.replace("  ", " ")
    end -= 1

This will replace every double space with a single space and will do it 1000 times. It means you can have 2000 extra spaces and will still work. :)


回答 22

我有一个不分裂的简单方法:

a = "Lorem   Ipsum Darum     Diesrum!"
while True:
    count = a.find("  ")
    if count > 0:
        a = a.replace("  ", " ")
        count = a.find("  ")
        continue
    else:
        break

print(a)

I’ve got a simple method without splitting:

a = "Lorem   Ipsum Darum     Diesrum!"
while True:
    count = a.find("  ")
    if count > 0:
        a = a.replace("  ", " ")
        count = a.find("  ")
        continue
    else:
        break

print(a)

回答 23

import re

Text = " You can select below trims for removing white space!!   BR Aliakbar     "
  # trims all white spaces
print('Remove all space:',re.sub(r"\s+", "", Text), sep='') 
# trims left space
print('Remove leading space:', re.sub(r"^\s+", "", Text), sep='') 
# trims right space
print('Remove trailing spaces:', re.sub(r"\s+$", "", Text), sep='')  
# trims both
print('Remove leading and trailing spaces:', re.sub(r"^\s+|\s+$", "", Text), sep='')
# replace more than one white space in the string with one white space
print('Remove more than one space:',re.sub(' +', ' ',Text), sep='') 

结果:

删除所有空间:您可以选择下面的修剪来删除空白!BRAliakbar删除前导空间:您可以选择下面的修剪来删除空白!BR Aliakbar
删除尾部空格:您可以选择以下修剪以删除空白!BR Aliakbar删除前导和尾随空格:您可以选择以下修饰来删除空白!!BR Aliakbar删除多个空格:您可以选择以下修剪以删除空白!!BR Aliakbar

import re

Text = " You can select below trims for removing white space!!   BR Aliakbar     "
  # trims all white spaces
print('Remove all space:',re.sub(r"\s+", "", Text), sep='') 
# trims left space
print('Remove leading space:', re.sub(r"^\s+", "", Text), sep='') 
# trims right space
print('Remove trailing spaces:', re.sub(r"\s+$", "", Text), sep='')  
# trims both
print('Remove leading and trailing spaces:', re.sub(r"^\s+|\s+$", "", Text), sep='')
# replace more than one white space in the string with one white space
print('Remove more than one space:',re.sub(' +', ' ',Text), sep='') 

Result:

Remove all space:Youcanselectbelowtrimsforremovingwhitespace!!BRAliakbar Remove leading space:You can select below trims for removing white space!! BR Aliakbar
Remove trailing spaces: You can select below trims for removing white space!! BR Aliakbar Remove leading and trailing spaces:You can select below trims for removing white space!! BR Aliakbar Remove more than one space: You can select below trims for removing white space!! BR Aliakbar


回答 24

我没有在其他示例中读很多书,但是我刚刚创建了用于合并多个连续空格字符的方法。

它不使用任何库,尽管就脚本长度而言比较长,但它不是一个复杂的实现:

def spaceMatcher(command):
    """
    Function defined to consolidate multiple whitespace characters in
    strings to a single space
    """
    # Initiate index to flag if more than one consecutive character
    iteration
    space_match = 0
    space_char = ""
    for char in command:
      if char == " ":
          space_match += 1
          space_char += " "
      elif (char != " ") & (space_match > 1):
          new_command = command.replace(space_char, " ")
          space_match = 0
          space_char = ""
      elif char != " ":
          space_match = 0
          space_char = ""
   return new_command

command = None
command = str(input("Please enter a command ->"))
print(spaceMatcher(command))
print(list(spaceMatcher(command)))

I haven’t read a lot into the other examples, but I have just created this method for consolidating multiple consecutive space characters.

It does not use any libraries, and whilst it is relatively long in terms of script length, it is not a complex implementation:

def spaceMatcher(command):
    """
    Function defined to consolidate multiple whitespace characters in
    strings to a single space
    """
    # Initiate index to flag if more than one consecutive character
    iteration
    space_match = 0
    space_char = ""
    for char in command:
      if char == " ":
          space_match += 1
          space_char += " "
      elif (char != " ") & (space_match > 1):
          new_command = command.replace(space_char, " ")
          space_match = 0
          space_char = ""
      elif char != " ":
          space_match = 0
          space_char = ""
   return new_command

command = None
command = str(input("Please enter a command ->"))
print(spaceMatcher(command))
print(list(spaceMatcher(command)))

在Django中,“ related_name”是用来做什么的?

问题:在Django中,“ related_name”是用来做什么的?

related_name参数对on ManyToManyFieldForeignKeyfield有什么用?例如,给定以下代码,的作用是related_name='maps'什么?

class Map(db.Model):
    members = models.ManyToManyField(User, related_name='maps',
                                     verbose_name=_('members'))

What is the related_name argument useful for on ManyToManyField and ForeignKey fields? For example, given the following code, what is the effect of related_name='maps'?

class Map(db.Model):
    members = models.ManyToManyField(User, related_name='maps',
                                     verbose_name=_('members'))

回答 0

related_name属性指定从User模型回到模型的反向关系的名称。

如果不指定related_name,Django会自动使用带有后缀的型号的名称创建一个_set,例如User.map_set.all()

如果确实related_name=mapsUser模型上指定,User.map_set则仍然可以使用,但是User.maps.语法显然更简洁,更简洁。因此,例如,如果您有一个用户对象current_user,则可以current_user.maps.all()用来获取Map模型中与关联的所有实例current_user

Django文档有更多的细节。

The related_name attribute specifies the name of the reverse relation from the User model back to your model.

If you don’t specify a related_name, Django automatically creates one using the name of your model with the suffix _set, for instance User.map_set.all().

If you do specify, e.g. related_name=maps on the User model, User.map_set will still work, but the User.maps. syntax is obviously a bit cleaner and less clunky; so for example, if you had a user object current_user, you could use current_user.maps.all() to get all instances of your Map model that have a relation to current_user.

The Django documentation has more details.


回答 1

要添加到现有答案中-如果模型中有2个FK指向同一张表,则必须使用相关名称。例如物料清单

@with_author 
class BOM(models.Model): 
    name = models.CharField(max_length=200,null=True, blank=True)
    description = models.TextField(null=True, blank=True)
    tomaterial =  models.ForeignKey(Material, related_name = 'tomaterial')
    frommaterial =  models.ForeignKey(Material, related_name = 'frommaterial')
    creation_time = models.DateTimeField(auto_now_add=True, blank=True)
    quantity = models.DecimalField(max_digits=19, decimal_places=10)

因此,当您必须访问此数据时,您只能使用相关名称

 bom = material.tomaterial.all().order_by('-creation_time')

否则它将无法正常工作(至少在同一张表中有2个FK的情况下,我无法跳过相关名称的使用。)

To add to existing answer – related name is a must in case there 2 FKs in the model that point to the same table. For example in case of Bill of material

@with_author 
class BOM(models.Model): 
    name = models.CharField(max_length=200,null=True, blank=True)
    description = models.TextField(null=True, blank=True)
    tomaterial =  models.ForeignKey(Material, related_name = 'tomaterial')
    frommaterial =  models.ForeignKey(Material, related_name = 'frommaterial')
    creation_time = models.DateTimeField(auto_now_add=True, blank=True)
    quantity = models.DecimalField(max_digits=19, decimal_places=10)

So when you will have to access this data you only can use related name

 bom = material.tomaterial.all().order_by('-creation_time')

It is not working otherwise (at least I was not able to skip the usage of related name in case of 2 FK’s to the same table.)


回答 2

related_name如果您具有更复杂的相关类名,则该参数也很有用。例如,如果您具有外键关系:

class UserMapDataFrame(models.Model):
    user = models.ForeignKey(User) 

为了UserMapDataFrame从related中访问对象User,默认调用为User.usermapdataframe_set.all(),这很难阅读。

使用,related_name您可以指定一个更简单或更清晰的名称来获取反向关系。在这种情况下,如果您指定user = models.ForeignKey(User, related_name='map_data'),则呼叫将为User.map_data.all()

The related_name argument is also useful if you have more complex related class names. For example, if you have a foreign key relationship:

class UserMapDataFrame(models.Model):
    user = models.ForeignKey(User) 

In order to access UserMapDataFrame objects from the related User, the default call would be User.usermapdataframe_set.all(), which it is quite difficult to read.

Using the related_name allows you to specify a simpler or more legible name to get the reverse relation. In this case, if you specify user = models.ForeignKey(User, related_name='map_data'), the call would then be User.map_data.all().


回答 3

相关的名称参数实际上是一个选项。如果我们不设置它,Django会自动为我们创建关系的另一面。对于Map模型,Django将创建一个map_set属性,从而允许m.map_set在您的示例中访问(m是您的类实例)。Django使用的公式是模型的名称,后跟字符串_set。因此,相关的name参数仅覆盖Django的默认值,而不提供新的行为。

The related name parameter is actually an option. If we do not set it, Django automatically creates the other side of the relation for us. In the case of the Map model, Django would have created a map_set attribute, allowing access via m.map_set in your example(m being your class instance). The formula Django uses is the name of the model followed by the string _set. The related name parameter thus simply overrides Django’s default rather than providing new behavior.


回答 4

prefetch_related用于预取多对多和多对一关系数据的数据。 select_related是从单个值关系中选择数据。这两个都用于从模型的关系中获取数据。例如,您构建一个模型以及一个与其他模型有关系的模型。当请求到来时,您还将查询他们的关系数据,并且Django具有很好的机制来从他们的关系中访问数据,例如book.author.name,当您迭代用于获取其关系数据的模型列表时,Django会为每个单个关系数据创建每个请求。为了克服这个问题,我们确实有 prefetchd_relatedselected_related

prefetch_related use for prefetch data for Many to many and many to one relationship data. select_related is to select data from a single value relationship. Both of these are used to fetch data from their relationships from a model. For example, you build a model and a model that has a relationship with other models. When a request comes you will also query for their relationship data and Django has very good mechanisms To access data from their relationship like book.author.name but when you iterate a list of models for fetching their relationship data Django create each request for every single relationship data. To overcome this we do have prefetchd_related and selected_related