分类目录归档:知识问答

禁用输出缓冲

问题:禁用输出缓冲

默认情况下,Python的解释器是否启用输出缓冲sys.stdout

如果答案是肯定的,那么有什么方法可以禁用它?

到目前为止的建议:

  1. 使用-u命令行开关
  2. 包装sys.stdout每次写入后刷新的对象
  3. 设置环境PYTHONUNBUFFERED变量
  4. sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)

还有其他方法可以在执行过程中以编程方式在sys/中设置一些全局标志sys.stdout吗?

Is output buffering enabled by default in Python’s interpreter for sys.stdout?

If the answer is positive, what are all the ways to disable it?

Suggestions so far:

  1. Use the -u command line switch
  2. Wrap sys.stdout in an object that flushes after every write
  3. Set PYTHONUNBUFFERED env var
  4. sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)

Is there any other way to set some global flag in sys/sys.stdout programmatically during execution?


回答 0

Magnus Lycka的邮件列表中答复

您可以使用“ python -u”(或#!/ usr / bin / env python -u等)或通过设置环境变量PYTHONUNBUFFERED跳过整个python进程的缓冲。

您还可以将sys.stdout替换为包装器之类的其他流,该流在每次调用后进行刷新。

class Unbuffered(object):
   def __init__(self, stream):
       self.stream = stream
   def write(self, data):
       self.stream.write(data)
       self.stream.flush()
   def writelines(self, datas):
       self.stream.writelines(datas)
       self.stream.flush()
   def __getattr__(self, attr):
       return getattr(self.stream, attr)

import sys
sys.stdout = Unbuffered(sys.stdout)
print 'Hello'

From Magnus Lycka answer on a mailing list:

You can skip buffering for a whole python process using “python -u” (or#!/usr/bin/env python -u etc) or by setting the environment variable PYTHONUNBUFFERED.

You could also replace sys.stdout with some other stream like wrapper which does a flush after every call.

class Unbuffered(object):
   def __init__(self, stream):
       self.stream = stream
   def write(self, data):
       self.stream.write(data)
       self.stream.flush()
   def writelines(self, datas):
       self.stream.writelines(datas)
       self.stream.flush()
   def __getattr__(self, attr):
       return getattr(self.stream, attr)

import sys
sys.stdout = Unbuffered(sys.stdout)
print 'Hello'

回答 1

我宁愿把答案 如何刷新打印功能的输出中?还是在Python的print函数中在调用缓冲区时刷新缓冲区?,但由于它们被标记为与此副本的副本(我不同意),因此我将在此处回答。

从Python 3.3开始,print()支持关键字参数“ flush”(请参阅文档):

print('Hello World!', flush=True)

I would rather put my answer in How to flush output of print function? or in Python’s print function that flushes the buffer when it’s called?, but since they were marked as duplicates of this one (what I do not agree), I’ll answer it here.

Since Python 3.3, print() supports the keyword argument “flush” (see documentation):

print('Hello World!', flush=True)

回答 2

# reopen stdout file descriptor with write mode
# and 0 as the buffer size (unbuffered)
import io, os, sys
try:
    # Python 3, open as binary, then wrap in a TextIOWrapper with write-through.
    sys.stdout = io.TextIOWrapper(open(sys.stdout.fileno(), 'wb', 0), write_through=True)
    # If flushing on newlines is sufficient, as of 3.7 you can instead just call:
    # sys.stdout.reconfigure(line_buffering=True)
except TypeError:
    # Python 2
    sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)

鸣谢:“ Sebastian”,在Python邮件列表上的某处。

# reopen stdout file descriptor with write mode
# and 0 as the buffer size (unbuffered)
import io, os, sys
try:
    # Python 3, open as binary, then wrap in a TextIOWrapper with write-through.
    sys.stdout = io.TextIOWrapper(open(sys.stdout.fileno(), 'wb', 0), write_through=True)
    # If flushing on newlines is sufficient, as of 3.7 you can instead just call:
    # sys.stdout.reconfigure(line_buffering=True)
except TypeError:
    # Python 2
    sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)

Credits: “Sebastian”, somewhere on the Python mailing list.


回答 3

是的。

您可以使用“ -u”开关在命令行上禁用它。

或者,您可以在每次写入时在sys.stdout上调用.flush()(或将其包装为自动执行此操作的对象)

Yes, it is.

You can disable it on the commandline with the “-u” switch.

Alternatively, you could call .flush() on sys.stdout on every write (or wrap it with an object that does this automatically)


回答 4

这与克里斯托瓦·索萨(CristóvãoD. Sousa)的答案有关,但我无法发表评论。

为了始终具有未缓冲的输出而使用Python 3flush关键字参数的直接方法是:

import functools
print = functools.partial(print, flush=True)

之后,打印将始终直接刷新输出(flush=False给出的除外)。

请注意,(a)这只能部分回答问题,因为它不会重定向所有输出。但是我想这print是在python中创建输出到stdout/ 的最常见方法stderr,因此这两行可能涵盖了大多数用例。

注意(b)它仅在定义它的模块/脚本中起作用。编写模块时这可能会很好,因为它不会与混淆sys.stdout

Python 2不提供flush参数,但是您可以仿真Python 3型print函数,如此处https://stackoverflow.com/a/27991478/3734258所述

This relates to Cristóvão D. Sousa’s answer, but I couldn’t comment yet.

A straight-forward way of using the flush keyword argument of Python 3 in order to always have unbuffered output is:

import functools
print = functools.partial(print, flush=True)

afterwards, print will always flush the output directly (except flush=False is given).

Note, (a) that this answers the question only partially as it doesn’t redirect all the output. But I guess print is the most common way for creating output to stdout/stderr in python, so these 2 lines cover probably most of the use cases.

Note (b) that it only works in the module/script where you defined it. This can be good when writing a module as it doesn’t mess with the sys.stdout.

Python 2 doesn’t provide the flush argument, but you could emulate a Python 3-type print function as described here https://stackoverflow.com/a/27991478/3734258 .


回答 5

def disable_stdout_buffering():
    # Appending to gc.garbage is a way to stop an object from being
    # destroyed.  If the old sys.stdout is ever collected, it will
    # close() stdout, which is not good.
    gc.garbage.append(sys.stdout)
    sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)

# Then this will give output in the correct order:
disable_stdout_buffering()
print "hello"
subprocess.call(["echo", "bye"])

如果不保存旧的sys.stdout,disable_stdout_buffering()并不是幂等的,并且多次调用将导致如下错误:

Traceback (most recent call last):
  File "test/buffering.py", line 17, in <module>
    print "hello"
IOError: [Errno 9] Bad file descriptor
close failed: [Errno 9] Bad file descriptor

另一种可能性是:

def disable_stdout_buffering():
    fileno = sys.stdout.fileno()
    temp_fd = os.dup(fileno)
    sys.stdout.close()
    os.dup2(temp_fd, fileno)
    os.close(temp_fd)
    sys.stdout = os.fdopen(fileno, "w", 0)

(添加到gc.garbage并不是一个好主意,因为这是放置不可释放的循环的地方,您可能需要检查这些循环。)

def disable_stdout_buffering():
    # Appending to gc.garbage is a way to stop an object from being
    # destroyed.  If the old sys.stdout is ever collected, it will
    # close() stdout, which is not good.
    gc.garbage.append(sys.stdout)
    sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)

# Then this will give output in the correct order:
disable_stdout_buffering()
print "hello"
subprocess.call(["echo", "bye"])

Without saving the old sys.stdout, disable_stdout_buffering() isn’t idempotent, and multiple calls will result in an error like this:

Traceback (most recent call last):
  File "test/buffering.py", line 17, in <module>
    print "hello"
IOError: [Errno 9] Bad file descriptor
close failed: [Errno 9] Bad file descriptor

Another possibility is:

def disable_stdout_buffering():
    fileno = sys.stdout.fileno()
    temp_fd = os.dup(fileno)
    sys.stdout.close()
    os.dup2(temp_fd, fileno)
    os.close(temp_fd)
    sys.stdout = os.fdopen(fileno, "w", 0)

(Appending to gc.garbage is not such a good idea because it’s where unfreeable cycles get put, and you might want to check for those.)


回答 6

以下在Python 2.6、2.7和3.2中有效:

import os
import sys
buf_arg = 0
if sys.version_info[0] == 3:
    os.environ['PYTHONUNBUFFERED'] = '1'
    buf_arg = 1
sys.stdout = os.fdopen(sys.stdout.fileno(), 'a+', buf_arg)
sys.stderr = os.fdopen(sys.stderr.fileno(), 'a+', buf_arg)

The following works in Python 2.6, 2.7, and 3.2:

import os
import sys
buf_arg = 0
if sys.version_info[0] == 3:
    os.environ['PYTHONUNBUFFERED'] = '1'
    buf_arg = 1
sys.stdout = os.fdopen(sys.stdout.fileno(), 'a+', buf_arg)
sys.stderr = os.fdopen(sys.stderr.fileno(), 'a+', buf_arg)

回答 7

是的,默认情况下启用。您可以在调用python时通过在命令行上使用-u选项禁用它。

Yes, it is enabled by default. You can disable it by using the -u option on the command line when calling python.


回答 8

您还可以使用stdbuf实用程序运行Python :

stdbuf -oL python <script>

You can also run Python with stdbuf utility:

stdbuf -oL python <script>


回答 9

在Python 3中,您可以使用Monkey补丁打印功能,以始终发送flush = True:

_orig_print = print

def print(*args, **kwargs):
    _orig_print(*args, flush=True, **kwargs)

如注释中所指出的,您可以通过以下方式将flush参数绑定到一个值来简化此操作functools.partial

print = functools.partial(print, flush=True)

In Python 3, you can monkey-patch the print function, to always send flush=True:

_orig_print = print

def print(*args, **kwargs):
    _orig_print(*args, flush=True, **kwargs)

As pointed out in a comment, you can simplify this by binding the flush parameter to a value, via functools.partial:

print = functools.partial(print, flush=True)

回答 10

您也可以使用fcntl即时更改文件标志。

fl = fcntl.fcntl(fd.fileno(), fcntl.F_GETFL)
fl |= os.O_SYNC # or os.O_DSYNC (if you don't care the file timestamp updates)
fcntl.fcntl(fd.fileno(), fcntl.F_SETFL, fl)

You can also use fcntl to change the file flags in-fly.

fl = fcntl.fcntl(fd.fileno(), fcntl.F_GETFL)
fl |= os.O_SYNC # or os.O_DSYNC (if you don't care the file timestamp updates)
fcntl.fcntl(fd.fileno(), fcntl.F_SETFL, fl)

回答 11

可以使用调用的方法 覆盖的write方法。建议的方法实现如下。sys.stdoutflush

def write_flush(args, w=stdout.write):
    w(args)
    stdout.flush()

w参数的默认值将保留原始write方法引用。 write_flush定义之后,原始文件write可能会被覆盖。

stdout.write = write_flush

该代码假定以stdout这种方式导入from sys import stdout

It is possible to override only write method of sys.stdout with one that calls flush. Suggested method implementation is below.

def write_flush(args, w=stdout.write):
    w(args)
    stdout.flush()

Default value of w argument will keep original write method reference. After write_flush is defined, the original write might be overridden.

stdout.write = write_flush

The code assumes that stdout is imported this way from sys import stdout.


回答 12

您可以创建一个无缓冲的文件,并将该文件分配给sys.stdout。

import sys 
myFile= open( "a.log", "w", 0 ) 
sys.stdout= myFile

您无法神奇地更改系统提供的标准输出;因为它是由操作系统提供给您的python程序的。

You can create an unbuffered file and assign this file to sys.stdout.

import sys 
myFile= open( "a.log", "w", 0 ) 
sys.stdout= myFile

You can’t magically change the system-supplied stdout; since it’s supplied to your python program by the OS.


回答 13

在不崩溃的情况下起作用的变体(至少在win32上; python 2.7,ipython 0.12)然后随后被调用(多次):

def DisOutBuffering():
    if sys.stdout.name == '<stdout>':
        sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)

    if sys.stderr.name == '<stderr>':
        sys.stderr = os.fdopen(sys.stderr.fileno(), 'w', 0)

Variant that works without crashing (at least on win32; python 2.7, ipython 0.12) then called subsequently (multiple times):

def DisOutBuffering():
    if sys.stdout.name == '<stdout>':
        sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)

    if sys.stderr.name == '<stderr>':
        sys.stderr = os.fdopen(sys.stderr.fileno(), 'w', 0)

回答 14

(我发表了评论,但由于某种原因迷失了。因此,再次:)

  1. 正如我注意到的那样,CPython(至少在Linux上)的行为取决于输出的位置。如果是tty,则在每个’之后都将刷新输出。\n'
    如果是管道/进程,则将其缓冲,您可以使用flush()基于基础的解决方案或上面建议的-u选项。

  2. 与输出缓冲稍微相关:
    如果您使用来遍历输入中的行

    for line in sys.stdin:

然后在CPython中for实现将收集输入一段时间,然后对一堆输入行执行循环主体。如果您的脚本要为每条输入行写输出,这可能看起来像输出缓冲,但实际上是批处理,因此,等技术都无法提供帮助。有趣的是,您在pypy中没有这种行为。为了避免这种情况,您可以使用flush()

while True: line=sys.stdin.readline()

(I’ve posted a comment, but it got lost somehow. So, again:)

  1. As I noticed, CPython (at least on Linux) behaves differently depending on where the output goes. If it goes to a tty, then the output is flushed after each ‘\n'
    If it goes to a pipe/process, then it is buffered and you can use the flush() based solutions or the -u option recommended above.

  2. Slightly related to output buffering:
    If you iterate over the lines in the input with

    for line in sys.stdin:

then the for implementation in CPython will collect the input for a while and then execute the loop body for a bunch of input lines. If your script is about to write output for each input line, this might look like output buffering but it’s actually batching, and therefore, none of the flush(), etc. techniques will help that. Interestingly, you don’t have this behaviour in pypy. To avoid this, you can use

while True: line=sys.stdin.readline()


回答 15

获得无缓冲输出的一种方法是使用sys.stderr而不是sys.stdout或简单地调用sys.stdout.flush()以显式强制发生写入。

您可以通过执行以下操作轻松重定向所有打印内容:

import sys; sys.stdout = sys.stderr
print "Hello World!"

或仅针对特定print语句进行重定向:

print >>sys.stderr, "Hello World!"

要重置标准输出,您可以执行以下操作:

sys.stdout = sys.__stdout__

One way to get unbuffered output would be to use sys.stderr instead of sys.stdout or to simply call sys.stdout.flush() to explicitly force a write to occur.

You could easily redirect everything printed by doing:

import sys; sys.stdout = sys.stderr
print "Hello World!"

Or to redirect just for a particular print statement:

print >>sys.stderr, "Hello World!"

To reset stdout you can just do:

sys.stdout = sys.__stdout__

python multiprocessing pool.map用于多个参数

问题:python multiprocessing pool.map用于多个参数

在Python多处理库中,是否存在pool.map的变体,它支持多个参数?

text = "test"
def harvester(text, case):
    X = case[0]
    text+ str(X)

if __name__ == '__main__':
    pool = multiprocessing.Pool(processes=6)
    case = RAW_DATASET
    pool.map(harvester(text,case),case, 1)
    pool.close()
    pool.join()

In the Python multiprocessing library, is there a variant of pool.map which support multiple arguments?

text = "test"
def harvester(text, case):
    X = case[0]
    text+ str(X)

if __name__ == '__main__':
    pool = multiprocessing.Pool(processes=6)
    case = RAW_DATASET
    pool.map(harvester(text,case),case, 1)
    pool.close()
    pool.join()

回答 0

答案是取决于版本和情况。JF Sebastian首先描述了最近的Python版本(从3.3开始)的最普遍答案。1它使用Pool.starmap方法,该方法接受一个参数元组序列。然后,它会自动将每个元组的参数解包,并将其传递给给定的函数:

import multiprocessing
from itertools import product

def merge_names(a, b):
    return '{} & {}'.format(a, b)

if __name__ == '__main__':
    names = ['Brown', 'Wilson', 'Bartlett', 'Rivera', 'Molloy', 'Opie']
    with multiprocessing.Pool(processes=3) as pool:
        results = pool.starmap(merge_names, product(names, repeat=2))
    print(results)

# Output: ['Brown & Brown', 'Brown & Wilson', 'Brown & Bartlett', ...

对于早期版本的Python,您需要编写一个辅助函数来显式解压缩参数。如果要使用with,则还需要编写一个包装器以变为Pool上下文管理器。(感谢muon指出这一点。)

import multiprocessing
from itertools import product
from contextlib import contextmanager

def merge_names(a, b):
    return '{} & {}'.format(a, b)

def merge_names_unpack(args):
    return merge_names(*args)

@contextmanager
def poolcontext(*args, **kwargs):
    pool = multiprocessing.Pool(*args, **kwargs)
    yield pool
    pool.terminate()

if __name__ == '__main__':
    names = ['Brown', 'Wilson', 'Bartlett', 'Rivera', 'Molloy', 'Opie']
    with poolcontext(processes=3) as pool:
        results = pool.map(merge_names_unpack, product(names, repeat=2))
    print(results)

# Output: ['Brown & Brown', 'Brown & Wilson', 'Brown & Bartlett', ...

在更简单的情况下,使用固定的第二个参数,您也可以使用partial,但仅在Python 2.7+中使用。

import multiprocessing
from functools import partial
from contextlib import contextmanager

@contextmanager
def poolcontext(*args, **kwargs):
    pool = multiprocessing.Pool(*args, **kwargs)
    yield pool
    pool.terminate()

def merge_names(a, b):
    return '{} & {}'.format(a, b)

if __name__ == '__main__':
    names = ['Brown', 'Wilson', 'Bartlett', 'Rivera', 'Molloy', 'Opie']
    with poolcontext(processes=3) as pool:
        results = pool.map(partial(merge_names, b='Sons'), names)
    print(results)

# Output: ['Brown & Sons', 'Wilson & Sons', 'Bartlett & Sons', ...

1.这在很大程度上是受他的回答启发的,而他的回答可能应该被接受。但是,由于这个问题排在了最前面,所以最好对将来的读者进行改进。

The answer to this is version- and situation-dependent. The most general answer for recent versions of Python (since 3.3) was first described below by J.F. Sebastian.1 It uses the Pool.starmap method, which accepts a sequence of argument tuples. It then automatically unpacks the arguments from each tuple and passes them to the given function:

import multiprocessing
from itertools import product

def merge_names(a, b):
    return '{} & {}'.format(a, b)

if __name__ == '__main__':
    names = ['Brown', 'Wilson', 'Bartlett', 'Rivera', 'Molloy', 'Opie']
    with multiprocessing.Pool(processes=3) as pool:
        results = pool.starmap(merge_names, product(names, repeat=2))
    print(results)

# Output: ['Brown & Brown', 'Brown & Wilson', 'Brown & Bartlett', ...

For earlier versions of Python, you’ll need to write a helper function to unpack the arguments explicitly. If you want to use with, you’ll also need to write a wrapper to turn Pool into a context manager. (Thanks to muon for pointing this out.)

import multiprocessing
from itertools import product
from contextlib import contextmanager

def merge_names(a, b):
    return '{} & {}'.format(a, b)

def merge_names_unpack(args):
    return merge_names(*args)

@contextmanager
def poolcontext(*args, **kwargs):
    pool = multiprocessing.Pool(*args, **kwargs)
    yield pool
    pool.terminate()

if __name__ == '__main__':
    names = ['Brown', 'Wilson', 'Bartlett', 'Rivera', 'Molloy', 'Opie']
    with poolcontext(processes=3) as pool:
        results = pool.map(merge_names_unpack, product(names, repeat=2))
    print(results)

# Output: ['Brown & Brown', 'Brown & Wilson', 'Brown & Bartlett', ...

In simpler cases, with a fixed second argument, you can also use partial, but only in Python 2.7+.

import multiprocessing
from functools import partial
from contextlib import contextmanager

@contextmanager
def poolcontext(*args, **kwargs):
    pool = multiprocessing.Pool(*args, **kwargs)
    yield pool
    pool.terminate()

def merge_names(a, b):
    return '{} & {}'.format(a, b)

if __name__ == '__main__':
    names = ['Brown', 'Wilson', 'Bartlett', 'Rivera', 'Molloy', 'Opie']
    with poolcontext(processes=3) as pool:
        results = pool.map(partial(merge_names, b='Sons'), names)
    print(results)

# Output: ['Brown & Sons', 'Wilson & Sons', 'Bartlett & Sons', ...

1. Much of this was inspired by his answer, which should probably have been accepted instead. But since this one is stuck at the top, it seemed best to improve it for future readers.


回答 1

是否有pool.map的变体,它支持多个参数?

Python 3.3包含pool.starmap()方法

#!/usr/bin/env python3
from functools import partial
from itertools import repeat
from multiprocessing import Pool, freeze_support

def func(a, b):
    return a + b

def main():
    a_args = [1,2,3]
    second_arg = 1
    with Pool() as pool:
        L = pool.starmap(func, [(1, 1), (2, 1), (3, 1)])
        M = pool.starmap(func, zip(a_args, repeat(second_arg)))
        N = pool.map(partial(func, b=second_arg), a_args)
        assert L == M == N

if __name__=="__main__":
    freeze_support()
    main()

对于旧版本:

#!/usr/bin/env python2
import itertools
from multiprocessing import Pool, freeze_support

def func(a, b):
    print a, b

def func_star(a_b):
    """Convert `f([1,2])` to `f(1,2)` call."""
    return func(*a_b)

def main():
    pool = Pool()
    a_args = [1,2,3]
    second_arg = 1
    pool.map(func_star, itertools.izip(a_args, itertools.repeat(second_arg)))

if __name__=="__main__":
    freeze_support()
    main()

输出量

1 1
2 1
3 1

注意此处的用法itertools.izip()itertools.repeat()用法。

由于@unutbu提到的错误,您无法functools.partial()在Python 2.6上使用或类似的功能,因此func_star()应明确定义简单的包装器函数。又见解决方法 的建议uptimebox

is there a variant of pool.map which support multiple arguments?

Python 3.3 includes pool.starmap() method:

#!/usr/bin/env python3
from functools import partial
from itertools import repeat
from multiprocessing import Pool, freeze_support

def func(a, b):
    return a + b

def main():
    a_args = [1,2,3]
    second_arg = 1
    with Pool() as pool:
        L = pool.starmap(func, [(1, 1), (2, 1), (3, 1)])
        M = pool.starmap(func, zip(a_args, repeat(second_arg)))
        N = pool.map(partial(func, b=second_arg), a_args)
        assert L == M == N

if __name__=="__main__":
    freeze_support()
    main()

For older versions:

#!/usr/bin/env python2
import itertools
from multiprocessing import Pool, freeze_support

def func(a, b):
    print a, b

def func_star(a_b):
    """Convert `f([1,2])` to `f(1,2)` call."""
    return func(*a_b)

def main():
    pool = Pool()
    a_args = [1,2,3]
    second_arg = 1
    pool.map(func_star, itertools.izip(a_args, itertools.repeat(second_arg)))

if __name__=="__main__":
    freeze_support()
    main()

Output

1 1
2 1
3 1

Notice how itertools.izip() and itertools.repeat() are used here.

Due to the bug mentioned by @unutbu you can’t use functools.partial() or similar capabilities on Python 2.6, so the simple wrapper function func_star() should be defined explicitly. See also the workaround suggested by uptimebox.


回答 2

我认为下面会更好

def multi_run_wrapper(args):
   return add(*args)
def add(x,y):
    return x+y
if __name__ == "__main__":
    from multiprocessing import Pool
    pool = Pool(4)
    results = pool.map(multi_run_wrapper,[(1,2),(2,3),(3,4)])
    print results

输出

[3, 5, 7]

I think the below will be better

def multi_run_wrapper(args):
   return add(*args)
def add(x,y):
    return x+y
if __name__ == "__main__":
    from multiprocessing import Pool
    pool = Pool(4)
    results = pool.map(multi_run_wrapper,[(1,2),(2,3),(3,4)])
    print results

output

[3, 5, 7]

回答 3

Python 3.3+pool.starmap():

from multiprocessing.dummy import Pool as ThreadPool 

def write(i, x):
    print(i, "---", x)

a = ["1","2","3"]
b = ["4","5","6"] 

pool = ThreadPool(2)
pool.starmap(write, zip(a,b)) 
pool.close() 
pool.join()

结果:

1 --- 4
2 --- 5
3 --- 6

如果您愿意,还可以zip()更多参数: zip(a,b,c,d,e)

如果您希望将常量值作为参数传递,则必须使用import itertools,然后再使用zip(itertools.repeat(constant), a)

Using Python 3.3+ with pool.starmap():

from multiprocessing.dummy import Pool as ThreadPool 

def write(i, x):
    print(i, "---", x)

a = ["1","2","3"]
b = ["4","5","6"] 

pool = ThreadPool(2)
pool.starmap(write, zip(a,b)) 
pool.close() 
pool.join()

Result:

1 --- 4
2 --- 5
3 --- 6

You can also zip() more arguments if you like: zip(a,b,c,d,e)

In case you want to have a constant value passed as an argument you have to use import itertools and then zip(itertools.repeat(constant), a) for example.


回答 4

JF Sebastian答案中了解了itertools之后,我决定进一步研究并编写一个parmap程序包,该程序包涉及python-2.7和python-3.2(以及后来的版本)上的并行化,提供mapstarmap功能,可以采用任意数量的位置参数。

安装

pip install parmap

如何并行化:

import parmap
# If you want to do:
y = [myfunction(x, argument1, argument2) for x in mylist]
# In parallel:
y = parmap.map(myfunction, mylist, argument1, argument2)

# If you want to do:
z = [myfunction(x, y, argument1, argument2) for (x,y) in mylist]
# In parallel:
z = parmap.starmap(myfunction, mylist, argument1, argument2)

# If you want to do:
listx = [1, 2, 3, 4, 5, 6]
listy = [2, 3, 4, 5, 6, 7]
param = 3.14
param2 = 42
listz = []
for (x, y) in zip(listx, listy):
        listz.append(myfunction(x, y, param1, param2))
# In parallel:
listz = parmap.starmap(myfunction, zip(listx, listy), param1, param2)

我已将parmap上传到PyPI和github存储库

例如,可以如下回答该问题:

import parmap

def harvester(case, text):
    X = case[0]
    text+ str(X)

if __name__ == "__main__":
    case = RAW_DATASET  # assuming this is an iterable
    parmap.map(harvester, case, "test", chunksize=1)

Having learnt about itertools in J.F. Sebastian answer I decided to take it a step further and write a parmap package that takes care about parallelization, offering map and starmap functions on python-2.7 and python-3.2 (and later also) that can take any number of positional arguments.

Installation

pip install parmap

How to parallelize:

import parmap
# If you want to do:
y = [myfunction(x, argument1, argument2) for x in mylist]
# In parallel:
y = parmap.map(myfunction, mylist, argument1, argument2)

# If you want to do:
z = [myfunction(x, y, argument1, argument2) for (x,y) in mylist]
# In parallel:
z = parmap.starmap(myfunction, mylist, argument1, argument2)

# If you want to do:
listx = [1, 2, 3, 4, 5, 6]
listy = [2, 3, 4, 5, 6, 7]
param = 3.14
param2 = 42
listz = []
for (x, y) in zip(listx, listy):
        listz.append(myfunction(x, y, param1, param2))
# In parallel:
listz = parmap.starmap(myfunction, zip(listx, listy), param1, param2)

I have uploaded parmap to PyPI and to a github repository.

As an example, the question can be answered as follows:

import parmap

def harvester(case, text):
    X = case[0]
    text+ str(X)

if __name__ == "__main__":
    case = RAW_DATASET  # assuming this is an iterable
    parmap.map(harvester, case, "test", chunksize=1)

回答 5

#“如何接受多个参数”。

def f1(args):
    a, b, c = args[0] , args[1] , args[2]
    return a+b+c

if __name__ == "__main__":
    import multiprocessing
    pool = multiprocessing.Pool(4) 

    result1 = pool.map(f1, [ [1,2,3] ])
    print(result1)

# “How to take multiple arguments”.

def f1(args):
    a, b, c = args[0] , args[1] , args[2]
    return a+b+c

if __name__ == "__main__":
    import multiprocessing
    pool = multiprocessing.Pool(4) 

    result1 = pool.map(f1, [ [1,2,3] ])
    print(result1)

回答 6

有一个multiprocessing名为pathos的分支(注意:使用github上的版本不需要),因为starmapmap函数镜像了python map的API,因此map可以采用多个参数。使用pathos,您通常还可以在解释器中进行多处理,而不会卡在__main__块中。经过一些轻微的更新后,Pathos即将发布,主要是转换为python3.x。

  Python 2.7.5 (default, Sep 30 2013, 20:15:49) 
  [GCC 4.2.1 (Apple Inc. build 5566)] on darwin
  Type "help", "copyright", "credits" or "license" for more information.
  >>> def func(a,b):
  ...     print a,b
  ...
  >>>
  >>> from pathos.multiprocessing import ProcessingPool    
  >>> pool = ProcessingPool(nodes=4)
  >>> pool.map(func, [1,2,3], [1,1,1])
  1 1
  2 1
  3 1
  [None, None, None]
  >>>
  >>> # also can pickle stuff like lambdas 
  >>> result = pool.map(lambda x: x**2, range(10))
  >>> result
  [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
  >>>
  >>> # also does asynchronous map
  >>> result = pool.amap(pow, [1,2,3], [4,5,6])
  >>> result.get()
  [1, 32, 729]
  >>>
  >>> # or can return a map iterator
  >>> result = pool.imap(pow, [1,2,3], [4,5,6])
  >>> result
  <processing.pool.IMapIterator object at 0x110c2ffd0>
  >>> list(result)
  [1, 32, 729]

pathos有几种方法可以使您获得的确切行为starmap

>>> def add(*x):
...   return sum(x)
... 
>>> x = [[1,2,3],[4,5,6]]
>>> import pathos
>>> import numpy as np
>>> # use ProcessPool's map and transposing the inputs
>>> pp = pathos.pools.ProcessPool()
>>> pp.map(add, *np.array(x).T)
[6, 15]
>>> # use ProcessPool's map and a lambda to apply the star
>>> pp.map(lambda x: add(*x), x)
[6, 15]
>>> # use a _ProcessPool, which has starmap
>>> _pp = pathos.pools._ProcessPool()
>>> _pp.starmap(add, x)
[6, 15]
>>> 

There’s a fork of multiprocessing called pathos (note: use the version on github) that doesn’t need starmap — the map functions mirror the API for python’s map, thus map can take multiple arguments. With pathos, you can also generally do multiprocessing in the interpreter, instead of being stuck in the __main__ block. Pathos is due for a release, after some mild updating — mostly conversion to python 3.x.

  Python 2.7.5 (default, Sep 30 2013, 20:15:49) 
  [GCC 4.2.1 (Apple Inc. build 5566)] on darwin
  Type "help", "copyright", "credits" or "license" for more information.
  >>> def func(a,b):
  ...     print a,b
  ...
  >>>
  >>> from pathos.multiprocessing import ProcessingPool    
  >>> pool = ProcessingPool(nodes=4)
  >>> pool.map(func, [1,2,3], [1,1,1])
  1 1
  2 1
  3 1
  [None, None, None]
  >>>
  >>> # also can pickle stuff like lambdas 
  >>> result = pool.map(lambda x: x**2, range(10))
  >>> result
  [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
  >>>
  >>> # also does asynchronous map
  >>> result = pool.amap(pow, [1,2,3], [4,5,6])
  >>> result.get()
  [1, 32, 729]
  >>>
  >>> # or can return a map iterator
  >>> result = pool.imap(pow, [1,2,3], [4,5,6])
  >>> result
  <processing.pool.IMapIterator object at 0x110c2ffd0>
  >>> list(result)
  [1, 32, 729]

pathos has several ways that that you can get the exact behavior of starmap.

>>> def add(*x):
...   return sum(x)
... 
>>> x = [[1,2,3],[4,5,6]]
>>> import pathos
>>> import numpy as np
>>> # use ProcessPool's map and transposing the inputs
>>> pp = pathos.pools.ProcessPool()
>>> pp.map(add, *np.array(x).T)
[6, 15]
>>> # use ProcessPool's map and a lambda to apply the star
>>> pp.map(lambda x: add(*x), x)
[6, 15]
>>> # use a _ProcessPool, which has starmap
>>> _pp = pathos.pools._ProcessPool()
>>> _pp.starmap(add, x)
[6, 15]
>>> 

回答 7

您可以使用以下两个函数,以避免为每个新函数编写包装器:

import itertools
from multiprocessing import Pool

def universal_worker(input_pair):
    function, args = input_pair
    return function(*args)

def pool_args(function, *args):
    return zip(itertools.repeat(function), zip(*args))

使用功能function与参数的清单arg_0arg_1arg_2如下:

pool = Pool(n_core)
list_model = pool.map(universal_worker, pool_args(function, arg_0, arg_1, arg_2)
pool.close()
pool.join()

You can use the following two functions so as to avoid writing a wrapper for each new function:

import itertools
from multiprocessing import Pool

def universal_worker(input_pair):
    function, args = input_pair
    return function(*args)

def pool_args(function, *args):
    return zip(itertools.repeat(function), zip(*args))

Use the function function with the lists of arguments arg_0, arg_1 and arg_2 as follows:

pool = Pool(n_core)
list_model = pool.map(universal_worker, pool_args(function, arg_0, arg_1, arg_2)
pool.close()
pool.join()

回答 8

python2的更好解决方案:

from multiprocessing import Pool
def func((i, (a, b))):
    print i, a, b
    return a + b
pool = Pool(3)
pool.map(func, [(0,(1,2)), (1,(2,3)), (2,(3, 4))])

2 3 4

1 2 3

0 1 2

出[]:

[3,5,7]

A better solution for python2:

from multiprocessing import Pool
def func((i, (a, b))):
    print i, a, b
    return a + b
pool = Pool(3)
pool.map(func, [(0,(1,2)), (1,(2,3)), (2,(3, 4))])

2 3 4

1 2 3

0 1 2

out[]:

[3, 5, 7]


回答 9

另一个简单的替代方法是将函数参数包装在一个元组中,然后再包装应该在元组中传递的参数。当处理大量数据时,这可能不是理想的。我相信它将为每个元组复制一份。

from multiprocessing import Pool

def f((a,b,c,d)):
    print a,b,c,d
    return a + b + c +d

if __name__ == '__main__':
    p = Pool(10)
    data = [(i+0,i+1,i+2,i+3) for i in xrange(10)]
    print(p.map(f, data))
    p.close()
    p.join()

以某种随机顺序给出输出:

0 1 2 3
1 2 3 4
2 3 4 5
3 4 5 6
4 5 6 7
5 6 7 8
7 8 9 10
6 7 8 9
8 9 10 11
9 10 11 12
[6, 10, 14, 18, 22, 26, 30, 34, 38, 42]

Another simple alternative is to wrap your function parameters in a tuple and then wrap the parameters that should be passed in tuples as well. This is perhaps not ideal when dealing with large pieces of data. I believe it would make copies for each tuple.

from multiprocessing import Pool

def f((a,b,c,d)):
    print a,b,c,d
    return a + b + c +d

if __name__ == '__main__':
    p = Pool(10)
    data = [(i+0,i+1,i+2,i+3) for i in xrange(10)]
    print(p.map(f, data))
    p.close()
    p.join()

Gives the output in some random order:

0 1 2 3
1 2 3 4
2 3 4 5
3 4 5 6
4 5 6 7
5 6 7 8
7 8 9 10
6 7 8 9
8 9 10 11
9 10 11 12
[6, 10, 14, 18, 22, 26, 30, 34, 38, 42]

回答 10

更好的方法是使用装饰器,而不是手动编写包装器函数。特别是当您有许多要映射的函数时,装饰器将避免为每个函数编写包装器,从而节省了时间。通常,装饰功能是不可选的,但是我们可以使用functools它来解决它。可以在这里找到更多讨论

这里的例子

def unpack_args(func):
    from functools import wraps
    @wraps(func)
    def wrapper(args):
        if isinstance(args, dict):
            return func(**args)
        else:
            return func(*args)
    return wrapper

@unpack_args
def func(x, y):
    return x + y

然后,您可以使用压缩参数映射它

np, xlist, ylist = 2, range(10), range(10)
pool = Pool(np)
res = pool.map(func, zip(xlist, ylist))
pool.close()
pool.join()

当然,您可能总是Pool.starmap在Python 3(> = 3.3)中使用其他答案。

A better way is using decorator instead of writing wrapper function by hand. Especially when you have a lot of functions to map, decorator will save your time by avoiding writing wrapper for every function. Usually a decorated function is not picklable, however we may use functools to get around it. More disscusions can be found here.

Here the example

def unpack_args(func):
    from functools import wraps
    @wraps(func)
    def wrapper(args):
        if isinstance(args, dict):
            return func(**args)
        else:
            return func(*args)
    return wrapper

@unpack_args
def func(x, y):
    return x + y

Then you may map it with zipped arguments

np, xlist, ylist = 2, range(10), range(10)
pool = Pool(np)
res = pool.map(func, zip(xlist, ylist))
pool.close()
pool.join()

Of course, you may always use Pool.starmap in Python 3 (>=3.3) as mentioned in other answers.


回答 11

另一种方法是将列表的列表传递给一个参数的例程:

import os
from multiprocessing import Pool

def task(args):
    print "PID =", os.getpid(), ", arg1 =", args[0], ", arg2 =", args[1]

pool = Pool()

pool.map(task, [
        [1,2],
        [3,4],
        [5,6],
        [7,8]
    ])

然后,可以使用自己喜欢的方法构造一个参数列表。

Another way is to pass a list of lists to a one-argument routine:

import os
from multiprocessing import Pool

def task(args):
    print "PID =", os.getpid(), ", arg1 =", args[0], ", arg2 =", args[1]

pool = Pool()

pool.map(task, [
        [1,2],
        [3,4],
        [5,6],
        [7,8]
    ])

One can than construct a list lists of arguments with one’s favorite method.


回答 12

这是另一种方法,即IMHO比提供的任何其他答案都更加简单和优雅。

该程序具有接受两个参数,将它们打印出来并打印和的功能:

import multiprocessing

def main():

    with multiprocessing.Pool(10) as pool:
        params = [ (2, 2), (3, 3), (4, 4) ]
        pool.starmap(printSum, params)
    # end with

# end function

def printSum(num1, num2):
    mySum = num1 + num2
    print('num1 = ' + str(num1) + ', num2 = ' + str(num2) + ', sum = ' + str(mySum))
# end function

if __name__ == '__main__':
    main()

输出为:

num1 = 2, num2 = 2, sum = 4
num1 = 3, num2 = 3, sum = 6
num1 = 4, num2 = 4, sum = 8

有关更多信息,请参见python文档:

https://docs.python.org/3/library/multiprocessing.html#module-multiprocessing.pool

特别要确保检查出该starmap功能。

我使用的是Python 3.6,我不确定这是否适用于较旧的Python版本

我不确定为什么在文档中没有这样一个非常简单的示例。

Here is another way to do it that IMHO is more simple and elegant than any of the other answers provided.

This program has a function that takes two parameters, prints them out and also prints the sum:

import multiprocessing

def main():

    with multiprocessing.Pool(10) as pool:
        params = [ (2, 2), (3, 3), (4, 4) ]
        pool.starmap(printSum, params)
    # end with

# end function

def printSum(num1, num2):
    mySum = num1 + num2
    print('num1 = ' + str(num1) + ', num2 = ' + str(num2) + ', sum = ' + str(mySum))
# end function

if __name__ == '__main__':
    main()

output is:

num1 = 2, num2 = 2, sum = 4
num1 = 3, num2 = 3, sum = 6
num1 = 4, num2 = 4, sum = 8

See the python docs for more info:

https://docs.python.org/3/library/multiprocessing.html#module-multiprocessing.pool

In particular be sure to check out the starmap function.

I’m using Python 3.6, I’m not sure if this will work with older Python versions

Why there is not a very straight-forward example like this in the docs, I’m not sure.


回答 13

从python 3.4.4开始,您可以使用multiprocessing.get_context()获得上下文对象以使用多个启动方法:

import multiprocessing as mp

def foo(q, h, w):
    q.put(h + ' ' + w)
    print(h + ' ' + w)

if __name__ == '__main__':
    ctx = mp.get_context('spawn')
    q = ctx.Queue()
    p = ctx.Process(target=foo, args=(q,'hello', 'world'))
    p.start()
    print(q.get())
    p.join()

或者您只需替换

pool.map(harvester(text,case),case, 1)

通过:

pool.apply_async(harvester(text,case),case, 1)

From python 3.4.4, you can use multiprocessing.get_context() to obtain a context object to use multiple start methods:

import multiprocessing as mp

def foo(q, h, w):
    q.put(h + ' ' + w)
    print(h + ' ' + w)

if __name__ == '__main__':
    ctx = mp.get_context('spawn')
    q = ctx.Queue()
    p = ctx.Process(target=foo, args=(q,'hello', 'world'))
    p.start()
    print(q.get())
    p.join()

Or you just simply replace

pool.map(harvester(text,case),case, 1)

by:

pool.apply_async(harvester(text,case),case, 1)

回答 14

这里有很多答案,但似乎没有一个提供可在任何版本上运行的Python 2/3兼容代码。如果您希望您的代码正常工作,则适用于以下任一Python版本:

# For python 2/3 compatibility, define pool context manager
# to support the 'with' statement in Python 2
if sys.version_info[0] == 2:
    from contextlib import contextmanager
    @contextmanager
    def multiprocessing_context(*args, **kwargs):
        pool = multiprocessing.Pool(*args, **kwargs)
        yield pool
        pool.terminate()
else:
    multiprocessing_context = multiprocessing.Pool

之后,您可以随意使用常规Python 3方式进行多处理。例如:

def _function_to_run_for_each(x):
       return x.lower()
with multiprocessing_context(processes=3) as pool:
    results = pool.map(_function_to_run_for_each, ['Bob', 'Sue', 'Tim'])    print(results)

将在Python 2或Python 3中工作。

There are many answers here, but none seem to provide Python 2/3 compatible code that will work on any version. If you want your code to just work, this will work for either Python version:

# For python 2/3 compatibility, define pool context manager
# to support the 'with' statement in Python 2
if sys.version_info[0] == 2:
    from contextlib import contextmanager
    @contextmanager
    def multiprocessing_context(*args, **kwargs):
        pool = multiprocessing.Pool(*args, **kwargs)
        yield pool
        pool.terminate()
else:
    multiprocessing_context = multiprocessing.Pool

After that, you can use multiprocessing the regular Python 3 way, however you like. For example:

def _function_to_run_for_each(x):
       return x.lower()
with multiprocessing_context(processes=3) as pool:
    results = pool.map(_function_to_run_for_each, ['Bob', 'Sue', 'Tim'])    print(results)

will work in Python 2 or Python 3.


回答 15

在官方文档中声明它仅支持一个可迭代的参数。在这种情况下,我喜欢使用apply_async。在您的情况下,我会这样做:

from multiprocessing import Process, Pool, Manager

text = "test"
def harvester(text, case, q = None):
 X = case[0]
 res = text+ str(X)
 if q:
  q.put(res)
 return res


def block_until(q, results_queue, until_counter=0):
 i = 0
 while i < until_counter:
  results_queue.put(q.get())
  i+=1

if __name__ == '__main__':
 pool = multiprocessing.Pool(processes=6)
 case = RAW_DATASET
 m = Manager()
 q = m.Queue()
 results_queue = m.Queue() # when it completes results will reside in this queue
 blocking_process = Process(block_until, (q, results_queue, len(case)))
 blocking_process.start()
 for c in case:
  try:
   res = pool.apply_async(harvester, (text, case, q = None))
   res.get(timeout=0.1)
  except:
   pass
 blocking_process.join()

In the official documentation states that it supports only one iterable argument. I like to use apply_async in such cases. In your case I would do:

from multiprocessing import Process, Pool, Manager

text = "test"
def harvester(text, case, q = None):
 X = case[0]
 res = text+ str(X)
 if q:
  q.put(res)
 return res


def block_until(q, results_queue, until_counter=0):
 i = 0
 while i < until_counter:
  results_queue.put(q.get())
  i+=1

if __name__ == '__main__':
 pool = multiprocessing.Pool(processes=6)
 case = RAW_DATASET
 m = Manager()
 q = m.Queue()
 results_queue = m.Queue() # when it completes results will reside in this queue
 blocking_process = Process(block_until, (q, results_queue, len(case)))
 blocking_process.start()
 for c in case:
  try:
   res = pool.apply_async(harvester, (text, case, q = None))
   res.get(timeout=0.1)
  except:
   pass
 blocking_process.join()

回答 16

text = "test"

def unpack(args):
    return args[0](*args[1:])

def harvester(text, case):
    X = case[0]
    text+ str(X)

if __name__ == '__main__':
    pool = multiprocessing.Pool(processes=6)
    case = RAW_DATASET
    # args is a list of tuples 
    # with the function to execute as the first item in each tuple
    args = [(harvester, text, c) for c in case]
    # doing it this way, we can pass any function
    # and we don't need to define a wrapper for each different function
    # if we need to use more than one
    pool.map(unpack, args)
    pool.close()
    pool.join()
text = "test"

def unpack(args):
    return args[0](*args[1:])

def harvester(text, case):
    X = case[0]
    text+ str(X)

if __name__ == '__main__':
    pool = multiprocessing.Pool(processes=6)
    case = RAW_DATASET
    # args is a list of tuples 
    # with the function to execute as the first item in each tuple
    args = [(harvester, text, c) for c in case]
    # doing it this way, we can pass any function
    # and we don't need to define a wrapper for each different function
    # if we need to use more than one
    pool.map(unpack, args)
    pool.close()
    pool.join()

回答 17

这是我用来将多个参数传递给pool.imap分支中使用的一个参数函数的例程的示例:

from multiprocessing import Pool

# Wrapper of the function to map:
class makefun:
    def __init__(self, var2):
        self.var2 = var2
    def fun(self, i):
        var2 = self.var2
        return var1[i] + var2

# Couple of variables for the example:
var1 = [1, 2, 3, 5, 6, 7, 8]
var2 = [9, 10, 11, 12]

# Open the pool:
pool = Pool(processes=2)

# Wrapper loop
for j in range(len(var2)):
    # Obtain the function to map
    pool_fun = makefun(var2[j]).fun

    # Fork loop
    for i, value in enumerate(pool.imap(pool_fun, range(len(var1))), 0):
        print(var1[i], '+' ,var2[j], '=', value)

# Close the pool
pool.close()

This is an example of the routine I use to pass multiple arguments to a one-argument function used in a pool.imap fork:

from multiprocessing import Pool

# Wrapper of the function to map:
class makefun:
    def __init__(self, var2):
        self.var2 = var2
    def fun(self, i):
        var2 = self.var2
        return var1[i] + var2

# Couple of variables for the example:
var1 = [1, 2, 3, 5, 6, 7, 8]
var2 = [9, 10, 11, 12]

# Open the pool:
pool = Pool(processes=2)

# Wrapper loop
for j in range(len(var2)):
    # Obtain the function to map
    pool_fun = makefun(var2[j]).fun

    # Fork loop
    for i, value in enumerate(pool.imap(pool_fun, range(len(var1))), 0):
        print(var1[i], '+' ,var2[j], '=', value)

# Close the pool
pool.close()

回答 18

对于python2,您可以使用此技巧

def fun(a,b):
    return a+b

pool = multiprocessing.Pool(processes=6)
b=233
pool.map(lambda x:fun(x,b),range(1000))

for python2, you can use this trick

def fun(a,b):
    return a+b

pool = multiprocessing.Pool(processes=6)
b=233
pool.map(lambda x:fun(x,b),range(1000))

获取当前时间(以毫秒为单位)在Python中?

问题:获取当前时间(以毫秒为单位)在Python中?

如何在Python中获取以毫秒为单位的当前时间?

How can I get the current time in milliseconds in Python?


回答 0

根据我上面的@samplebias的评论,这是我需要做的:

import time
millis = int(round(time.time() * 1000))
print millis

快点 谢谢大家,为您的大脑屁感到抱歉。

要重用:

import time

current_milli_time = lambda: int(round(time.time() * 1000))

然后:

>>> current_milli_time()
1378761833768

For what I needed, here’s what I did, based on @samplebias’ comment above:

import time
millis = int(round(time.time() * 1000))
print millis

Quick’n’easy. Thanks all, sorry for the brain fart.

For reuse:

import time

current_milli_time = lambda: int(round(time.time() * 1000))

Then:

>>> current_milli_time()
1378761833768

回答 1

time.time()可能只提供秒的分辨率,毫秒的首选方法是datetime

from datetime import datetime
dt = datetime.now()
dt.microsecond

time.time() may only give resolution to the second, the preferred approach for milliseconds is datetime.

from datetime import datetime
dt = datetime.now()
dt.microsecond

回答 2

def TimestampMillisec64():
    return int((datetime.datetime.utcnow() - datetime.datetime(1970, 1, 1)).total_seconds() * 1000) 
def TimestampMillisec64():
    return int((datetime.datetime.utcnow() - datetime.datetime(1970, 1, 1)).total_seconds() * 1000) 

回答 3

3.7版开始,您可以time.time_ns()用来获取从纪元开始经过的纳秒级的时间。所以你可以做

ms = time.time_ns() // 1000000 

以毫秒为单位获取时间作为整数。

From version 3.7 you can use time.time_ns() to get time as passed nano seconds from epoch. So you can do

ms = time.time_ns() // 1000000 

to get time in mili-seconds as integer.


回答 4

只是示例代码:

import time
timestamp = int(time.time()*1000.0)

输出:1534343781311

Just sample code:

import time
timestamp = int(time.time()*1000.0)

Output: 1534343781311


回答 5

另一个解决方案是可以嵌入到自己的utils.py中的函数

import time as time_ #make sure we don't override time
def millis():
    return int(round(time_.time() * 1000))

another solution is the function you can embed into your own utils.py

import time as time_ #make sure we don't override time
def millis():
    return int(round(time_.time() * 1000))

回答 6

如果您想在代码中使用一个简单的方法来返回带有datetime的毫秒数:

from datetime import datetime
from datetime import timedelta

start_time = datetime.now()

# returns the elapsed milliseconds since the start of the program
def millis():
   dt = datetime.now() - start_time
   ms = (dt.days * 24 * 60 * 60 + dt.seconds) * 1000 + dt.microseconds / 1000.0
   return ms

If you want a simple method in your code that returns the milliseconds with datetime:

from datetime import datetime
from datetime import timedelta

start_time = datetime.now()

# returns the elapsed milliseconds since the start of the program
def millis():
   dt = datetime.now() - start_time
   ms = (dt.days * 24 * 60 * 60 + dt.seconds) * 1000 + dt.microseconds / 1000.0
   return ms

回答 7

我发现以毫秒为单位获取当前UTC时间的最简单方法是:

# timeutil.py
import datetime


def get_epochtime_ms():
    return round(datetime.datetime.utcnow().timestamp() * 1000)

# sample.py
import timeutil


timeutil.get_epochtime_ms()

The simpliest way I’ve found to get the current UTC time in milliseconds is:

# timeutil.py
import datetime


def get_epochtime_ms():
    return round(datetime.datetime.utcnow().timestamp() * 1000)

# sample.py
import timeutil


timeutil.get_epochtime_ms()

回答 8

如果您担心测量经过的时间,则应使用单调时钟(python 3)。该时钟不受系统时钟更新的影响,例如,您会看到NTP查询是否调整了系统时间。

>>> import time
>>> millis = round(time.monotonic() * 1000)

它提供了以秒为单位的参考时间,可用于以后进行比较以测量经过的时间。

If you’re concerned about measuring elapsed time, you should use the monotonic clock (python 3). This clock is not affected by system clock updates like you would see if an NTP query adjusted your system time, for example.

>>> import time
>>> millis = round(time.monotonic() * 1000)

It provides a reference time in seconds that can be used to compare later to measure elapsed time.


回答 9

如果您使用我的代码(如下所示),则时间将以秒为单位,然后在十进制后为毫秒。我认为Windows和Unix之间有区别-如果有区别,请发表评论。

from time import time

x = time()
print(x)

我的结果(在Windows上)是:

1576095264.2682993

编辑:没有区别:)谢谢tc0nn

If you use my code (below), the time will appear in seconds, then, after a decimal, milliseconds. I think that there is a difference between Windows and Unix – please comment if there is.

from time import time

x = time()
print(x)

my result (on Windows) was:

1576095264.2682993

EDIT: There is no difference:) Thanks tc0nn


回答 10

这些乘以1000毫秒的乘法对于解决或使某些先决条件可接受可能是不错的选择。它可以用来填补数据库中实际上从未使用过的空白。虽然,对于需要精确定时的实际情况,它最终会失败。我不建议任何人将这种方法用于需要执行操作或在特定时间进行处理的关键任务操作。

例如:在美国,双向ping是30-80毫秒…您不能将其四舍五入并有效地使用它。

我自己的示例要求每秒执行一次任务,这意味着如果我在响应第一个任务后将其四舍五入,仍然会导致处理时间乘以每个主循环周期。最终每60秒调用一次函数。每天大约是1440 ..不太准确。

对于那些希望寻求更准确推理而不是解决从未真正使用过数据库缺口的人们来说,这只是一个想法。

These multiplications to 1000 for milliseconds may be decent for solving or making some prerequisite acceptable. It could be used to fill a gap in your database which doesn’t really ever use it. Although, for real situations which require precise timing it would ultimately fail. I wouldn’t suggest anyone use this method for mission-critical operations which require actions, or processing at specific timings.

For example: round-trip pings being 30-80ms in the USA… You couldn’t just round that up and use it efficiently.

My own example requires tasks at every second which means if I rounded up after the first tasks responded I would still incur the processing time multiplied every main loop cycle. This ended up being a total function call every 60 seconds. that’s ~1440 a day.. not too accurate.

Just a thought for people looking for more accurate reasoning beyond solving a database gap which never really uses it.


回答 11

这是使用datetime适用于Python 3 的模块的另一种解决方案。

datetime.datetime.timestamp(datetime.datetime.now())

Just another solution using the datetime module for Python 3.

datetime.datetime.timestamp(datetime.datetime.now())

如何在Matplotlib中设置图形标题和轴标签的字体大小?

问题:如何在Matplotlib中设置图形标题和轴标签的字体大小?

我正在Matplotlib中创建一个图形,如下所示:

from matplotlib import pyplot as plt

fig = plt.figure()
plt.plot(data)
fig.suptitle('test title')
plt.xlabel('xlabel')
plt.ylabel('ylabel')
fig.savefig('test.jpg')

我想为图形标题和轴标签指定字体大小。我需要所有三个字体大小都不同,所以我不需要设置全局字体大小(mpl.rcParams['font.size']=x)。如何分别设置图形标题和轴标签的字体大小?

I am creating a figure in Matplotlib like this:

from matplotlib import pyplot as plt

fig = plt.figure()
plt.plot(data)
fig.suptitle('test title')
plt.xlabel('xlabel')
plt.ylabel('ylabel')
fig.savefig('test.jpg')

I want to specify font sizes for the figure title and the axis labels. I need all three to be different font sizes, so setting a global font size (mpl.rcParams['font.size']=x) is not what I want. How do I set font sizes for the figure title and the axis labels individually?


回答 0

对付像文本功能labeltitle等接受参数相同matplotlib.text.Text。对于字体大小,您可以使用size/fontsize

from matplotlib import pyplot as plt    

fig = plt.figure()
plt.plot(data)
fig.suptitle('test title', fontsize=20)
plt.xlabel('xlabel', fontsize=18)
plt.ylabel('ylabel', fontsize=16)
fig.savefig('test.jpg')

对于全局设置titlelabel大小,mpl.rcParams包含axes.titlesizeaxes.labelsize。(来自页面):

axes.titlesize      : large   # fontsize of the axes title
axes.labelsize      : medium  # fontsize of the x any y labels

(据我所知,没有办法分别设置xy标记尺寸。)

而且我看到那axes.titlesize没有影响suptitle。我想,您需要手动设置。

Functions dealing with text like label, title, etc. accept parameters same as matplotlib.text.Text. For the font size you can use size/fontsize:

from matplotlib import pyplot as plt    

fig = plt.figure()
plt.plot(data)
fig.suptitle('test title', fontsize=20)
plt.xlabel('xlabel', fontsize=18)
plt.ylabel('ylabel', fontsize=16)
fig.savefig('test.jpg')

For globally setting title and label sizes, mpl.rcParams contains axes.titlesize and axes.labelsize. (From the page):

axes.titlesize      : large   # fontsize of the axes title
axes.labelsize      : medium  # fontsize of the x any y labels

(As far as I can see, there is no way to set x and y label sizes separately.)

And I see that axes.titlesize does not affect suptitle. I guess, you need to set that manually.


回答 1

您也可以通过rcParams字典全局执行此操作:

import matplotlib.pylab as pylab
params = {'legend.fontsize': 'x-large',
          'figure.figsize': (15, 5),
         'axes.labelsize': 'x-large',
         'axes.titlesize':'x-large',
         'xtick.labelsize':'x-large',
         'ytick.labelsize':'x-large'}
pylab.rcParams.update(params)

You can also do this globally via a rcParams dictionary:

import matplotlib.pylab as pylab
params = {'legend.fontsize': 'x-large',
          'figure.figsize': (15, 5),
         'axes.labelsize': 'x-large',
         'axes.titlesize':'x-large',
         'xtick.labelsize':'x-large',
         'ytick.labelsize':'x-large'}
pylab.rcParams.update(params)

回答 2

如果您更习惯于使用ax对象进行绘图,则可能会ax.xaxis.label.set_size()更容易记住,或者至少在ipython终端中使用tab会更容易找到。看到效果后似乎需要重新绘制操作。例如:

import matplotlib.pyplot as plt

# set up a plot with dummy data
fig, ax = plt.subplots()
x = [0, 1, 2]
y = [0, 3, 9]
ax.plot(x,y)

# title and labels, setting initial sizes
fig.suptitle('test title', fontsize=12)
ax.set_xlabel('xlabel', fontsize=10)
ax.set_ylabel('ylabel', fontsize='medium')   # relative to plt.rcParams['font.size']

# setting label sizes after creation
ax.xaxis.label.set_size(20)
plt.draw()

我不知道创建字幕后设置字幕大小的类似方法。

If you’re more used to using ax objects to do your plotting, you might find the ax.xaxis.label.set_size() easier to remember, or at least easier to find using tab in an ipython terminal. It seems to need a redraw operation after to see the effect. For example:

import matplotlib.pyplot as plt

# set up a plot with dummy data
fig, ax = plt.subplots()
x = [0, 1, 2]
y = [0, 3, 9]
ax.plot(x,y)

# title and labels, setting initial sizes
fig.suptitle('test title', fontsize=12)
ax.set_xlabel('xlabel', fontsize=10)
ax.set_ylabel('ylabel', fontsize='medium')   # relative to plt.rcParams['font.size']

# setting label sizes after creation
ax.xaxis.label.set_size(20)
plt.draw()

I don’t know of a similar way to set the suptitle size after it’s created.


回答 3

为了只修改标题的字体(而不是轴的字体),我使用了以下命令:

import matplotlib.pyplot as plt
fig = plt.Figure()
ax = fig.add_subplot(111)
ax.set_title('My Title', fontdict={'fontsize': 8, 'fontweight': 'medium'})

fontdict接受matplotlib.text.Text中的所有kwarg 。

To only modify the title’s font (and not the font of the axis) I used this:

import matplotlib.pyplot as plt
fig = plt.Figure()
ax = fig.add_subplot(111)
ax.set_title('My Title', fontdict={'fontsize': 8, 'fontweight': 'medium'})

The fontdict accepts all kwargs from matplotlib.text.Text.


回答 4

根据官方指南pylab不再建议使用。matplotlib.pyplot应该直接使用。

在全球范围内设置字体大小通过rcParams应该做

import matplotlib.pyplot as plt
plt.rcParams['axes.labelsize'] = 16
plt.rcParams['axes.titlesize'] = 16

# or

params = {'axes.labelsize': 16,
          'axes.titlesize': 16}
plt.rcParams.update(params)

# or

import matplotlib as mpl
mpl.rc('axes', labelsize=16, titlesize=16)

# or 

axes = {'labelsize': 16,
        'titlesize': 16}
mpl.rc('axes', **axes)

可以使用以下命令恢复默认值

plt.rcParams.update(plt.rcParamsDefault)

您还可以通过在matplotlib配置目录下的目录中创建样式表来完成此操作(您可以从中获取配置目录)。样式表格式为stylelibmatplotlib.get_configdir()

axes.labelsize: 16
axes.titlesize: 16

如果您有样式表,/path/to/mpl_configdir/stylelib/mystyle.mplstyle则可以通过

plt.style.use('mystyle')

# or, for a single section

with plt.style.context('mystyle'):
    # ...

您还可以创建(或修改)matplotlibrc文件共享格式

axes.labelsize = 16
axes.titlesize = 16

取决于您修改的matplotlibrc文件,这些更改将仅用于当前工作目录,具有matplotlibrc文件的所有工作目录,或具有matplotlibrc文件且没有其他matplotlibrc文件的所有工作目录。被指定。看到本节更多详细信息,定制matplotlib页面的。

rcParams可以通过找到完整的键列表plt.rcParams.keys(),但是要调整字体大小,请使用(此处引号为斜体)

  • axes.labelsizex和y标签的字体大小
  • axes.titlesize轴标题的字体大小
  • figure.titlesize图形标题的大小(Figure.suptitle()
  • xtick.labelsize刻度标签的字体大小
  • ytick.labelsize刻度标签的字体大小
  • legend.fontsize-图例的字体大小(plt.legend()fig.legend()
  • legend.title_fontsize-图例标题的字体大小,None设置为与默认轴相同。有关用法示例,请参见此答案

所有这些都接受字符串大小{'xx-small', 'x-small', 'smaller', 'small', 'medium', 'large', 'larger', 'x-large', 'xxlarge'}floatin pt。字符串大小是相对于默认字体大小定义的,该默认大小由

  • font.size文本的默认字体大小,以pts为单位。标准值为10点

此外,可以通过以下方式指定重量(尽管仅用于默认值)

  • font.weight-所使用的字体的默认粗细text.Text。接受{100, 200, 300, 400, 500, 600, 700, 800, 900}'normal'(400),'bold'(700)'lighter',和'bolder'相对于当前重量)。

Per the official guide, use of pylab is no longer recommended. matplotlib.pyplot should be used directly instead.

Globally setting font sizes via rcParams should be done with

import matplotlib.pyplot as plt
plt.rcParams['axes.labelsize'] = 16
plt.rcParams['axes.titlesize'] = 16

# or

params = {'axes.labelsize': 16,
          'axes.titlesize': 16}
plt.rcParams.update(params)

# or

import matplotlib as mpl
mpl.rc('axes', labelsize=16, titlesize=16)

# or 

axes = {'labelsize': 16,
        'titlesize': 16}
mpl.rc('axes', **axes)

The defaults can be restored using

plt.rcParams.update(plt.rcParamsDefault)

You can also do this by creating a style sheet in the stylelib directory under the matplotlib configuration directory (you can get your configuration directory from matplotlib.get_configdir()). The style sheet format is

axes.labelsize: 16
axes.titlesize: 16

If you have a style sheet at /path/to/mpl_configdir/stylelib/mystyle.mplstyle then you can use it via

plt.style.use('mystyle')

# or, for a single section

with plt.style.context('mystyle'):
    # ...

You can also create (or modify) a matplotlibrc file which shares the format

axes.labelsize = 16
axes.titlesize = 16

Depending on which matplotlibrc file you modify these changes will be used for only the current working directory, for all working directories which do not have a matplotlibrc file, or for all working directories which do not have a matplotlibrc file and where no other matplotlibrc file has been specified. See this section of the customizing matplotlib page for more details.

A complete list of the rcParams keys can be retrieved via plt.rcParams.keys(), but for adjusting font sizes you have (italics quoted from here)

  • axes.labelsizeFontsize of the x and y labels
  • axes.titlesizeFontsize of the axes title
  • figure.titlesizeSize of the figure title (Figure.suptitle())
  • xtick.labelsizeFontsize of the tick labels
  • ytick.labelsizeFontsize of the tick labels
  • legend.fontsize – Fontsize for legends (plt.legend(), fig.legend())
  • legend.title_fontsize – Fontsize for legend titles, None sets to the same as the default axes. See this answer for usage example.

all of which accept string sizes {'xx-small', 'x-small', 'smaller', 'small', 'medium', 'large', 'larger', 'x-large', 'xxlarge'} or a float in pt. The string sizes are defined relative to the default font size which is specified by

  • font.sizethe default font size for text, given in pts. 10 pt is the standard value

Additionally, the weight can be specified (though only for the default it appears) by

  • font.weight – The default weight of the font used by text.Text. Accepts {100, 200, 300, 400, 500, 600, 700, 800, 900} or 'normal' (400), 'bold' (700), 'lighter', and 'bolder' (relative with respect to current weight).

回答 5

更改字体大小的另一种方法是更改​​填充。当Python保存您的PNG时,您可以使用打开的对话框更改布局。轴之间的间距,如果需要,可以更改内边距。

An alternative solution to changing the font size is to change the padding. When Python saves your PNG, you can change the layout using the dialogue box that opens. The spacing between the axes, padding if you like can be altered at this stage.


回答 6

放在right_ax之前set_ylabel()

ax.right_ax.set_ylabel('AB scale')

Place right_ax before set_ylabel()

ax.right_ax.set_ylabel('AB scale')


回答 7

7(最佳解决方案)

 from numpy import*
 import matplotlib.pyplot as plt
 X = linspace(-pi, pi, 1000)

class Crtaj:

    def nacrtaj(self,x,y):
         self.x=x
         self.y=y
         return plt.plot (x,y,"om")

def oznaci(self):
    return plt.xlabel("x-os"), plt.ylabel("y-os"), plt.grid(b=True)

6(较差的解决方案)

from numpy import*
M = array([[3,2,3],[1,2,6]])
class AriSred(object):
    def __init__(self,m):
    self.m=m

def srednja(self):
    redovi = len(M)
    stupci = len (M[0])
    lista=[]
    a=0
    suma=0
    while a<stupci:
        for i in range (0,redovi):
            suma=suma+ M[i,a]
        lista.append(suma)
        a=a+1
        suma=0
    b=array(lista) 
    b=b/redovi
    return b



OBJ = AriSred(M)
sr = OBJ.srednja()

7 (best solution)

 from numpy import*
 import matplotlib.pyplot as plt
 X = linspace(-pi, pi, 1000)

class Crtaj:

    def nacrtaj(self,x,y):
         self.x=x
         self.y=y
         return plt.plot (x,y,"om")

def oznaci(self):
    return plt.xlabel("x-os"), plt.ylabel("y-os"), plt.grid(b=True)

6 (slightly worse solution)

from numpy import*
M = array([[3,2,3],[1,2,6]])
class AriSred(object):
    def __init__(self,m):
    self.m=m

def srednja(self):
    redovi = len(M)
    stupci = len (M[0])
    lista=[]
    a=0
    suma=0
    while a<stupci:
        for i in range (0,redovi):
            suma=suma+ M[i,a]
        lista.append(suma)
        a=a+1
        suma=0
    b=array(lista) 
    b=b/redovi
    return b



OBJ = AriSred(M)
sr = OBJ.srednja()

什么是Python鸡蛋?

问题:什么是Python鸡蛋?

我是Python的新手,只是想了解它的软件包是如何工作的。大概“蛋”是某种包装机制,但是如何快速概述它们所扮演的角色,以及可能提供有关为什么它们有用以及如何创建它们的一些信息?

I’m new to Python and am just trying to understand how its packages work. Presumably “eggs” are some sort of packaging mechanism, but what would be a quick overview of what role they play and may be some information on why they’re useful and how to create them?


回答 0

注意:鸡蛋包装已被滚轮包装取代。

.jarJava文件的概念相同,它是.zip重命名了一些元数据文件的文件.egg,用于将代码作为分发包分发。

具体来说:Python Eggs的内部结构

“ Python鸡蛋”是一种逻辑结构,体现了特定版本的Python项目的发布,包括其代码,资源和元数据。可以使用多种格式对Python鸡蛋进行物理编码,还可以开发其他格式。但是,Python鸡蛋的关键原则是它们应该是可发现的和可导入的。也就是说,Python应用程序应该有可能轻松有效地找出系统中存在的卵,并确保所需卵的内容可导入。

.egg格式非常适合于分发以及代码的轻松卸载或升级,因为该项目本质上是独立的,包含在单个目录或文件中,没有与任何其他项目的代码或资源混合在一起。它还可以同时安装一个项目的多个版本,以便各个程序可以选择他们想要使用的版本。

Note: Egg packaging has been superseded by Wheel packaging.

Same concept as a .jar file in Java, it is a .zip file with some metadata files renamed .egg, for distributing code as bundles.

Specifically: The Internal Structure of Python Eggs

A “Python egg” is a logical structure embodying the release of a specific version of a Python project, comprising its code, resources, and metadata. There are multiple formats that can be used to physically encode a Python egg, and others can be developed. However, a key principle of Python eggs is that they should be discoverable and importable. That is, it should be possible for a Python application to easily and efficiently find out what eggs are present on a system, and to ensure that the desired eggs’ contents are importable.

The .egg format is well-suited to distribution and the easy uninstallation or upgrades of code, since the project is essentially self-contained within a single directory or file, unmingled with any other projects’ code or resources. It also makes it possible to have multiple versions of a project simultaneously installed, such that individual programs can select the versions they wish to use.


回答 1

.egg文件是Python软件包的分发格式。它只是源代码发行版或Windows的替代方案exe。但是请注意,对于pure Python.egg文件是完全跨平台的。

.egg文件本身实质上是一个.zip文件。如果将扩展名更改为“ zip”,则可以看到它在存档中将包含文件夹。

另外,如果您有.egg文件,则可以使用以下文件作为软件包安装easy_install

示例:要.egg为目录创建一个文件,例如mymath它本身可能具有多个python脚本,请执行以下步骤:

# setup.py
from setuptools import setup, find_packages
setup(
    name = "mymath",
    version = "0.1",
    packages = find_packages()
    )

然后,从终端执行:

 $ python setup.py bdist_egg

这将产生很多输出,但是完成后,您会看到拥有三个新文件夹:builddistmymath.egg-info。我们唯一关心的文件夹是dist文件夹,您可以在其中找到.egg文件,mymath-0.1-py3.5.egg带有默认的python(安装)版本号(此处为3.5)

资料来源:Python库博客

The .egg file is a distribution format for Python packages. It’s just an alternative to a source code distribution or Windows exe. But note that for pure Python, the .egg file is completely cross-platform.

The .egg file itself is essentially a .zip file. If you change the extension to “zip”, you can see that it will have folders inside the archive.

Also, if you have an .egg file, you can install it as a package using easy_install

Example: To create an .egg file for a directory say mymath which itself may have several python scripts, do the following step:

# setup.py
from setuptools import setup, find_packages
setup(
    name = "mymath",
    version = "0.1",
    packages = find_packages()
    )

Then, from the terminal do:

 $ python setup.py bdist_egg

This will generate lot of outputs, but when it’s completed you’ll see that you have three new folders: build, dist, and mymath.egg-info. The only folder that we care about is the dist folder where you’ll find your .egg file, mymath-0.1-py3.5.egg with your default python (installation) version number(mine here: 3.5)

Source: Python library blog


回答 2

Python蛋是将附加信息与Python项目捆绑在一起的一种方式,它允许在运行时检查和满足项目的依赖关系,并允许项目为其他项目提供插件。有几种包含鸡蛋的二进制格式,但是最常见的是’.egg’zipfile格式,因为它是分发项目的便捷方式。所有格式都支持,包括特定于软件包的数据,项目范围的元数据,C扩展名和Python代码。

安装和使用Python egg的最简单方法是使用“简易安装” Python软件包管理器,它将为您查找,下载,构建和安装egg。您要做的就是告诉它您要使用的Python项目的名称(以及版本)。

Python鸡蛋可以与Python 2.3及更高版本一起使用,并且可以使用setuptools软件包进行构建(有关源代码,请参见Python Subversion沙箱;有关当前安装说明,请参见EasyInstall页面)。

Python Eggs的主要好处是:

  • 它们启用了诸如“轻松安装” Python软件包管理器之类的工具

  • .egg文件是Python软件包的“零安装”格式;无需构建或安装步骤,只需将它们放在PYTHONPATH或sys.path上并使用它们即可(如果使用C扩展名或数据文件,则可能需要安装运行时)

  • 它们可以包括包元数据,例如它们依赖的其他鸡蛋

  • 它们允许将“命名空间包”(仅包含其他包的包)拆分为单独的分布(例如zope。,twisted。,peak。*)包可以作为单独的鸡蛋分发,这与通常必须始终放在同一包下的普通包不同父目录。这允许将现在庞大的整体软件包作为单独的组件分发。)

  • 它们允许应用程序或库指定库的所需版本,以便您可以在导入twisted.internet之前例如require(“ Twisted-Internet> = 2.0”)。

  • 对于将扩展或插件分发到可扩展的应用程序和框架,它们是一种很好的格式(例如Trac,它从0.9b1开始使用鸡蛋作为插件),因为Egg运行时提供了简单的API来查找鸡蛋并找到其广告入口点(类似Eclipse的“扩展点”概念)。

标准化格式还会带来其他好处,类似于Java的“ jar”格式的好处。

Python eggs are a way of bundling additional information with a Python project, that allows the project’s dependencies to be checked and satisfied at runtime, as well as allowing projects to provide plugins for other projects. There are several binary formats that embody eggs, but the most common is ‘.egg’ zipfile format, because it’s a convenient one for distributing projects. All of the formats support including package-specific data, project-wide metadata, C extensions, and Python code.

The easiest way to install and use Python eggs is to use the “Easy Install” Python package manager, which will find, download, build, and install eggs for you; all you do is tell it the name (and optionally, version) of the Python project(s) you want to use.

Python eggs can be used with Python 2.3 and up, and can be built using the setuptools package (see the Python Subversion sandbox for source code, or the EasyInstall page for current installation instructions).

The primary benefits of Python Eggs are:

  • They enable tools like the “Easy Install” Python package manager

  • .egg files are a “zero installation” format for a Python package; no build or install step is required, just put them on PYTHONPATH or sys.path and use them (may require the runtime installed if C extensions or data files are used)

  • They can include package metadata, such as the other eggs they depend on

  • They allow “namespace packages” (packages that just contain other packages) to be split into separate distributions (e.g. zope., twisted., peak.* packages can be distributed as separate eggs, unlike normal packages which must always be placed under the same parent directory. This allows what are now huge monolithic packages to be distributed as separate components.)

  • They allow applications or libraries to specify the needed version of a library, so that you can e.g. require(“Twisted-Internet>=2.0”) before doing an import twisted.internet.

  • They’re a great format for distributing extensions or plugins to extensible applications and frameworks (such as Trac, which uses eggs for plugins as of 0.9b1), because the egg runtime provides simple APIs to locate eggs and find their advertised entry points (similar to Eclipse’s “extension point” concept).

There are also other benefits that may come from having a standardized format, similar to the benefits of Java’s “jar” format.


回答 3

“ Egg”是与Python相关的项目的单文件可导入分发格式。

“ Python Eggs快速指南”指出:“ Eggs是Python,而Jars是Java …”

鸡蛋实际上比罐子还要丰富。它们包含有趣的元数据,例如许可详细信息,发布依赖项等。

“Egg” is a single-file importable distribution format for Python-related projects.

“The Quick Guide to Python Eggs” notes that “Eggs are to Pythons as Jars are to Java…”

Eggs actually are richer than jars; they hold interesting metadata such as licensing details, release dependencies, etc.


如何将列表的字符串表示形式转换为列表?

问题:如何将列表的字符串表示形式转换为列表?

我想知道最简单的方法是将string类似以下的列表转换为list

x = u'[ "A","B","C" , " D"]'

即使用户在逗号之间加上空格,也要在引号内使用空格。我还需要处理以下内容:

x = ["A", "B", "C", "D"] 

在Python中。

我知道我可以使用strip()split()使用split运算符删除空格,并检查非字母。但是代码变得非常混乱。有我不知道的快速功能吗?

I was wondering what the simplest way is to convert a string list like the following to a list:

x = u'[ "A","B","C" , " D"]'

Even in case user puts spaces in between the commas, and spaces inside of the quotes. I need to handle that as well to:

x = ["A", "B", "C", "D"] 

in Python.

I know I can strip spaces with strip() and split() using the split operator and check for non alphabets. But the code was getting very kludgy. Is there a quick function that I’m not aware of?


回答 0

>>> import ast
>>> x = u'[ "A","B","C" , " D"]'
>>> x = ast.literal_eval(x)
>>> x
['A', 'B', 'C', ' D']
>>> x = [n.strip() for n in x]
>>> x
['A', 'B', 'C', 'D']

ast.literal_eval

使用ast.literal_eval,您可以安全地评估表达式节点或包含Python表达式的字符串。提供的字符串或节点只能由以下Python文字结构组成:字符串,数字,元组,列表,字典,布尔值和无。

>>> import ast
>>> x = u'[ "A","B","C" , " D"]'
>>> x = ast.literal_eval(x)
>>> x
['A', 'B', 'C', ' D']
>>> x = [n.strip() for n in x]
>>> x
['A', 'B', 'C', 'D']

ast.literal_eval:

With ast.literal_eval, you can safely evaluate an expression node or a string containing a Python expression. The string or node provided may only consist of the following Python literal structures: strings, numbers, tuples, lists, dicts, booleans, and None.


回答 1

json每当有字典的字符串列表时,该模块都是更好的解决方案。该json.loads(your_data)函数可用于将其转换为列表。

>>> import json
>>> x = u'[ "A","B","C" , " D"]'
>>> json.loads(x)
[u'A', u'B', u'C', u' D']

相似地

>>> x = u'[ "A","B","C" , {"D":"E"}]'
>>> json.loads(x)
[u'A', u'B', u'C', {u'D': u'E'}]

The json module is a better solution whenever there is a stringified list of dictionaries. The json.loads(your_data) function can be used to convert it to a list.

>>> import json
>>> x = u'[ "A","B","C" , " D"]'
>>> json.loads(x)
[u'A', u'B', u'C', u' D']

Similarly

>>> x = u'[ "A","B","C" , {"D":"E"}]'
>>> json.loads(x)
[u'A', u'B', u'C', {u'D': u'E'}]

回答 2

eval很危险-您不应该执行用户输入。

如果您使用2.6或更高版本,请使用ast而不是eval:

>>> import ast
>>> ast.literal_eval('["A","B" ,"C" ," D"]')
["A", "B", "C", " D"]

一旦有了,就可以strip了。

如果您使用的是旧版Python,则可以使用简单的正则表达式非常接近所需的内容:

>>> x='[  "A",  " B", "C","D "]'
>>> re.findall(r'"\s*([^"]*?)\s*"', x)
['A', 'B', 'C', 'D']

这不如ast解决方案好,例如,它不能正确处理字符串中的转义引号。但这很简单,不涉及危险的评估,如果您使用的是没有ast的旧Python,则可能足以满足您的目的。

The eval is dangerous – you shouldn’t execute user input.

If you have 2.6 or newer, use ast instead of eval:

>>> import ast
>>> ast.literal_eval('["A","B" ,"C" ," D"]')
["A", "B", "C", " D"]

Once you have that, strip the strings.

If you’re on an older version of Python, you can get very close to what you want with a simple regular expression:

>>> x='[  "A",  " B", "C","D "]'
>>> re.findall(r'"\s*([^"]*?)\s*"', x)
['A', 'B', 'C', 'D']

This isn’t as good as the ast solution, for example it doesn’t correctly handle escaped quotes in strings. But it’s simple, doesn’t involve a dangerous eval, and might be good enough for your purpose if you’re on an older Python without ast.


回答 3

import ast
l = ast.literal_eval('[ "A","B","C" , " D"]')
l = [i.strip() for i in l]
import ast
l = ast.literal_eval('[ "A","B","C" , " D"]')
l = [i.strip() for i in l]

回答 4

有一个快速的解决方案:

x = eval('[ "A","B","C" , " D"]')

可以通过以下方式删除列表元素中不需要的空格:

x = [x.strip() for x in eval('[ "A","B","C" , " D"]')]

There is a quick solution:

x = eval('[ "A","B","C" , " D"]')

Unwanted whitespaces in the list elements may be removed in this way:

x = [x.strip() for x in eval('[ "A","B","C" , " D"]')]

回答 5

从上面适用于基本python软件包的一些答案的启发中,我比较了一些(使用Python 3.7.3)的性能:

方法1:AST

import ast
list(map(str.strip, ast.literal_eval(u'[ "A","B","C" , " D"]')))
# ['A', 'B', 'C', 'D']

import timeit
timeit.timeit(stmt="list(map(str.strip, ast.literal_eval(u'[ \"A\",\"B\",\"C\" , \" D\"]')))", setup='import ast', number=100000)
# 1.292875313000195

方法2:JSON

import json
list(map(str.strip, json.loads(u'[ "A","B","C" , " D"]')))
# ['A', 'B', 'C', 'D']

import timeit
timeit.timeit(stmt="list(map(str.strip, json.loads(u'[ \"A\",\"B\",\"C\" , \" D\"]')))", setup='import json', number=100000)
# 0.27833264000014424

方法3:不导入

list(map(str.strip, u'[ "A","B","C" , " D"]'.strip('][').replace('"', '').split(',')))
# ['A', 'B', 'C', 'D']

import timeit
timeit.timeit(stmt="list(map(str.strip, u'[ \"A\",\"B\",\"C\" , \" D\"]'.strip('][').replace('\"', '').split(',')))", number=100000)
# 0.12935059100027502

我很失望地看到我认为可读性最差的方法是性能最好的方法。选择可读性最高的选项时要权衡考虑…对于我通常使用python的工作量类型相对于性能稍高的选项,它更重视可读性,但通常情况下,它取决于。

Inspired from some of the answers above that work with base python packages I compared the performance of a few (using Python 3.7.3):

Method 1: ast

import ast
list(map(str.strip, ast.literal_eval(u'[ "A","B","C" , " D"]')))
# ['A', 'B', 'C', 'D']

import timeit
timeit.timeit(stmt="list(map(str.strip, ast.literal_eval(u'[ \"A\",\"B\",\"C\" , \" D\"]')))", setup='import ast', number=100000)
# 1.292875313000195

Method 2: json

import json
list(map(str.strip, json.loads(u'[ "A","B","C" , " D"]')))
# ['A', 'B', 'C', 'D']

import timeit
timeit.timeit(stmt="list(map(str.strip, json.loads(u'[ \"A\",\"B\",\"C\" , \" D\"]')))", setup='import json', number=100000)
# 0.27833264000014424

Method 3: no import

list(map(str.strip, u'[ "A","B","C" , " D"]'.strip('][').replace('"', '').split(',')))
# ['A', 'B', 'C', 'D']

import timeit
timeit.timeit(stmt="list(map(str.strip, u'[ \"A\",\"B\",\"C\" , \" D\"]'.strip('][').replace('\"', '').split(',')))", number=100000)
# 0.12935059100027502

I was disappointed to see what I considered the method with the worst readability was the method with the best performance… there are tradeoffs to consider when going with the most readable option… for the type of workloads I use python for I usually value readability over a slightly more performant option, but as usual it depends.


回答 6

如果只是一维列表,则无需导入任何内容即可完成:

>>> x = u'[ "A","B","C" , " D"]'
>>> ls = x.strip('[]').replace('"', '').replace(' ', '').split(',')
>>> ls
['A', 'B', 'C', 'D']

If it’s only a one dimensional list, this can be done without importing anything:

>>> x = u'[ "A","B","C" , " D"]'
>>> ls = x.strip('[]').replace('"', '').replace(' ', '').split(',')
>>> ls
['A', 'B', 'C', 'D']

回答 7

假设所有输入都是列表,并且输入中的双引号实际上并不重要,则可以使用简单的regexp替换来完成。它有点Perl-y,但是却像魅力一样。还要注意,输出现在是unicode字符串的列表,您没有指定所需的字符串,但是对于unicode输入,这似乎很有意义。

import re
x = u'[ "A","B","C" , " D"]'
junkers = re.compile('[[" \]]')
result = junkers.sub('', x).split(',')
print result
--->  [u'A', u'B', u'C', u'D']

junkers变量包含一个我们不想使用的所有字符的正则表达式(用于速度),使用]作为字符需要一些反斜杠技巧。re.sub将所有这些字符全部替换为空,然后将结果字符串拆分为逗号。

请注意,这还会从内部条目u'[“ oh no”]’—> [u’ohno’]中删除空格。如果这不是您想要的,则需要增加正则表达式。

Assuming that all your inputs are lists and that the double quotes in the input actually don’t matter, this can be done with a simple regexp replace. It is a bit perl-y but works like a charm. Note also that the output is now a list of unicode strings, you didn’t specify that you needed that, but it seems to make sense given unicode input.

import re
x = u'[ "A","B","C" , " D"]'
junkers = re.compile('[[" \]]')
result = junkers.sub('', x).split(',')
print result
--->  [u'A', u'B', u'C', u'D']

The junkers variable contains a compiled regexp (for speed) of all characters we don’t want, using ] as a character required some backslash trickery. The re.sub replaces all these characters with nothing, and we split the resulting string at the commas.

Note that this also removes spaces from inside entries u'[“oh no”]’ —> [u’ohno’]. If this is not what you wanted, the regexp needs to be souped up a bit.


回答 8

如果您知道列表仅包含带引号的字符串,则此pyparsing示例将为您提供剥离字符串的列表(甚至保留原始Unicode-ness)。

>>> from pyparsing import *
>>> x =u'[ "A","B","C" , " D"]'
>>> LBR,RBR = map(Suppress,"[]")
>>> qs = quotedString.setParseAction(removeQuotes, lambda t: t[0].strip())
>>> qsList = LBR + delimitedList(qs) + RBR
>>> print qsList.parseString(x).asList()
[u'A', u'B', u'C', u'D']

如果你的列表可以有更多的数据类型,甚至包含列表中列出,那么你将需要一个更完整的语法-像这样一个在pyparsing wiki,它可以处理的元组,列表,整数,浮点数,和引用字符串。将适用于2.4之前的Python版本。

If you know that your lists only contain quoted strings, this pyparsing example will give you your list of stripped strings (even preserving the original Unicode-ness).

>>> from pyparsing import *
>>> x =u'[ "A","B","C" , " D"]'
>>> LBR,RBR = map(Suppress,"[]")
>>> qs = quotedString.setParseAction(removeQuotes, lambda t: t[0].strip())
>>> qsList = LBR + delimitedList(qs) + RBR
>>> print qsList.parseString(x).asList()
[u'A', u'B', u'C', u'D']

If your lists can have more datatypes, or even contain lists within lists, then you will need a more complete grammar – like this one on the pyparsing wiki, which will handle tuples, lists, ints, floats, and quoted strings. Will work with Python versions back to 2.4.


回答 9

为了进一步使用json完成@Ryan的答案,这里发布的一个非常方便的函数来转换unicode: https

例如,用双引号或单引号引起来:

>print byteify(json.loads(u'[ "A","B","C" , " D"]')
>print byteify(json.loads(u"[ 'A','B','C' , ' D']".replace('\'','"')))
['A', 'B', 'C', ' D']
['A', 'B', 'C', ' D']

To further complete @Ryan ‘s answer using json, one very convenient function to convert unicode is the one posted here: https://stackoverflow.com/a/13105359/7599285

ex with double or single quotes:

>print byteify(json.loads(u'[ "A","B","C" , " D"]')
>print byteify(json.loads(u"[ 'A','B','C' , ' D']".replace('\'','"')))
['A', 'B', 'C', ' D']
['A', 'B', 'C', ' D']

回答 10

我想用正则表达式提供一个更直观的模式解决方案。下面的函数将包含任意字符串的字符串化列表作为输入。

分步说明: 删除所有whitespacing,花括号和value_separators(前提是它们不是要提取的值的一部分,否则会使正则表达式更复杂)。然后,将清洗后的字符串用单引号或双引号引起来,并采用非空值(或奇数索引值,无论使用哪种首选项)。

def parse_strlist(sl):
import re
clean = re.sub("[\[\],\s]","",sl)
splitted = re.split("[\'\"]",clean)
values_only = [s for s in splitted if s != '']
return values_only

testsample:“ [’21’,” foo“’6’,’0’,” A“]”

I would like to provide a more intuitive patterning solution with regex. The below function takes as input a stringified list containing arbitrary strings.

Stepwise explanation: You remove all whitespacing,bracketing and value_separators (provided they are not part of the values you want to extract, else make the regex more complex). Then you split the cleaned string on single or double quotes and take the non-empty values (or odd indexed values, whatever the preference).

def parse_strlist(sl):
import re
clean = re.sub("[\[\],\s]","",sl)
splitted = re.split("[\'\"]",clean)
values_only = [s for s in splitted if s != '']
return values_only

testsample: “[’21’,”foo” ‘6’, ‘0’, ” A”]”


回答 11

并使用纯python-不导入任何库

[x for x in  x.split('[')[1].split(']')[0].split('"')[1:-1] if x not in[',',' , ',', ']]

and with pure python – not importing any libraries

[x for x in  x.split('[')[1].split(']')[0].split('"')[1:-1] if x not in[',',' , ',', ']]

回答 12

在处理存储为Pandas DataFrame的抓取数据时,您可能会遇到这样的问题。

如果值列表以文本形式出现,则此解决方案的工作方式类似于魅力。

def textToList(hashtags):
    return hashtags.strip('[]').replace('\'', '').replace(' ', '').split(',')

hashtags = "[ 'A','B','C' , ' D']"
hashtags = textToList(hashtags)

Output: ['A', 'B', 'C', 'D']

无需外部库。

You may run into such problem while dealing with scraped data stored as Pandas DataFrame.

This solution works like charm if the list of values is present as text.

def textToList(hashtags):
    return hashtags.strip('[]').replace('\'', '').replace(' ', '').split(',')

hashtags = "[ 'A','B','C' , ' D']"
hashtags = textToList(hashtags)

Output: ['A', 'B', 'C', 'D']

No external library required.


回答 13

因此,按照所有答案,我决定为最常见的方法计时:

from time import time
import re
import json


my_str = str(list(range(19)))
print(my_str)

reps = 100000

start = time()
for i in range(0, reps):
    re.findall("\w+", my_str)
print("Regex method:\t", (time() - start) / reps)

start = time()
for i in range(0, reps):
    json.loads(my_str)
print("json method:\t", (time() - start) / reps)

start = time()
for i in range(0, reps):
    ast.literal_eval(my_str)
print("ast method:\t\t", (time() - start) / reps)

start = time()
for i in range(0, reps):
    [n.strip() for n in my_str]
print("strip method:\t", (time() - start) / reps)



    regex method:    6.391477584838867e-07
    json method:     2.535374164581299e-06
    ast method:      2.4425282478332518e-05
    strip method:    4.983267784118653e-06

因此,最终正则表达式获胜!

So, following all the answers I decided to time the most common methods:

from time import time
import re
import json


my_str = str(list(range(19)))
print(my_str)

reps = 100000

start = time()
for i in range(0, reps):
    re.findall("\w+", my_str)
print("Regex method:\t", (time() - start) / reps)

start = time()
for i in range(0, reps):
    json.loads(my_str)
print("json method:\t", (time() - start) / reps)

start = time()
for i in range(0, reps):
    ast.literal_eval(my_str)
print("ast method:\t\t", (time() - start) / reps)

start = time()
for i in range(0, reps):
    [n.strip() for n in my_str]
print("strip method:\t", (time() - start) / reps)



    regex method:    6.391477584838867e-07
    json method:     2.535374164581299e-06
    ast method:      2.4425282478332518e-05
    strip method:    4.983267784118653e-06

So in the end regex wins!


回答 14

您可以通过从列表的字符串表示中切下第一个和最后符来节省.strip()fcn(请参见下面的第三行)

>>> mylist=[1,2,3,4,5,'baloney','alfalfa']
>>> strlist=str(mylist)
['1', ' 2', ' 3', ' 4', ' 5', " 'baloney'", " 'alfalfa'"]
>>> mylistfromstring=(strlist[1:-1].split(', '))
>>> mylistfromstring[3]
'4'
>>> for entry in mylistfromstring:
...     print(entry)
...     type(entry)
... 
1
<class 'str'>
2
<class 'str'>
3
<class 'str'>
4
<class 'str'>
5
<class 'str'>
'baloney'
<class 'str'>
'alfalfa'
<class 'str'>

you can save yourself the .strip() fcn by just slicing off the first and last characters from the string representation of the list (see third line below)

>>> mylist=[1,2,3,4,5,'baloney','alfalfa']
>>> strlist=str(mylist)
['1', ' 2', ' 3', ' 4', ' 5', " 'baloney'", " 'alfalfa'"]
>>> mylistfromstring=(strlist[1:-1].split(', '))
>>> mylistfromstring[3]
'4'
>>> for entry in mylistfromstring:
...     print(entry)
...     type(entry)
... 
1
<class 'str'>
2
<class 'str'>
3
<class 'str'>
4
<class 'str'>
5
<class 'str'>
'baloney'
<class 'str'>
'alfalfa'
<class 'str'>

collections.defaultdict如何工作?

问题:collections.defaultdict如何工作?

我已经阅读了python文档中的示例,但仍然无法弄清楚此方法的含义。有人可以帮忙吗?这是python文档中的两个示例

>>> from collections import defaultdict

>>> s = 'mississippi'
>>> d = defaultdict(int)
>>> for k in s:
...     d[k] += 1
...
>>> d.items()
[('i', 4), ('p', 2), ('s', 4), ('m', 1)]

>>> s = [('yellow', 1), ('blue', 2), ('yellow', 3), ('blue', 4), ('red', 1)]
>>> d = defaultdict(list)
>>> for k, v in s:
...     d[k].append(v)
...
>>> d.items()
[('blue', [2, 4]), ('red', [1]), ('yellow', [1, 3])]

参数int和目的list是什么?

I’ve read the examples in python docs, but still can’t figure out what this method means. Can somebody help? Here are two examples from the python docs

>>> from collections import defaultdict

>>> s = 'mississippi'
>>> d = defaultdict(int)
>>> for k in s:
...     d[k] += 1
...
>>> d.items()
[('i', 4), ('p', 2), ('s', 4), ('m', 1)]

and

>>> s = [('yellow', 1), ('blue', 2), ('yellow', 3), ('blue', 4), ('red', 1)]
>>> d = defaultdict(list)
>>> for k, v in s:
...     d[k].append(v)
...
>>> d.items()
[('blue', [2, 4]), ('red', [1]), ('yellow', [1, 3])]

the parameters int and list are for what?


回答 0

通常,KeyError如果您尝试使用字典中当前不存在的键来获取项,则Python字典会抛出a 。该defaultdict相反只会创建您尝试访问的任何物品(当然前提是他们还不存在)。为了创建这样的“默认”项,它调用传递给构造函数的函数对象(更确切地说,它是一个任意的“可调用”对象,其中包括函数和类型对象)。对于第一个示例,默认项是使用创建的int(),它将返回integer对象0。对于第二个示例,使用创建默认项list(),该项返回一个新的空列表对象。

Usually, a Python dictionary throws a KeyError if you try to get an item with a key that is not currently in the dictionary. The defaultdict in contrast will simply create any items that you try to access (provided of course they do not exist yet). To create such a “default” item, it calls the function object that you pass to the constructor (more precisely, it’s an arbitrary “callable” object, which includes function and type objects). For the first example, default items are created using int(), which will return the integer object 0. For the second example, default items are created using list(), which returns a new empty list object.


回答 1

defaultdict表示如果在字典中找不到键,则KeyError创建新条目而不是引发键。此新条目的类型由defaultdict的参数给出。

例如:

somedict = {}
print(somedict[3]) # KeyError

someddict = defaultdict(int)
print(someddict[3]) # print int(), thus 0

defaultdict means that if a key is not found in the dictionary, then instead of a KeyError being thrown, a new entry is created. The type of this new entry is given by the argument of defaultdict.

For example:

somedict = {}
print(somedict[3]) # KeyError

someddict = defaultdict(int)
print(someddict[3]) # print int(), thus 0

回答 2

defaultdict

“标准字典包括setdefault()方法,该方法用于检索值并在该值不存在时建立默认值。相比之下,defaultdict让调用者在初始化容器时预先指定默认值(要返回的值)。”

Doug HellmannPython标准库中通过示例定义

如何使用defaultdict

导入defaultdict

>>> from collections import defaultdict

初始化defaultdict

通过传递来初始化

作为其第一个参数(强制性)

>>> d_int = defaultdict(int)
>>> d_list = defaultdict(list)
>>> def foo():
...     return 'default value'
... 
>>> d_foo = defaultdict(foo)
>>> d_int
defaultdict(<type 'int'>, {})
>>> d_list
defaultdict(<type 'list'>, {})
>>> d_foo
defaultdict(<function foo at 0x7f34a0a69578>, {})

** kwargs作为第二个参数(可选)

>>> d_int = defaultdict(int, a=10, b=12, c=13)
>>> d_int
defaultdict(<type 'int'>, {'a': 10, 'c': 13, 'b': 12})

要么

>>> kwargs = {'a':10,'b':12,'c':13}
>>> d_int = defaultdict(int, **kwargs)
>>> d_int
defaultdict(<type 'int'>, {'a': 10, 'c': 13, 'b': 12})

如何运作

作为标准字典的子类,它可以执行所有相同的功能。

但是,如果传递未知密钥,它将返回默认值而不是错误。例如:

>>> d_int['a']
10
>>> d_int['d']
0
>>> d_int
defaultdict(<type 'int'>, {'a': 10, 'c': 13, 'b': 12, 'd': 0})

如果要更改默认值,请覆盖default_factory:

>>> d_int.default_factory = lambda: 1
>>> d_int['e']
1
>>> d_int
defaultdict(<function <lambda> at 0x7f34a0a91578>, {'a': 10, 'c': 13, 'b': 12, 'e': 1, 'd': 0})

要么

>>> def foo():
...     return 2
>>> d_int.default_factory = foo
>>> d_int['f']
2
>>> d_int
defaultdict(<function foo at 0x7f34a0a0a140>, {'a': 10, 'c': 13, 'b': 12, 'e': 1, 'd': 0, 'f': 2})

问题中的例子

例子1

由于int已作为default_factory传递,因此默认情况下,任何未知键都将返回0。

现在,当字符串在循环中传递时,它将增加d中这些字母的计数。

>>> s = 'mississippi'
>>> d = defaultdict(int)
>>> d.default_factory
<type 'int'>
>>> for k in s:
...     d[k] += 1
>>> d.items()
[('i', 4), ('p', 2), ('s', 4), ('m', 1)]
>>> d
defaultdict(<type 'int'>, {'i': 4, 'p': 2, 's': 4, 'm': 1})

例子2

由于列表已作为default_factory传递,因此默认情况下,任何未知(不存在)键都将返回[](即list)。

现在,在循环中传递元组列表时,它将在d [color]中附加值

>>> s = [('yellow', 1), ('blue', 2), ('yellow', 3), ('blue', 4), ('red', 1)]
>>> d = defaultdict(list)
>>> d.default_factory
<type 'list'>
>>> for k, v in s:
...     d[k].append(v)
>>> d.items()
[('blue', [2, 4]), ('red', [1]), ('yellow', [1, 3])]
>>> d
defaultdict(<type 'list'>, {'blue': [2, 4], 'red': [1], 'yellow': [1, 3]})

defaultdict

“The standard dictionary includes the method setdefault() for retrieving a value and establishing a default if the value does not exist. By contrast, defaultdict lets the caller specify the default(value to be returned) up front when the container is initialized.”

as defined by Doug Hellmann in The Python Standard Library by Example

How to use defaultdict

Import defaultdict

>>> from collections import defaultdict

Initialize defaultdict

Initialize it by passing

callable as its first argument(mandatory)

>>> d_int = defaultdict(int)
>>> d_list = defaultdict(list)
>>> def foo():
...     return 'default value'
... 
>>> d_foo = defaultdict(foo)
>>> d_int
defaultdict(<type 'int'>, {})
>>> d_list
defaultdict(<type 'list'>, {})
>>> d_foo
defaultdict(<function foo at 0x7f34a0a69578>, {})

**kwargs as its second argument(optional)

>>> d_int = defaultdict(int, a=10, b=12, c=13)
>>> d_int
defaultdict(<type 'int'>, {'a': 10, 'c': 13, 'b': 12})

or

>>> kwargs = {'a':10,'b':12,'c':13}
>>> d_int = defaultdict(int, **kwargs)
>>> d_int
defaultdict(<type 'int'>, {'a': 10, 'c': 13, 'b': 12})

How does it works

As is a child class of standard dictionary, it can perform all the same functions.

But in case of passing an unknown key it returns the default value instead of error. For ex:

>>> d_int['a']
10
>>> d_int['d']
0
>>> d_int
defaultdict(<type 'int'>, {'a': 10, 'c': 13, 'b': 12, 'd': 0})

In case you want to change default value overwrite default_factory:

>>> d_int.default_factory = lambda: 1
>>> d_int['e']
1
>>> d_int
defaultdict(<function <lambda> at 0x7f34a0a91578>, {'a': 10, 'c': 13, 'b': 12, 'e': 1, 'd': 0})

or

>>> def foo():
...     return 2
>>> d_int.default_factory = foo
>>> d_int['f']
2
>>> d_int
defaultdict(<function foo at 0x7f34a0a0a140>, {'a': 10, 'c': 13, 'b': 12, 'e': 1, 'd': 0, 'f': 2})

Examples in the Question

Example 1

As int has been passed as default_factory, any unknown key will return 0 by default.

Now as the string is passed in the loop, it will increase the count of those alphabets in d.

>>> s = 'mississippi'
>>> d = defaultdict(int)
>>> d.default_factory
<type 'int'>
>>> for k in s:
...     d[k] += 1
>>> d.items()
[('i', 4), ('p', 2), ('s', 4), ('m', 1)]
>>> d
defaultdict(<type 'int'>, {'i': 4, 'p': 2, 's': 4, 'm': 1})

Example 2

As a list has been passed as default_factory, any unknown(non-existent) key will return [ ](ie. list) by default.

Now as the list of tuples is passed in the loop, it will append the value in the d[color]

>>> s = [('yellow', 1), ('blue', 2), ('yellow', 3), ('blue', 4), ('red', 1)]
>>> d = defaultdict(list)
>>> d.default_factory
<type 'list'>
>>> for k, v in s:
...     d[k].append(v)
>>> d.items()
[('blue', [2, 4]), ('red', [1]), ('yellow', [1, 3])]
>>> d
defaultdict(<type 'list'>, {'blue': [2, 4], 'red': [1], 'yellow': [1, 3]})

回答 3

字典是一种方便的存储数据的方式,以便以后按名称(键)进行检索。键必须是唯一的,不可变的对象,并且通常是字符串。字典中的值可以是任何值。对于许多应用程序,值是简单的类型,例如整数和字符串。

当字典中的值是集合(列表,字典等)时,它将变得更加有趣。在这种情况下,必须在首次使用给定键时初始化值(空列表或字典)。尽管这相对容易手动完成,但是defaultdict类型可自动执行并简化此类操作。defaultdict的工作原理与普通dict完全相同,但是它使用不带任何参数并为不存在的键提供默认值的函数(“默认工厂”)进行了初始化。

defaultdict将永远不会引发KeyError。任何不存在的键都将获取默认工厂返回的值。

from collections import defaultdict
ice_cream = defaultdict(lambda: 'Vanilla')

ice_cream['Sarah'] = 'Chunky Monkey'
ice_cream['Abdul'] = 'Butter Pecan'

print(ice_cream['Sarah'])
>>>Chunky Monkey

print(ice_cream['Joe'])
>>>Vanilla

这是另一个示例,说明如何使用defaultdict如何降低复杂性

from collections import defaultdict
# Time complexity O(n^2)
def delete_nth_naive(array, n):
    ans = []
    for num in array:
        if ans.count(num) < n:
            ans.append(num)
    return ans

# Time Complexity O(n), using hash tables.
def delete_nth(array,n):
    result = []
    counts = defaultdict(int)

    for i in array:
        if counts[i] < n:
            result.append(i)
            counts[i] += 1
    return result


x = [1,2,3,1,2,1,2,3]
print(delete_nth(x, n=2))
print(delete_nth_naive(x, n=2))

总之,每当需要字典时,每个元素的值都应以默认值开头,请使用defaultdict。

Dictionaries are a convenient way to store data for later retrieval by name (key). Keys must be unique, immutable objects, and are typically strings. The values in a dictionary can be anything. For many applications, the values are simple types such as integers and strings.

It gets more interesting when the values in a dictionary are collections (lists, dicts, etc.) In this case, the value (an empty list or dict) must be initialized the first time a given key is used. While this is relatively easy to do manually, the defaultdict type automates and simplifies these kinds of operations. A defaultdict works exactly like a normal dict, but it is initialized with a function (“default factory”) that takes no arguments and provides the default value for a nonexistent key.

A defaultdict will never raise a KeyError. Any key that does not exist gets the value returned by the default factory.

from collections import defaultdict
ice_cream = defaultdict(lambda: 'Vanilla')

ice_cream['Sarah'] = 'Chunky Monkey'
ice_cream['Abdul'] = 'Butter Pecan'

print(ice_cream['Sarah'])
>>>Chunky Monkey

print(ice_cream['Joe'])
>>>Vanilla

Here is another example on How using defaultdict, we can reduce complexity

from collections import defaultdict
# Time complexity O(n^2)
def delete_nth_naive(array, n):
    ans = []
    for num in array:
        if ans.count(num) < n:
            ans.append(num)
    return ans

# Time Complexity O(n), using hash tables.
def delete_nth(array,n):
    result = []
    counts = defaultdict(int)

    for i in array:
        if counts[i] < n:
            result.append(i)
            counts[i] += 1
    return result


x = [1,2,3,1,2,1,2,3]
print(delete_nth(x, n=2))
print(delete_nth_naive(x, n=2))

In conclusion, whenever you need a dictionary, and each element’s value should start with a default value, use a defaultdict.


回答 4

这里对defaultdicts有很好的解释:http : //ludovf.net/blog/python-collections-defaultdict/

基本上,参数intlist是您传递的函数。请记住,Python接受函数名称作为参数。int默认返回0并列出当用括号调用时返回一个空列表。

在普通词典中,如果在您的示例中尝试调用d[a],则会出现错误(KeyError),因为仅存在键m,s,i和p,而键a尚未初始化。但是在defaultdict中,它将函数名称作为参数,当您尝试使用尚未初始化的键时,它只是调用您传入的函数,并将其返回值分配为新键的值。

There is a great explanation of defaultdicts here: http://ludovf.net/blog/python-collections-defaultdict/

Basically, the parameters int and list are functions that you pass. Remember that Python accepts function names as arguments. int returns 0 by default and list returns an empty list when called with parentheses.

In normal dictionaries, if in your example I try calling d[a], I will get an error (KeyError), since only keys m, s, i and p exist and key a has not been initialized. But in a defaultdict, it takes a function name as an argument, when you try to use a key that has not been initialized, it simply calls the function you passed in and assigns its return value as the value of the new key.


回答 5

由于问题是关于“它是如何工作的”,因此一些读者可能希望看到更多的螺母和螺栓。具体地说,所讨论的方法是该__missing__(key)方法。请参阅:https : //docs.python.org/2/library/collections.html#defaultdict-objects

更具体地说,此答案显示了如何以__missing__(key)实际方式使用:https : //stackoverflow.com/a/17956989/1593924

为了阐明“ callable”的含义,这是一个交互式会话(来自2.7.6,但也应在v3中工作):

>>> x = int
>>> x
<type 'int'>
>>> y = int(5)
>>> y
5
>>> z = x(5)
>>> z
5

>>> from collections import defaultdict
>>> dd = defaultdict(int)
>>> dd
defaultdict(<type 'int'>, {})
>>> dd = defaultdict(x)
>>> dd
defaultdict(<type 'int'>, {})
>>> dd['a']
0
>>> dd
defaultdict(<type 'int'>, {'a': 0})

那是defaultdict的最典型用法(除了x变量的无意义使用外)。您可以使用0作为显式默认值来执行相同的操作,但不能使用简单的值:

>>> dd2 = defaultdict(0)

Traceback (most recent call last):
  File "<pyshell#7>", line 1, in <module>
    dd2 = defaultdict(0)
TypeError: first argument must be callable

相反,下面的方法起作用了,因为它传入了一个简单的函数(它动态创建了一个不带参数的无名称函数,并且始终返回0):

>>> dd2 = defaultdict(lambda: 0)
>>> dd2
defaultdict(<function <lambda> at 0x02C4C130>, {})
>>> dd2['a']
0
>>> dd2
defaultdict(<function <lambda> at 0x02C4C130>, {'a': 0})
>>> 

并使用不同的默认值:

>>> dd3 = defaultdict(lambda: 1)
>>> dd3
defaultdict(<function <lambda> at 0x02C4C170>, {})
>>> dd3['a']
1
>>> dd3
defaultdict(<function <lambda> at 0x02C4C170>, {'a': 1})
>>> 

Since the question is about “how it works”, some readers may want to see more nuts and bolts. Specifically, the method in question is the __missing__(key) method. See: https://docs.python.org/2/library/collections.html#defaultdict-objects .

More concretely, this answer shows how to make use of __missing__(key) in a practical way: https://stackoverflow.com/a/17956989/1593924

To clarify what ‘callable’ means, here’s an interactive session (from 2.7.6 but should work in v3 too):

>>> x = int
>>> x
<type 'int'>
>>> y = int(5)
>>> y
5
>>> z = x(5)
>>> z
5

>>> from collections import defaultdict
>>> dd = defaultdict(int)
>>> dd
defaultdict(<type 'int'>, {})
>>> dd = defaultdict(x)
>>> dd
defaultdict(<type 'int'>, {})
>>> dd['a']
0
>>> dd
defaultdict(<type 'int'>, {'a': 0})

That was the most typical use of defaultdict (except for the pointless use of the x variable). You can do the same thing with 0 as the explicit default value, but not with a simple value:

>>> dd2 = defaultdict(0)

Traceback (most recent call last):
  File "<pyshell#7>", line 1, in <module>
    dd2 = defaultdict(0)
TypeError: first argument must be callable

Instead, the following works because it passes in a simple function (it creates on the fly a nameless function which takes no arguments and always returns 0):

>>> dd2 = defaultdict(lambda: 0)
>>> dd2
defaultdict(<function <lambda> at 0x02C4C130>, {})
>>> dd2['a']
0
>>> dd2
defaultdict(<function <lambda> at 0x02C4C130>, {'a': 0})
>>> 

And with a different default value:

>>> dd3 = defaultdict(lambda: 1)
>>> dd3
defaultdict(<function <lambda> at 0x02C4C170>, {})
>>> dd3['a']
1
>>> dd3
defaultdict(<function <lambda> at 0x02C4C170>, {'a': 1})
>>> 

回答 6

我自己的2¢:您还可以将defaultdict子类化:

class MyDict(defaultdict):
    def __missing__(self, key):
        value = [None, None]
        self[key] = value
        return value

对于非常复杂的情况,这可能会派上用场。

My own 2¢: you can also subclass defaultdict:

class MyDict(defaultdict):
    def __missing__(self, key):
        value = [None, None]
        self[key] = value
        return value

This could come in handy for very complex cases.


回答 7

的行为defaultdict可以使用dict.setdefault代替轻松地模仿d[key]在每个调用中。

换句话说,代码:

from collections import defaultdict

d = defaultdict(list)

print(d['key'])                        # empty list []
d['key'].append(1)                     # adding constant 1 to the list
print(d['key'])                        # list containing the constant [1]

等效于:

d = dict()

print(d.setdefault('key', list()))     # empty list []
d.setdefault('key', list()).append(1)  # adding constant 1 to the list
print(d.setdefault('key', list()))     # list containing the constant [1]

唯一的区别是,使用defaultdict,列表构造函数仅被调用一次,而使用dict.setdefault列表构造函数则被更频繁地调用(但如果确实需要,可以重写代码来避免这种情况)。

有人可能会认为有性能方面的考虑,但是这个话题是一个雷区。 这篇文章显示,例如,使用defaultdict不会带来很大的性能提升。

IMO,defaultdict是一个集合,它给代码增加的混乱多于好处。对我没用,但其他人可能会有所不同。

The behavior of defaultdict can be easily mimicked using dict.setdefault instead of d[key] in every call.

In other words, the code:

from collections import defaultdict

d = defaultdict(list)

print(d['key'])                        # empty list []
d['key'].append(1)                     # adding constant 1 to the list
print(d['key'])                        # list containing the constant [1]

is equivalent to:

d = dict()

print(d.setdefault('key', list()))     # empty list []
d.setdefault('key', list()).append(1)  # adding constant 1 to the list
print(d.setdefault('key', list()))     # list containing the constant [1]

The only difference is that, using defaultdict, the list constructor is called only once, and using dict.setdefault the list constructor is called more often (but the code may be rewriten to avoid this, if really needed).

Some may argue there is a performance consideration, but this topic is a minefield. This post shows there isn’t a big performance gain in using defaultdict, for example.

IMO, defaultdict is a collection that adds more confusion than benefits to the code. Useless for me, but others may think different.


回答 8

defaultdict工具是Python的collections类中的容器。它与通常的字典(dict)容器相似,但有一个区别:值字段的数据类型是在初始化时指定的。

例如:

from collections import defaultdict

d = defaultdict(list)

d['python'].append("awesome")

d['something-else'].append("not relevant")

d['python'].append("language")

for i in d.items():

    print i

打印:

('python', ['awesome', 'language'])
('something-else', ['not relevant'])

The defaultdict tool is a container in the collections class of Python. It’s similar to the usual dictionary (dict) container, but it has one difference: The value fields’ data type is specified upon initialization.

For example:

from collections import defaultdict

d = defaultdict(list)

d['python'].append("awesome")

d['something-else'].append("not relevant")

d['python'].append("language")

for i in d.items():

    print i

This prints:

('python', ['awesome', 'language'])
('something-else', ['not relevant'])

回答 9

我认为最好用它来代替switch case语句。假设我们有一个switch case语句,如下所示:

option = 1

switch(option) {
    case 1: print '1st option'
    case 2: print '2nd option'
    case 3: print '3rd option'
    default: return 'No such option'
}

switchpython中没有case语句。我们可以使用来达到相同的目的defaultdict

from collections import defaultdict

def default_value(): return "Default Value"
dd = defaultdict(default_value)

dd[1] = '1st option'
dd[2] = '2nd option'
dd[3] = '3rd option'

print(dd[4])    
print(dd[5])    
print(dd[3])

它打印:

Default Value
Default Value
3rd option

在上面的代码片段dd中没有按键4或5,因此它打印出了我们在辅助函数中配置的默认值。这比原始字典好得多,在原始字典中,KeyError如果不存在键,则抛出a 。由此可见,defaultdict很像switch case语句,我们可以避免复杂的情况。if-elif-elif-else块。

这个网站给我留下了深刻的印象。

>>> from collections import defaultdict
>>> food_list = 'spam spam spam spam spam spam eggs spam'.split()
>>> food_count = defaultdict(int) # default value of int is 0
>>> for food in food_list:
...     food_count[food] += 1 # increment element's value by 1
...
defaultdict(<type 'int'>, {'eggs': 1, 'spam': 7})
>>>

如果我们尝试访问除以外的任何其他项目eggsspam则计数为0。

I think its best used in place of a switch case statement. Imagine if we have a switch case statement as below:

option = 1

switch(option) {
    case 1: print '1st option'
    case 2: print '2nd option'
    case 3: print '3rd option'
    default: return 'No such option'
}

There is no switch case statements available in python. We can achieve the same by using defaultdict.

from collections import defaultdict

def default_value(): return "Default Value"
dd = defaultdict(default_value)

dd[1] = '1st option'
dd[2] = '2nd option'
dd[3] = '3rd option'

print(dd[4])    
print(dd[5])    
print(dd[3])

It prints:

Default Value
Default Value
3rd option

In the above snippet dd has no keys 4 or 5 and hence it prints out a default value which we have configured in a helper function. This is quite nicer than a raw dictionary where a KeyError is thrown if key is not present. From this it is evident that defaultdict more like a switch case statement where we can avoid a complicated if-elif-elif-else blocks.

One more good example that impressed me a lot from this site is:

>>> from collections import defaultdict
>>> food_list = 'spam spam spam spam spam spam eggs spam'.split()
>>> food_count = defaultdict(int) # default value of int is 0
>>> for food in food_list:
...     food_count[food] += 1 # increment element's value by 1
...
defaultdict(<type 'int'>, {'eggs': 1, 'spam': 7})
>>>

If we try to access any items other than eggs and spam we will get a count of 0.


回答 10

如果不使用defaultdict,则可能会为看不见的键分配新值,但无法对其进行修改。例如:

import collections
d = collections.defaultdict(int)
for i in range(10):
  d[i] += i
print(d)
# Output: defaultdict(<class 'int'>, {0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9})

import collections
d = {}
for i in range(10):
  d[i] += i
print(d)
# Output: Traceback (most recent call last): File "python", line 4, in <module> KeyError: 0

Without defaultdict, you can probably assign new values to unseen keys but you cannot modify it. For example:

import collections
d = collections.defaultdict(int)
for i in range(10):
  d[i] += i
print(d)
# Output: defaultdict(<class 'int'>, {0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9})

import collections
d = {}
for i in range(10):
  d[i] += i
print(d)
# Output: Traceback (most recent call last): File "python", line 4, in <module> KeyError: 0

回答 11

好吧,在以下情况下,defaultdict也会引发keyerror:

    from collections import defaultdict
    d = defaultdict()
    print(d[3]) #raises keyerror

始终记得将参数传递给defaultdict,例如defaultdict(int)。

Well, defaultdict can also raise keyerror in the following case:

    from collections import defaultdict
    d = defaultdict()
    print(d[3]) #raises keyerror

Always remember to give argument to the defaultdict like defaultdict(int).


回答 12

标准字典包含setdefault()方法,该方法用于检索值并在该值不存在时建立默认值。相比之下,defaultdict允许调用方在初始化容器时预先指定默认值。

import collections

def default_factory():
    return 'default value'

d = collections.defaultdict(default_factory, foo='bar')
print 'd:', d
print 'foo =>', d['foo']
print 'bar =>', d['bar']

只要所有键都具有相同的默认值,此方法就可以很好地工作。如果默认值是用于聚合或累积值的类型(例如列表,集合甚至int),则它特别有用。标准库文档包括使用这种方式使用defaultdict的几个示例。

$ python collections_defaultdict.py

d: defaultdict(<function default_factory at 0x100468c80>, {'foo': 'bar'})
foo => bar
bar => default value

The standard dictionary includes the method setdefault() for retrieving a value and establishing a default if the value does not exist. By contrast, defaultdict lets the caller specify the default up front when the container is initialized.

import collections

def default_factory():
    return 'default value'

d = collections.defaultdict(default_factory, foo='bar')
print 'd:', d
print 'foo =>', d['foo']
print 'bar =>', d['bar']

This works well as long as it is appropriate for all keys to have the same default. It can be especially useful if the default is a type used for aggregating or accumulating values, such as a list, set, or even int. The standard library documentation includes several examples of using defaultdict this way.

$ python collections_defaultdict.py

d: defaultdict(<function default_factory at 0x100468c80>, {'foo': 'bar'})
foo => bar
bar => default value

回答 13

简而言之:

defaultdict(int) -参数int表示值将为int类型。

defaultdict(list) -参数列表指示值将是列表类型。

In short:

defaultdict(int) – the argument int indicates that the values will be int type.

defaultdict(list) – the argument list indicates that the values will be list type.


回答 14

文档和说明几乎是不言自明的:

http://docs.python.org/library/collections.html#collections.defaultdict

作为参数传递的类型函数(int / str等)用于为字典中不存在该键的任何给定键初始化默认值。

The documentation and the explanation are pretty much self-explanatory:

http://docs.python.org/library/collections.html#collections.defaultdict

The type function(int/str etc.) passed as an argument is used to initialize a default value for any given key where the key is not present in the dict.


想要一个简单的argparse示例:1个参数,3个结果

问题:想要一个简单的argparse示例:1个参数,3个结果

文档argparse Python模块,而优秀的我敢肯定,是太多了我的小初学者的大脑现在掌握。我不需要在命令行上进行数学运算,也不需要在屏幕上设置格式行或更改选项字符。我要做的只是“如果arg是A,如果以上都不显示帮助并退出,则B这样做。”

The documentation for the argparse python module, while excellent I’m sure, is too much for my tiny beginner brain to grasp right now. I don’t need to do math on the command line or meddle with formatting lines on the screen or change option characters. All I want to do is “If arg is A, do this, if B do that, if none of the above show help and quit”.


回答 0

我对原始问题的理解是双重的。首先,就最简单的argparse示例而言,令我惊讶的是我在这里没有看到它。当然,简而言之,这几乎没有任何功能,而且开销很大,但这可能会让您入门。

import argparse

parser = argparse.ArgumentParser()
parser.add_argument("a")
args = parser.parse_args()

if args.a == 'magic.name':
    print 'You nailed it!'

但是,现在需要此位置参数。如果在调用该程序时将其遗漏,则会出现有关缺少参数的错误。这将我引到原始问题的第二部分。马特·威尔基(Matt Wilkie)似乎想要一个不带命名标签(–option标签)的可选参数。我的建议是修改上面的代码,如下所示:

...
parser.add_argument("a", nargs='?', default="check_string_for_empty")
...
if args.a == 'check_string_for_empty':
    print 'I can tell that no argument was given and I can deal with that here.'
elif args.a == 'magic.name':
    print 'You nailed it!'
else:
    print args.a

可能会有一个更优雅的解决方案,但这是可行的并且是极简主义的。

My understanding of the original question is two-fold. First, in terms of the simplest possible argparse example, I’m surprised that I haven’t seen it here. Of course, to be dead-simple, it’s also all overhead with little power, but it might get you started.

import argparse

parser = argparse.ArgumentParser()
parser.add_argument("a")
args = parser.parse_args()

if args.a == 'magic.name':
    print 'You nailed it!'

But this positional argument is now required. If you leave it out when invoking this program, you’ll get an error about missing arguments. This leads me to the second part of the original question. Matt Wilkie seems to want a single optional argument without a named label (the –option labels). My suggestion would be to modify the code above as follows:

...
parser.add_argument("a", nargs='?', default="check_string_for_empty")
...
if args.a == 'check_string_for_empty':
    print 'I can tell that no argument was given and I can deal with that here.'
elif args.a == 'magic.name':
    print 'You nailed it!'
else:
    print args.a

There may well be a more elegant solution, but this works and is minimalist.


回答 1

这是我的处理方式argparse(带有多个args):

parser = argparse.ArgumentParser(description='Description of your program')
parser.add_argument('-f','--foo', help='Description for foo argument', required=True)
parser.add_argument('-b','--bar', help='Description for bar argument', required=True)
args = vars(parser.parse_args())

args 将是包含参数的字典:

if args['foo'] == 'Hello':
    # code here

if args['bar'] == 'World':
    # code here

在您的情况下,只需添加一个参数即可。

Here’s the way I do it with argparse (with multiple args):

parser = argparse.ArgumentParser(description='Description of your program')
parser.add_argument('-f','--foo', help='Description for foo argument', required=True)
parser.add_argument('-b','--bar', help='Description for bar argument', required=True)
args = vars(parser.parse_args())

args will be a dictionary containing the arguments:

if args['foo'] == 'Hello':
    # code here

if args['bar'] == 'World':
    # code here

In your case simply add only one argument.


回答 2

argparse文档相当不错,但省略了一些可能并不明显的有用细节。(@Diego Navarro已经提到了其中一些内容,但是我将尝试对他的回答进行一些扩展。)基本用法如下:

parser = argparse.ArgumentParser()
parser.add_argument('-f', '--my-foo', default='foobar')
parser.add_argument('-b', '--bar-value', default=3.14)
args = parser.parse_args()

您从中获得的对象parse_args()是“命名空间”对象:该对象的成员变量以命令行参数命名。该Namespace对象是您访问参数和与之关联的值的方式:

args = parser.parse_args()
print args.my_foo
print args.bar_value

(请注意,argparse在命名变量时,请在参数名称中用下划线替换“-”。)

在许多情况下,您可能希望仅将参数用作没有值的标志。您可以像这样在argparse中添加它们:

parser.add_argument('--foo', action='store_true')
parser.add_argument('--no-foo', action='store_false')

上面的代码将分别创建名称为’foo’的True变量和’no_foo’的False变量:

if (args.foo):
    print "foo is true"

if (args.no_foo is False):
    print "nofoo is false"

还请注意,添加参数时可以使用“ required”选项:

parser.add_argument('-o', '--output', required=True)

这样,如果您在命令行中忽略此参数,argparse则会告诉您它丢失了,并停止执行脚本。

最后,请注意,可以使用vars函数创建参数的dict结构,如果这样会使您的生活更轻松。

args = parser.parse_args()
argsdict = vars(args)
print argsdict['my_foo']
print argsdict['bar_value']

如您所见,vars返回一个dict,其参数名称为键,其值为er值。

您可以执行许多其他选择和操作,但这应该涵盖最基本,最常见的使用情况。

The argparse documentation is reasonably good but leaves out a few useful details which might not be obvious. (@Diego Navarro already mentioned some of this but I’ll try to expand on his answer slightly.) Basic usage is as follows:

parser = argparse.ArgumentParser()
parser.add_argument('-f', '--my-foo', default='foobar')
parser.add_argument('-b', '--bar-value', default=3.14)
args = parser.parse_args()

The object you get back from parse_args() is a ‘Namespace’ object: An object whose member variables are named after your command-line arguments. The Namespace object is how you access your arguments and the values associated with them:

args = parser.parse_args()
print args.my_foo
print args.bar_value

(Note that argparse replaces ‘-‘ in your argument names with underscores when naming the variables.)

In many situations you may wish to use arguments simply as flags which take no value. You can add those in argparse like this:

parser.add_argument('--foo', action='store_true')
parser.add_argument('--no-foo', action='store_false')

The above will create variables named ‘foo’ with value True, and ‘no_foo’ with value False, respectively:

if (args.foo):
    print "foo is true"

if (args.no_foo is False):
    print "nofoo is false"

Note also that you can use the “required” option when adding an argument:

parser.add_argument('-o', '--output', required=True)

That way if you omit this argument at the command line argparse will tell you it’s missing and stop execution of your script.

Finally, note that it’s possible to create a dict structure of your arguments using the vars function, if that makes life easier for you.

args = parser.parse_args()
argsdict = vars(args)
print argsdict['my_foo']
print argsdict['bar_value']

As you can see, vars returns a dict with your argument names as keys and their values as, er, values.

There are lots of other options and things you can do, but this should cover the most essential, common usage scenarios.


回答 3

Matt正在询问argparse中的位置参数,我同意在这方面缺少Python文档。在约20个奇数页中,没有一个完整的示例显示解析和使用位置参数

这里的其他答案均未显示位置参数的完整示例,因此,这是一个完整的示例:

# tested with python 2.7.1
import argparse

parser = argparse.ArgumentParser(description="An argparse example")

parser.add_argument('action', help='The action to take (e.g. install, remove, etc.)')
parser.add_argument('foo-bar', help='Hyphens are cumbersome in positional arguments')

args = parser.parse_args()

if args.action == "install":
    print("You asked for installation")
else:
    print("You asked for something other than installation")

# The following do not work:
# print(args.foo-bar)
# print(args.foo_bar)

# But this works:
print(getattr(args, 'foo-bar'))

让我失望的是argparse会将命名参数“ –foo-bar”转换为“ foo_bar”,但是名为“ foo-bar”的位置参数保持为“ foo-bar”,这使得如何处理在您的程序中使用它。

请注意,在我的示例结尾处的两行-这两行都无法获取foo-bar位置参数的值。第一个显然是错误的(这是一个算术表达式args.foo减去bar),但是第二个也不起作用:

AttributeError: 'Namespace' object has no attribute 'foo_bar'

如果要使用该foo-bar属性,则必须使用getattr,如我的示例的最后一行所示。疯狂的是,如果您试图dest=foo_bar将属性名称更改为更易于访问的名称,则会收到一个非常奇怪的错误消息:

ValueError: dest supplied twice for positional argument

上面的示例运行方式如下:

$ python test.py
usage: test.py [-h] action foo-bar
test.py: error: too few arguments

$ python test.py -h
usage: test.py [-h] action foo-bar

An argparse example

positional arguments:
  action      The action to take (e.g. install, remove, etc.)
  foo-bar     Hyphens are cumbersome in positional arguments

optional arguments:
  -h, --help  show this help message and exit

$ python test.py install foo
You asked for installation
foo

Matt is asking about positional parameters in argparse, and I agree that the Python documentation is lacking on this aspect. There’s not a single, complete example in the ~20 odd pages that shows both parsing and using positional parameters.

None of the other answers here show a complete example of positional parameters, either, so here’s a complete example:

# tested with python 2.7.1
import argparse

parser = argparse.ArgumentParser(description="An argparse example")

parser.add_argument('action', help='The action to take (e.g. install, remove, etc.)')
parser.add_argument('foo-bar', help='Hyphens are cumbersome in positional arguments')

args = parser.parse_args()

if args.action == "install":
    print("You asked for installation")
else:
    print("You asked for something other than installation")

# The following do not work:
# print(args.foo-bar)
# print(args.foo_bar)

# But this works:
print(getattr(args, 'foo-bar'))

The thing that threw me off is that argparse will convert the named argument “–foo-bar” into “foo_bar”, but a positional parameter named “foo-bar” stays as “foo-bar”, making it less obvious how to use it in your program.

Notice the two lines near the end of my example — neither of those will work to get the value of the foo-bar positional param. The first one is obviously wrong (it’s an arithmetic expression args.foo minus bar), but the second one doesn’t work either:

AttributeError: 'Namespace' object has no attribute 'foo_bar'

If you want to use the foo-bar attribute, you must use getattr, as seen in the last line of my example. What’s crazy is that if you tried to use dest=foo_bar to change the property name to something that’s easier to access, you’d get a really bizarre error message:

ValueError: dest supplied twice for positional argument

Here’s how the example above runs:

$ python test.py
usage: test.py [-h] action foo-bar
test.py: error: too few arguments

$ python test.py -h
usage: test.py [-h] action foo-bar

An argparse example

positional arguments:
  action      The action to take (e.g. install, remove, etc.)
  foo-bar     Hyphens are cumbersome in positional arguments

optional arguments:
  -h, --help  show this help message and exit

$ python test.py install foo
You asked for installation
foo

回答 4

另一个摘要的介绍,受本文启发。

import argparse

# define functions, classes, etc.

# executes when your script is called from the command-line
if __name__ == "__main__":

    parser = argparse.ArgumentParser()
    #
    # define each option with: parser.add_argument
    #
    args = parser.parse_args() # automatically looks at sys.argv
    #
    # access results with: args.argumentName
    #

参数是由以下组合定义的:

parser.add_argument( 'name', options... )              # positional argument
parser.add_argument( '-x', options... )                # single-char flag
parser.add_argument( '-x', '--long-name', options... ) # flag with long name

常见选项有:

  • help:该参数的描述--help
  • 默认:如果省略arg的默认值。
  • 输入:如果您期望a floatint(否则为str)。
  • dest:为标志命名(例如'-x', '--long-name', dest='longName')。
    注意:默认情况下--long-name使用args.long_name
  • 动作:对某些参数的特殊处理
    • store_true, store_false用于布尔参数
      '--foo', action='store_true' => args.foo == True
    • store_const与选项一起使用const
      '--foo', action='store_const', const=42 => args.foo == 42
    • count用于重复的选项,例如./myscript.py -vv
      '-v', action='count' => args.v == 2
    • append用于重复的选项,例如./myscript.py --foo 1 --foo 2
      '--foo', action='append' => args.foo == ['1', '2']
  • required:如果需要标志,或者不需要位置参数。
  • nargs:用于捕获N args的标志
    ./myscript.py --foo a b => args.foo = ['a', 'b']
  • 选择:限制可能的输入(指定为字符串列表,如果为,则指定为int type=int)。

Yet another summary introduction, inspired by this post.

import argparse

# define functions, classes, etc.

# executes when your script is called from the command-line
if __name__ == "__main__":

    parser = argparse.ArgumentParser()
    #
    # define each option with: parser.add_argument
    #
    args = parser.parse_args() # automatically looks at sys.argv
    #
    # access results with: args.argumentName
    #

Arguments are defined with combinations of the following:

parser.add_argument( 'name', options... )              # positional argument
parser.add_argument( '-x', options... )                # single-char flag
parser.add_argument( '-x', '--long-name', options... ) # flag with long name

Common options are:

  • help: description for this arg when --help is used.
  • default: default value if the arg is omitted.
  • type: if you expect a float or int (otherwise is str).
  • dest: give a different name to a flag (e.g. '-x', '--long-name', dest='longName').
    Note: by default --long-name is accessed with args.long_name
  • action: for special handling of certain arguments
    • store_true, store_false: for boolean args
      '--foo', action='store_true' => args.foo == True
    • store_const: to be used with option const
      '--foo', action='store_const', const=42 => args.foo == 42
    • count: for repeated options, as in ./myscript.py -vv
      '-v', action='count' => args.v == 2
    • append: for repeated options, as in ./myscript.py --foo 1 --foo 2
      '--foo', action='append' => args.foo == ['1', '2']
  • required: if a flag is required, or a positional argument is not.
  • nargs: for a flag to capture N args
    ./myscript.py --foo a b => args.foo = ['a', 'b']
  • choices: to restrict possible inputs (specify as list of strings, or ints if type=int).

回答 5

注意Argparse教程Python的HOWTO文档。它从最基本的示例开始,例如以下示例:

import argparse
parser = argparse.ArgumentParser()
parser.add_argument("square", type=int,
                    help="display a square of a given number")
args = parser.parse_args()
print(args.square**2)

并发展到基本程度较低的水平。

有一个带有预定义选项的示例,例如:

import argparse
parser = argparse.ArgumentParser()
parser.add_argument("square", type=int,
                    help="display a square of a given number")
parser.add_argument("-v", "--verbosity", type=int, choices=[0, 1, 2],
                    help="increase output verbosity")
args = parser.parse_args()
answer = args.square**2
if args.verbosity == 2:
    print("the square of {} equals {}".format(args.square, answer))
elif args.verbosity == 1:
    print("{}^2 == {}".format(args.square, answer))
else:
    print(answer)

Note the Argparse Tutorial in Python HOWTOs. It starts from most basic examples, like this one:

import argparse
parser = argparse.ArgumentParser()
parser.add_argument("square", type=int,
                    help="display a square of a given number")
args = parser.parse_args()
print(args.square**2)

and progresses to less basic ones.

There is an example with predefined choice for an option, like what is asked:

import argparse
parser = argparse.ArgumentParser()
parser.add_argument("square", type=int,
                    help="display a square of a given number")
parser.add_argument("-v", "--verbosity", type=int, choices=[0, 1, 2],
                    help="increase output verbosity")
args = parser.parse_args()
answer = args.square**2
if args.verbosity == 2:
    print("the square of {} equals {}".format(args.square, answer))
elif args.verbosity == 1:
    print("{}^2 == {}".format(args.square, answer))
else:
    print(answer)

回答 6

这主要是由于@DMH而使我在学习项目中想到的…

演示代码:

import argparse

def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('-f', '--flag', action='store_true', default=False)  # can 'store_false' for no-xxx flags
    parser.add_argument('-r', '--reqd', required=True)
    parser.add_argument('-o', '--opt', default='fallback')
    parser.add_argument('arg', nargs='*') # use '+' for 1 or more args (instead of 0 or more)
    parsed = parser.parse_args()
    # NOTE: args with '-' have it replaced with '_'
    print('Result:',  vars(parsed))
    print('parsed.reqd:', parsed.reqd)

if __name__ == "__main__":
    main()

这可能已经发展并且可以在线获得:command-line.py

用于锻炼此代码的脚本:command-line-demo.sh

Here’s what I came up with in my learning project thanks mainly to @DMH…

Demo code:

import argparse

def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('-f', '--flag', action='store_true', default=False)  # can 'store_false' for no-xxx flags
    parser.add_argument('-r', '--reqd', required=True)
    parser.add_argument('-o', '--opt', default='fallback')
    parser.add_argument('arg', nargs='*') # use '+' for 1 or more args (instead of 0 or more)
    parsed = parser.parse_args()
    # NOTE: args with '-' have it replaced with '_'
    print('Result:',  vars(parsed))
    print('parsed.reqd:', parsed.reqd)

if __name__ == "__main__":
    main()

This may have evolved and is available online: command-line.py

Script to give this code a workout: command-line-demo.sh


回答 7

您也可以使用placargparse)。

作为奖励,它会生成简洁的帮助说明-参见下文。

示例脚本:

#!/usr/bin/env python3
def main(
    arg: ('Argument with two possible values', 'positional', None, None, ['A', 'B'])
):
    """General help for application"""
    if arg == 'A':
        print("Argument has value A")
    elif arg == 'B':
        print("Argument has value B")

if __name__ == '__main__':
    import plac
    plac.call(main)

输出示例:

没有提供参数- example.py

usage: example.py [-h] {A,B}
example.py: error: the following arguments are required: arg

提供了意外的参数- example.py C

usage: example.py [-h] {A,B}
example.py: error: argument arg: invalid choice: 'C' (choose from 'A', 'B')

提供的正确参数- example.py A

Argument has value A

完整的帮助菜单(自动生成)- example.py -h

usage: example.py [-h] {A,B}

General help for application

positional arguments:
  {A,B}       Argument with two possible values

optional arguments:
  -h, --help  show this help message and exit

简短说明:

参数名称通常等于参数名称(arg)。

arg参数之后的元组注释具有以下含义:

  • 说明(Argument with two possible values
  • 参数类型-“标志”,“选项”或“位置”(positional)之一
  • 缩写(None
  • 参数值的类型-例如 浮点数,字符串(None
  • 限制选择集(['A', 'B']

说明文件:

要了解有关使用plac的更多信息,请查看其出色的文档:

Plac:轻松解析命令行

You could also use plac (a wrapper around argparse).

As a bonus it generates neat help instructions – see below.

Example script:

#!/usr/bin/env python3
def main(
    arg: ('Argument with two possible values', 'positional', None, None, ['A', 'B'])
):
    """General help for application"""
    if arg == 'A':
        print("Argument has value A")
    elif arg == 'B':
        print("Argument has value B")

if __name__ == '__main__':
    import plac
    plac.call(main)

Example output:

No arguments supplied – example.py:

usage: example.py [-h] {A,B}
example.py: error: the following arguments are required: arg

Unexpected argument supplied – example.py C:

usage: example.py [-h] {A,B}
example.py: error: argument arg: invalid choice: 'C' (choose from 'A', 'B')

Correct argument supplied – example.py A :

Argument has value A

Full help menu (generated automatically) – example.py -h:

usage: example.py [-h] {A,B}

General help for application

positional arguments:
  {A,B}       Argument with two possible values

optional arguments:
  -h, --help  show this help message and exit

Short explanation:

The name of the argument usually equals the parameter name (arg).

The tuple annotation after arg parameter has the following meaning:

  • Description (Argument with two possible values)
  • Type of argument – one of ‘flag’, ‘option’ or ‘positional’ (positional)
  • Abbreviation (None)
  • Type of argument value – eg. float, string (None)
  • Restricted set of choices (['A', 'B'])

Documentation:

To learn more about using plac check out its great documentation:

Plac: Parsing the Command Line the Easy Way


回答 8

除了其他人所说的:

我通常喜欢使用’dest’参数指定变量名,然后使用’globals()。update()’将这些变量放入全局命名空间中。

用法:

$ python script.py -i "Hello, World!"

码:

...
parser.add_argument('-i', '--input', ..., dest='inputted_variable',...)
globals().update(vars(parser.parse_args()))
...
print(inputted_variable) # Prints "Hello, World!"

To add to what others have stated:

I usually like to use the ‘dest’ parameter to specify a variable name and then use ‘globals().update()’ to put those variables in the global namespace.

Usage:

$ python script.py -i "Hello, World!"

Code:

...
parser.add_argument('-i', '--input', ..., dest='inputted_variable',...)
globals().update(vars(parser.parse_args()))
...
print(inputted_variable) # Prints "Hello, World!"

回答 9

使用argparse并修改’-h’/’–help’开关以显示自己的个人代码帮助说明的一种非常简单的方法是将默认帮助设置为False,您还可以根据需要添加尽可能多的其他.add_arguments :

import argparse

parser = argparse.ArgumentParser(add_help=False)

parser.add_argument('-h', '--help', action='help',
                help='To run this script please provide two arguments')
parser.parse_args()

运行:python test.py -h

输出:

usage: test.py [-h]

optional arguments:
  -h, --help  To run this script please provide two arguments

A really simple way to use argparse and amend the ‘-h’/ ‘–help’ switches to display your own personal code help instructions is to set the default help to False, you can also add as many additional .add_arguments as you like:

import argparse

parser = argparse.ArgumentParser(add_help=False)

parser.add_argument('-h', '--help', action='help',
                help='To run this script please provide two arguments')
parser.parse_args()

Run: python test.py -h

Output:

usage: test.py [-h]

optional arguments:
  -h, --help  To run this script please provide two arguments

回答 10

最简单的答案!

PS写argparse文件的人是愚蠢的

python代码:

import argparse
parser = argparse.ArgumentParser(description='')
parser.add_argument('--o_dct_fname',type=str)
parser.add_argument('--tp',type=str)
parser.add_argument('--new_res_set',type=int)
args = parser.parse_args()
o_dct_fname = args.o_dct_fname
tp = args.tp
new_res_set = args.new_res_set

运行代码

python produce_result.py --o_dct_fname o_dct --tp father_child --new_res_set 1

The simplest answer!

P.S. the one who wrote the document of argparse is foolish

python code:

import argparse
parser = argparse.ArgumentParser(description='')
parser.add_argument('--o_dct_fname',type=str)
parser.add_argument('--tp',type=str)
parser.add_argument('--new_res_set',type=int)
args = parser.parse_args()
o_dct_fname = args.o_dct_fname
tp = args.tp
new_res_set = args.new_res_set

running code

python produce_result.py --o_dct_fname o_dct --tp father_child --new_res_set 1

如何使用NumPy计算欧几里得距离?

问题:如何使用NumPy计算欧几里得距离?

我在3D中有两点:

(xa, ya, za)
(xb, yb, zb)

我想计算距离:

dist = sqrt((xa-xb)^2 + (ya-yb)^2 + (za-zb)^2)

使用NumPy或一般使用Python的最佳方法是什么?我有:

import numpy
a = numpy.array((xa ,ya, za))
b = numpy.array((xb, yb, zb))

I have two points in 3D:

(xa, ya, za)
(xb, yb, zb)

And I want to calculate the distance:

dist = sqrt((xa-xb)^2 + (ya-yb)^2 + (za-zb)^2)

What’s the best way to do this with NumPy, or with Python in general? I have:

import numpy
a = numpy.array((xa ,ya, za))
b = numpy.array((xb, yb, zb))

回答 0

用途numpy.linalg.norm

dist = numpy.linalg.norm(a-b)

您可以在“数据挖掘导论”中找到其背后的理论

这是有效的,因为欧几里得距离l2范数,并且numpy.linalg.norm 中ord参数的默认值为2。

enter image description here

Use numpy.linalg.norm:

dist = numpy.linalg.norm(a-b)

You can find the theory behind this in Introduction to Data Mining

This works because Euclidean distance is l2 norm and the default value of ord parameter in numpy.linalg.norm is 2.

enter image description here


回答 1

SciPy中有一个功能。称为欧几里得

例:

from scipy.spatial import distance
a = (1, 2, 3)
b = (4, 5, 6)
dst = distance.euclidean(a, b)

There’s a function for that in SciPy. It’s called Euclidean.

Example:

from scipy.spatial import distance
a = (1, 2, 3)
b = (4, 5, 6)
dst = distance.euclidean(a, b)

回答 2

对于有兴趣一次计算多个距离的任何人,我已经使用perfplot(我的一个小项目)进行了一些比较。

第一个建议是组织数据,使数组具有维(3, n)(并且显然是C连续的)。如果添加在连续的第一个维度发生,事情是更快,它没有太大的关系,如果您使用sqrt-sumaxis=0linalg.normaxis=0,或

a_min_b = a - b
numpy.sqrt(numpy.einsum('ij,ij->j', a_min_b, a_min_b))

这是最快的变体。(实际上也只适用于一行。)

您在第二个轴上进行汇总的变体axis=1都慢得多。

在此处输入图片说明


复制剧情的代码:

import numpy
import perfplot
from scipy.spatial import distance


def linalg_norm(data):
    a, b = data[0]
    return numpy.linalg.norm(a - b, axis=1)


def linalg_norm_T(data):
    a, b = data[1]
    return numpy.linalg.norm(a - b, axis=0)


def sqrt_sum(data):
    a, b = data[0]
    return numpy.sqrt(numpy.sum((a - b) ** 2, axis=1))


def sqrt_sum_T(data):
    a, b = data[1]
    return numpy.sqrt(numpy.sum((a - b) ** 2, axis=0))


def scipy_distance(data):
    a, b = data[0]
    return list(map(distance.euclidean, a, b))


def sqrt_einsum(data):
    a, b = data[0]
    a_min_b = a - b
    return numpy.sqrt(numpy.einsum("ij,ij->i", a_min_b, a_min_b))


def sqrt_einsum_T(data):
    a, b = data[1]
    a_min_b = a - b
    return numpy.sqrt(numpy.einsum("ij,ij->j", a_min_b, a_min_b))


def setup(n):
    a = numpy.random.rand(n, 3)
    b = numpy.random.rand(n, 3)
    out0 = numpy.array([a, b])
    out1 = numpy.array([a.T, b.T])
    return out0, out1


perfplot.save(
    "norm.png",
    setup=setup,
    n_range=[2 ** k for k in range(22)],
    kernels=[
        linalg_norm,
        linalg_norm_T,
        scipy_distance,
        sqrt_sum,
        sqrt_sum_T,
        sqrt_einsum,
        sqrt_einsum_T,
    ],
    logx=True,
    logy=True,
    xlabel="len(x), len(y)",
)

For anyone interested in computing multiple distances at once, I’ve done a little comparison using perfplot (a small project of mine).

The first advice is to organize your data such that the arrays have dimension (3, n) (and are C-contiguous obviously). If adding happens in the contiguous first dimension, things are faster, and it doesn’t matter too much if you use sqrt-sum with axis=0, linalg.norm with axis=0, or

a_min_b = a - b
numpy.sqrt(numpy.einsum('ij,ij->j', a_min_b, a_min_b))

which is, by a slight margin, the fastest variant. (That actually holds true for just one row as well.)

The variants where you sum up over the second axis, axis=1, are all substantially slower.

enter image description here


Code to reproduce the plot:

import numpy
import perfplot
from scipy.spatial import distance


def linalg_norm(data):
    a, b = data[0]
    return numpy.linalg.norm(a - b, axis=1)


def linalg_norm_T(data):
    a, b = data[1]
    return numpy.linalg.norm(a - b, axis=0)


def sqrt_sum(data):
    a, b = data[0]
    return numpy.sqrt(numpy.sum((a - b) ** 2, axis=1))


def sqrt_sum_T(data):
    a, b = data[1]
    return numpy.sqrt(numpy.sum((a - b) ** 2, axis=0))


def scipy_distance(data):
    a, b = data[0]
    return list(map(distance.euclidean, a, b))


def sqrt_einsum(data):
    a, b = data[0]
    a_min_b = a - b
    return numpy.sqrt(numpy.einsum("ij,ij->i", a_min_b, a_min_b))


def sqrt_einsum_T(data):
    a, b = data[1]
    a_min_b = a - b
    return numpy.sqrt(numpy.einsum("ij,ij->j", a_min_b, a_min_b))


def setup(n):
    a = numpy.random.rand(n, 3)
    b = numpy.random.rand(n, 3)
    out0 = numpy.array([a, b])
    out1 = numpy.array([a.T, b.T])
    return out0, out1


perfplot.save(
    "norm.png",
    setup=setup,
    n_range=[2 ** k for k in range(22)],
    kernels=[
        linalg_norm,
        linalg_norm_T,
        scipy_distance,
        sqrt_sum,
        sqrt_sum_T,
        sqrt_einsum,
        sqrt_einsum_T,
    ],
    logx=True,
    logy=True,
    xlabel="len(x), len(y)",
)

回答 3

我想用各种性能说明来解释简单答案。np.linalg.norm可能会做比您需要的更多的工作:

dist = numpy.linalg.norm(a-b)

首先-该功能的目的是工作在一个列表,并返回所有的值,例如到距离比较pA的点的集合sP

sP = set(points)
pA = point
distances = np.linalg.norm(sP - pA, ord=2, axis=1.)  # 'distances' is a list

记住几件事:

  • Python函数调用非常昂贵。
  • [常规] Python不缓存名称查找。

所以

def distance(pointA, pointB):
    dist = np.linalg.norm(pointA - pointB)
    return dist

没有看起来那么天真。

>>> dis.dis(distance)
  2           0 LOAD_GLOBAL              0 (np)
              2 LOAD_ATTR                1 (linalg)
              4 LOAD_ATTR                2 (norm)
              6 LOAD_FAST                0 (pointA)
              8 LOAD_FAST                1 (pointB)
             10 BINARY_SUBTRACT
             12 CALL_FUNCTION            1
             14 STORE_FAST               2 (dist)

  3          16 LOAD_FAST                2 (dist)
             18 RETURN_VALUE

首先,每次调用时,我们都必须对“ np”进行全局查找,对“ linalg”进行有范围的查找,对“ norm”进行有范围的查找,以及仅调用的开销该函数就相当于数十个python。说明。

最后,我们浪费了两个操作来存储结果并重新加载以返回结果…

改进的第一步:加快查找速度,跳过商店

def distance(pointA, pointB, _norm=np.linalg.norm):
    return _norm(pointA - pointB)

我们得到了更加简化:

>>> dis.dis(distance)
  2           0 LOAD_FAST                2 (_norm)
              2 LOAD_FAST                0 (pointA)
              4 LOAD_FAST                1 (pointB)
              6 BINARY_SUBTRACT
              8 CALL_FUNCTION            1
             10 RETURN_VALUE

但是,函数调用开销仍然需要完成一些工作。而且,您需要进行基准测试以确定您自己做数学是否会更好:

def distance(pointA, pointB):
    return (
        ((pointA.x - pointB.x) ** 2) +
        ((pointA.y - pointB.y) ** 2) +
        ((pointA.z - pointB.z) ** 2)
    ) ** 0.5  # fast sqrt

在某些平台上,**0.5速度比math.sqrt。你的旅费可能会改变。

****高级性能说明。

为什么要计算距离?如果唯一的目的是显示它,

 print("The target is %.2fm away" % (distance(a, b)))

向前走。但是,如果您要比较距离,进行范围检查等,我想添加一些有用的性能观察。

让我们采取两种情况:按距离排序或将列表筛选为满足范围约束的项目。

# Ultra naive implementations. Hold onto your hat.

def sort_things_by_distance(origin, things):
    return things.sort(key=lambda thing: distance(origin, thing))

def in_range(origin, range, things):
    things_in_range = []
    for thing in things:
        if distance(origin, thing) <= range:
            things_in_range.append(thing)

我们需要记住的第一件事是我们正在使用毕达哥拉斯来计算距离(dist = sqrt(x^2 + y^2 + z^2)),因此我们进行了很多sqrt通话。数学101:

dist = root ( x^2 + y^2 + z^2 )
:.
dist^2 = x^2 + y^2 + z^2
and
sq(N) < sq(M) iff M > N
and
sq(N) > sq(M) iff N > M
and
sq(N) = sq(M) iff N == M

简而言之:直到我们实际需要以X而不是X ^ 2为单位的距离,我们才能消除计算中最困难的部分。

# Still naive, but much faster.

def distance_sq(left, right):
    """ Returns the square of the distance between left and right. """
    return (
        ((left.x - right.x) ** 2) +
        ((left.y - right.y) ** 2) +
        ((left.z - right.z) ** 2)
    )

def sort_things_by_distance(origin, things):
    return things.sort(key=lambda thing: distance_sq(origin, thing))

def in_range(origin, range, things):
    things_in_range = []

    # Remember that sqrt(N)**2 == N, so if we square
    # range, we don't need to root the distances.
    range_sq = range**2

    for thing in things:
        if distance_sq(origin, thing) <= range_sq:
            things_in_range.append(thing)

太好了,这两个函数不再需要任何昂贵的平方根。这样会更快。我们还可以通过将in_range转换为生成器来改进它:

def in_range(origin, range, things):
    range_sq = range**2
    yield from (thing for thing in things
                if distance_sq(origin, thing) <= range_sq)

如果您正在执行以下操作,则这尤其有好处:

if any(in_range(origin, max_dist, things)):
    ...

但是,如果接下来要做的事情需要一段距离,

for nearby in in_range(origin, walking_distance, hotdog_stands):
    print("%s %.2fm" % (nearby.name, distance(origin, nearby)))

考虑产生元组:

def in_range_with_dist_sq(origin, range, things):
    range_sq = range**2
    for thing in things:
        dist_sq = distance_sq(origin, thing)
        if dist_sq <= range_sq: yield (thing, dist_sq)

如果您可以进行范围检查(“找到在X附近且在Y Nm之内的东西”,因为您不必再​​次计算距离),这将特别有用。

但是,如果我们要搜索的清单很大,那things又有很多不值得考虑的地方怎么办?

实际上有一个非常简单的优化:

def in_range_all_the_things(origin, range, things):
    range_sq = range**2
    for thing in things:
        dist_sq = (origin.x - thing.x) ** 2
        if dist_sq <= range_sq:
            dist_sq += (origin.y - thing.y) ** 2
            if dist_sq <= range_sq:
                dist_sq += (origin.z - thing.z) ** 2
                if dist_sq <= range_sq:
                    yield thing

这是否有用将取决于“事物”的大小。

def in_range_all_the_things(origin, range, things):
    range_sq = range**2
    if len(things) >= 4096:
        for thing in things:
            dist_sq = (origin.x - thing.x) ** 2
            if dist_sq <= range_sq:
                dist_sq += (origin.y - thing.y) ** 2
                if dist_sq <= range_sq:
                    dist_sq += (origin.z - thing.z) ** 2
                    if dist_sq <= range_sq:
                        yield thing
    elif len(things) > 32:
        for things in things:
            dist_sq = (origin.x - thing.x) ** 2
            if dist_sq <= range_sq:
                dist_sq += (origin.y - thing.y) ** 2 + (origin.z - thing.z) ** 2
                if dist_sq <= range_sq:
                    yield thing
    else:
        ... just calculate distance and range-check it ...

再次考虑产生dist_sq。然后我们的热狗示例变为:

# Chaining generators
info = in_range_with_dist_sq(origin, walking_distance, hotdog_stands)
info = (stand, dist_sq**0.5 for stand, dist_sq in info)
for stand, dist in info:
    print("%s %.2fm" % (stand, dist))

I want to expound on the simple answer with various performance notes. np.linalg.norm will do perhaps more than you need:

dist = numpy.linalg.norm(a-b)

Firstly – this function is designed to work over a list and return all of the values, e.g. to compare the distance from pA to the set of points sP:

sP = set(points)
pA = point
distances = np.linalg.norm(sP - pA, ord=2, axis=1.)  # 'distances' is a list

Remember several things:

  • Python function calls are expensive.
  • [Regular] Python doesn’t cache name lookups.

So

def distance(pointA, pointB):
    dist = np.linalg.norm(pointA - pointB)
    return dist

isn’t as innocent as it looks.

>>> dis.dis(distance)
  2           0 LOAD_GLOBAL              0 (np)
              2 LOAD_ATTR                1 (linalg)
              4 LOAD_ATTR                2 (norm)
              6 LOAD_FAST                0 (pointA)
              8 LOAD_FAST                1 (pointB)
             10 BINARY_SUBTRACT
             12 CALL_FUNCTION            1
             14 STORE_FAST               2 (dist)

  3          16 LOAD_FAST                2 (dist)
             18 RETURN_VALUE

Firstly – every time we call it, we have to do a global lookup for “np”, a scoped lookup for “linalg” and a scoped lookup for “norm”, and the overhead of merely calling the function can equate to dozens of python instructions.

Lastly, we wasted two operations on to store the result and reload it for return…

First pass at improvement: make the lookup faster, skip the store

def distance(pointA, pointB, _norm=np.linalg.norm):
    return _norm(pointA - pointB)

We get the far more streamlined:

>>> dis.dis(distance)
  2           0 LOAD_FAST                2 (_norm)
              2 LOAD_FAST                0 (pointA)
              4 LOAD_FAST                1 (pointB)
              6 BINARY_SUBTRACT
              8 CALL_FUNCTION            1
             10 RETURN_VALUE

The function call overhead still amounts to some work, though. And you’ll want to do benchmarks to determine whether you might be better doing the math yourself:

def distance(pointA, pointB):
    return (
        ((pointA.x - pointB.x) ** 2) +
        ((pointA.y - pointB.y) ** 2) +
        ((pointA.z - pointB.z) ** 2)
    ) ** 0.5  # fast sqrt

On some platforms, **0.5 is faster than math.sqrt. Your mileage may vary.

**** Advanced performance notes.

Why are you calculating distance? If the sole purpose is to display it,

 print("The target is %.2fm away" % (distance(a, b)))

move along. But if you’re comparing distances, doing range checks, etc., I’d like to add some useful performance observations.

Let’s take two cases: sorting by distance or culling a list to items that meet a range constraint.

# Ultra naive implementations. Hold onto your hat.

def sort_things_by_distance(origin, things):
    return things.sort(key=lambda thing: distance(origin, thing))

def in_range(origin, range, things):
    things_in_range = []
    for thing in things:
        if distance(origin, thing) <= range:
            things_in_range.append(thing)

The first thing we need to remember is that we are using Pythagoras to calculate the distance (dist = sqrt(x^2 + y^2 + z^2)) so we’re making a lot of sqrt calls. Math 101:

dist = root ( x^2 + y^2 + z^2 )
:.
dist^2 = x^2 + y^2 + z^2
and
sq(N) < sq(M) iff M > N
and
sq(N) > sq(M) iff N > M
and
sq(N) = sq(M) iff N == M

In short: until we actually require the distance in a unit of X rather than X^2, we can eliminate the hardest part of the calculations.

# Still naive, but much faster.

def distance_sq(left, right):
    """ Returns the square of the distance between left and right. """
    return (
        ((left.x - right.x) ** 2) +
        ((left.y - right.y) ** 2) +
        ((left.z - right.z) ** 2)
    )

def sort_things_by_distance(origin, things):
    return things.sort(key=lambda thing: distance_sq(origin, thing))

def in_range(origin, range, things):
    things_in_range = []

    # Remember that sqrt(N)**2 == N, so if we square
    # range, we don't need to root the distances.
    range_sq = range**2

    for thing in things:
        if distance_sq(origin, thing) <= range_sq:
            things_in_range.append(thing)

Great, both functions no-longer do any expensive square roots. That’ll be much faster. We can also improve in_range by converting it to a generator:

def in_range(origin, range, things):
    range_sq = range**2
    yield from (thing for thing in things
                if distance_sq(origin, thing) <= range_sq)

This especially has benefits if you are doing something like:

if any(in_range(origin, max_dist, things)):
    ...

But if the very next thing you are going to do requires a distance,

for nearby in in_range(origin, walking_distance, hotdog_stands):
    print("%s %.2fm" % (nearby.name, distance(origin, nearby)))

consider yielding tuples:

def in_range_with_dist_sq(origin, range, things):
    range_sq = range**2
    for thing in things:
        dist_sq = distance_sq(origin, thing)
        if dist_sq <= range_sq: yield (thing, dist_sq)

This can be especially useful if you might chain range checks (‘find things that are near X and within Nm of Y’, since you don’t have to calculate the distance again).

But what about if we’re searching a really large list of things and we anticipate a lot of them not being worth consideration?

There is actually a very simple optimization:

def in_range_all_the_things(origin, range, things):
    range_sq = range**2
    for thing in things:
        dist_sq = (origin.x - thing.x) ** 2
        if dist_sq <= range_sq:
            dist_sq += (origin.y - thing.y) ** 2
            if dist_sq <= range_sq:
                dist_sq += (origin.z - thing.z) ** 2
                if dist_sq <= range_sq:
                    yield thing

Whether this is useful will depend on the size of ‘things’.

def in_range_all_the_things(origin, range, things):
    range_sq = range**2
    if len(things) >= 4096:
        for thing in things:
            dist_sq = (origin.x - thing.x) ** 2
            if dist_sq <= range_sq:
                dist_sq += (origin.y - thing.y) ** 2
                if dist_sq <= range_sq:
                    dist_sq += (origin.z - thing.z) ** 2
                    if dist_sq <= range_sq:
                        yield thing
    elif len(things) > 32:
        for things in things:
            dist_sq = (origin.x - thing.x) ** 2
            if dist_sq <= range_sq:
                dist_sq += (origin.y - thing.y) ** 2 + (origin.z - thing.z) ** 2
                if dist_sq <= range_sq:
                    yield thing
    else:
        ... just calculate distance and range-check it ...

And again, consider yielding the dist_sq. Our hotdog example then becomes:

# Chaining generators
info = in_range_with_dist_sq(origin, walking_distance, hotdog_stands)
info = (stand, dist_sq**0.5 for stand, dist_sq in info)
for stand, dist in info:
    print("%s %.2fm" % (stand, dist))

回答 4

此问题解决方法的另一个实例:

def dist(x,y):   
    return numpy.sqrt(numpy.sum((x-y)**2))

a = numpy.array((xa,ya,za))
b = numpy.array((xb,yb,zb))
dist_a_b = dist(a,b)

Another instance of this problem solving method:

def dist(x,y):   
    return numpy.sqrt(numpy.sum((x-y)**2))

a = numpy.array((xa,ya,za))
b = numpy.array((xb,yb,zb))
dist_a_b = dist(a,b)

回答 5

从开始Python 3.8math模块直接提供dist函数,该函数返回两点之间的欧几里得距离(以元组或坐标列表形式给出):

from math import dist

dist((1, 2, 6), (-2, 3, 2)) # 5.0990195135927845

如果您正在使用列表:

dist([1, 2, 6], [-2, 3, 2]) # 5.0990195135927845

Starting Python 3.8, the math module directly provides the dist function, which returns the euclidean distance between two points (given as tuples or lists of coordinates):

from math import dist

dist((1, 2, 6), (-2, 3, 2)) # 5.0990195135927845

And if you’re working with lists:

dist([1, 2, 6], [-2, 3, 2]) # 5.0990195135927845

回答 6

可以像下面这样完成。我不知道它有多快,但是它没有使用NumPy。

from math import sqrt
a = (1, 2, 3) # Data point 1
b = (4, 5, 6) # Data point 2
print sqrt(sum( (a - b)**2 for a, b in zip(a, b)))

It can be done like the following. I don’t know how fast it is, but it’s not using NumPy.

from math import sqrt
a = (1, 2, 3) # Data point 1
b = (4, 5, 6) # Data point 2
print sqrt(sum( (a - b)**2 for a, b in zip(a, b)))

回答 7

我在matplotlib.mlab中找到了一个“ dist”函数,但我认为它并不方便。

我将其发布在这里仅供参考。

import numpy as np
import matplotlib as plt

a = np.array([1, 2, 3])
b = np.array([2, 3, 4])

# Distance between a and b
dis = plt.mlab.dist(a, b)

I find a ‘dist’ function in matplotlib.mlab, but I don’t think it’s handy enough.

I’m posting it here just for reference.

import numpy as np
import matplotlib as plt

a = np.array([1, 2, 3])
b = np.array([2, 3, 4])

# Distance between a and b
dis = plt.mlab.dist(a, b)

回答 8

我喜欢np.dot(点积):

a = numpy.array((xa,ya,za))
b = numpy.array((xb,yb,zb))

distance = (np.dot(a-b,a-b))**.5

I like np.dot (dot product):

a = numpy.array((xa,ya,za))
b = numpy.array((xb,yb,zb))

distance = (np.dot(a-b,a-b))**.5

回答 9

一个不错的单线:

dist = numpy.linalg.norm(a-b)

但是,如果需要考虑速度,建议您在计算机上进行实验。我发现在我的机器上使用带有操作符的平方math函数库比单行NumPy解决方案快得多。sqrt**

我使用以下简单程序运行了测试:

#!/usr/bin/python
import math
import numpy
from random import uniform

def fastest_calc_dist(p1,p2):
    return math.sqrt((p2[0] - p1[0]) ** 2 +
                     (p2[1] - p1[1]) ** 2 +
                     (p2[2] - p1[2]) ** 2)

def math_calc_dist(p1,p2):
    return math.sqrt(math.pow((p2[0] - p1[0]), 2) +
                     math.pow((p2[1] - p1[1]), 2) +
                     math.pow((p2[2] - p1[2]), 2))

def numpy_calc_dist(p1,p2):
    return numpy.linalg.norm(numpy.array(p1)-numpy.array(p2))

TOTAL_LOCATIONS = 1000

p1 = dict()
p2 = dict()
for i in range(0, TOTAL_LOCATIONS):
    p1[i] = (uniform(0,1000),uniform(0,1000),uniform(0,1000))
    p2[i] = (uniform(0,1000),uniform(0,1000),uniform(0,1000))

total_dist = 0
for i in range(0, TOTAL_LOCATIONS):
    for j in range(0, TOTAL_LOCATIONS):
        dist = fastest_calc_dist(p1[i], p2[j]) #change this line for testing
        total_dist += dist

print total_dist

在我的机器上,math_calc_dist运行速度比numpy_calc_dist:1.5秒和23.5秒。

为了获得与之间的可测量差异fastest_calc_distmath_calc_dist我必须达到TOTAL_LOCATIONS6000。然后fastest_calc_dist花费〜50 秒,而math_calc_dist花费〜60秒。

您也可以尝试用numpy.sqrtnumpy.square,虽然均高于较慢math我的机器上的替代品。

我的测试是使用Python 2.6.6运行的。

A nice one-liner:

dist = numpy.linalg.norm(a-b)

However, if speed is a concern I would recommend experimenting on your machine. I’ve found that using math library’s sqrt with the ** operator for the square is much faster on my machine than the one-liner NumPy solution.

I ran my tests using this simple program:

#!/usr/bin/python
import math
import numpy
from random import uniform

def fastest_calc_dist(p1,p2):
    return math.sqrt((p2[0] - p1[0]) ** 2 +
                     (p2[1] - p1[1]) ** 2 +
                     (p2[2] - p1[2]) ** 2)

def math_calc_dist(p1,p2):
    return math.sqrt(math.pow((p2[0] - p1[0]), 2) +
                     math.pow((p2[1] - p1[1]), 2) +
                     math.pow((p2[2] - p1[2]), 2))

def numpy_calc_dist(p1,p2):
    return numpy.linalg.norm(numpy.array(p1)-numpy.array(p2))

TOTAL_LOCATIONS = 1000

p1 = dict()
p2 = dict()
for i in range(0, TOTAL_LOCATIONS):
    p1[i] = (uniform(0,1000),uniform(0,1000),uniform(0,1000))
    p2[i] = (uniform(0,1000),uniform(0,1000),uniform(0,1000))

total_dist = 0
for i in range(0, TOTAL_LOCATIONS):
    for j in range(0, TOTAL_LOCATIONS):
        dist = fastest_calc_dist(p1[i], p2[j]) #change this line for testing
        total_dist += dist

print total_dist

On my machine, math_calc_dist runs much faster than numpy_calc_dist: 1.5 seconds versus 23.5 seconds.

To get a measurable difference between fastest_calc_dist and math_calc_dist I had to up TOTAL_LOCATIONS to 6000. Then fastest_calc_dist takes ~50 seconds while math_calc_dist takes ~60 seconds.

You can also experiment with numpy.sqrt and numpy.square though both were slower than the math alternatives on my machine.

My tests were run with Python 2.6.6.


回答 10

您可以先减去向量,然后减去内积。

按照您的示例,

a = numpy.array((xa, ya, za))
b = numpy.array((xb, yb, zb))

tmp = a - b
sum_squared = numpy.dot(tmp.T, tmp)
result = sqrt(sum_squared)

You can just subtract the vectors and then innerproduct.

Following your example,

a = numpy.array((xa, ya, za))
b = numpy.array((xb, yb, zb))

tmp = a - b
sum_squared = numpy.dot(tmp.T, tmp)
result = sqrt(sum_squared)

回答 11

拥有ab定义它们时,还可以使用:

distance = np.sqrt(np.sum((a-b)**2))

Having a and b as you defined them, you can use also:

distance = np.sqrt(np.sum((a-b)**2))

回答 12

使用Python 3.8,这非常容易。

https://docs.python.org/3/library/math.html#math.dist

math.dist(p, q)

返回两个点p和q之间的欧几里得距离,每个点以坐标序列(或可迭代)给出。这两个点必须具有相同的尺寸。

大致相当于:

sqrt(sum((px - qx) ** 2.0 for px, qx in zip(p, q)))

With Python 3.8, it’s very easy.

https://docs.python.org/3/library/math.html#math.dist

math.dist(p, q)

Return the Euclidean distance between two points p and q, each given as a sequence (or iterable) of coordinates. The two points must have the same dimension.

Roughly equivalent to:

sqrt(sum((px - qx) ** 2.0 for px, qx in zip(p, q)))


回答 13

这是一些Python中的欧几里得距离的简洁代码,给出了用Python列表表示的两个点。

def distance(v1,v2): 
    return sum([(x-y)**2 for (x,y) in zip(v1,v2)])**(0.5)

Here’s some concise code for Euclidean distance in Python given two points represented as lists in Python.

def distance(v1,v2): 
    return sum([(x-y)**2 for (x,y) in zip(v1,v2)])**(0.5)

回答 14

从python 3.8开始

从Python 3.8开始,该math模块包含函数math.dist()
请参阅https://docs.python.org/3.8/library/math.html#math.dist

math.dist(p1,p2)
返回两个点p1和p2之间的欧几里得距离,每个点均以坐标序列(或可迭代)给出。

import math
print( math.dist( (0,0),   (1,1)   )) # sqrt(2) -> 1.4142
print( math.dist( (0,0,0), (1,1,1) )) # sqrt(3) -> 1.7321

Since Python 3.8

Since Python 3.8 the math module includes the function math.dist().
See here https://docs.python.org/3.8/library/math.html#math.dist.

math.dist(p1, p2)
Return the Euclidean distance between two points p1 and p2, each given as a sequence (or iterable) of coordinates.

import math
print( math.dist( (0,0),   (1,1)   )) # sqrt(2) -> 1.4142
print( math.dist( (0,0,0), (1,1,1) )) # sqrt(3) -> 1.7321

回答 15

计算多维空间的欧几里得距离:

 import math

 x = [1, 2, 6] 
 y = [-2, 3, 2]

 dist = math.sqrt(sum([(xi-yi)**2 for xi,yi in zip(x, y)]))
 5.0990195135927845

Calculate the Euclidean distance for multidimensional space:

 import math

 x = [1, 2, 6] 
 y = [-2, 3, 2]

 dist = math.sqrt(sum([(xi-yi)**2 for xi,yi in zip(x, y)]))
 5.0990195135927845

回答 16

import numpy as np
from scipy.spatial import distance
input_arr = np.array([[0,3,0],[2,0,0],[0,1,3],[0,1,2],[-1,0,1],[1,1,1]]) 
test_case = np.array([0,0,0])
dst=[]
for i in range(0,6):
    temp = distance.euclidean(test_case,input_arr[i])
    dst.append(temp)
print(dst)
import numpy as np
from scipy.spatial import distance
input_arr = np.array([[0,3,0],[2,0,0],[0,1,3],[0,1,2],[-1,0,1],[1,1,1]]) 
test_case = np.array([0,0,0])
dst=[]
for i in range(0,6):
    temp = distance.euclidean(test_case,input_arr[i])
    dst.append(temp)
print(dst)

回答 17

import math

dist = math.hypot(math.hypot(xa-xb, ya-yb), za-zb)
import math

dist = math.hypot(math.hypot(xa-xb, ya-yb), za-zb)

回答 18

您可以轻松使用公式

distance = np.sqrt(np.sum(np.square(a-b)))

实际上,这无非是使用毕达哥拉斯定理来计算距离,方法是将Δx,Δy和Δz的平方相加并取根。

You can easily use the formula

distance = np.sqrt(np.sum(np.square(a-b)))

which does actually nothing more than using Pythagoras’ theorem to calculate the distance, by adding the squares of Δx, Δy and Δz and rooting the result.


回答 19

首先找到两个矩阵的差。然后,使用numpy的乘法命令应用逐元素乘法。之后,找到逐元素相乘的新矩阵的总和。最后,找到求和的平方根。

def findEuclideanDistance(a, b):
    euclidean_distance = a - b
    euclidean_distance = np.sum(np.multiply(euclidean_distance, euclidean_distance))
    euclidean_distance = np.sqrt(euclidean_distance)
    return euclidean_distance

Find difference of two matrices first. Then, apply element wise multiplication with numpy’s multiply command. After then, find summation of the element wise multiplied new matrix. Finally, find square root of the summation.

def findEuclideanDistance(a, b):
    euclidean_distance = a - b
    euclidean_distance = np.sum(np.multiply(euclidean_distance, euclidean_distance))
    euclidean_distance = np.sqrt(euclidean_distance)
    return euclidean_distance

回答 20

import numpy as np
# any two python array as two points
a = [0, 0]
b = [3, 4]

您首先将列表更改为numpy array并执行以下操作:print(np.linalg.norm(np.array(a) - np.array(b)))。直接从python列表中获取的第二种方法为:print(np.linalg.norm(np.subtract(a,b)))

import numpy as np
# any two python array as two points
a = [0, 0]
b = [3, 4]

You first change list to numpy array and do like this: print(np.linalg.norm(np.array(a) - np.array(b))). Second method directly from python list as: print(np.linalg.norm(np.subtract(a,b)))


Python int转换为二进制字符串?

问题:Python int转换为二进制字符串?

是否有任何固定的Python方法将Python中的Integer(或Long)转换为二进制字符串?

Google上有无数的dec2bin()函数…但是我希望可以使用内置函数/库。

Are there any canned Python methods to convert an Integer (or Long) into a binary string in Python?

There are a myriad of dec2bin() functions out on Google… But I was hoping I could use a built-in function / library.


回答 0

Python的字符串格式方法可以采用格式规范。

>>> "{0:b}".format(37)
'100101'

适用于Python 2的格式规范文档

适用于Python 3的格式规范文档

Python’s string format method can take a format spec.

>>> "{0:b}".format(37)
'100101'

Format spec docs for Python 2

Format spec docs for Python 3


回答 1

如果您正在寻找bin()等同于hex(),它是在python 2.6中添加的。

例:

>>> bin(10)
'0b1010'

If you’re looking for bin() as an equivalent to hex(), it was added in python 2.6.

Example:

>>> bin(10)
'0b1010'

回答 2

Python的实际确实已经内建了对这个东西,做如操作的能力'{0:b}'.format(42),这将给你的位模式(在一个字符串)42,或101010


对于更一般的哲学,没有语言或库会向用户群提供他们想要的一切。如果您所处的环境不能完全满足您的需求,则在开发过程中应收集代码片段,以确保您不必重复编写同一件事。例如伪代码:

define intToBinString, receiving intVal:
    if intVal is equal to zero:
        return "0"
    set strVal to ""
    while intVal is greater than zero:
        if intVal is odd:
            prefix "1" to strVal
        else:
            prefix "0" to strVal
        divide intVal by two, rounding down
    return strVal

它将根据十进制值构造您的二进制字符串。请记住,这是伪代码的通用位,虽然这可能不是有效的方式,但是您似乎建议进行迭代,但这并没有太大的区别。它实际上只是作为如何完成操作的指南。

总体思路是使用代码(按优先顺序排列):

  • 语言或内置库。
  • 具有适当许可证的第三方库。
  • 你自己的收藏。
  • 您需要编写一些新内容(并保存在自己的收藏夹中以备后用)。

Python actually does have something already built in for this, the ability to do operations such as '{0:b}'.format(42), which will give you the bit pattern (in a string) for 42, or 101010.


For a more general philosophy, no language or library will give its user base everything that they desire. If you’re working in an environment that doesn’t provide exactly what you need, you should be collecting snippets of code as you develop to ensure you never have to write the same thing twice. Such as, for example, the pseudo-code:

define intToBinString, receiving intVal:
    if intVal is equal to zero:
        return "0"
    set strVal to ""
    while intVal is greater than zero:
        if intVal is odd:
            prefix "1" to strVal
        else:
            prefix "0" to strVal
        divide intVal by two, rounding down
    return strVal

which will construct your binary string based on the decimal value. Just keep in mind that’s a generic bit of pseudo-code which may not be the most efficient way of doing it though, with the iterations you seem to be proposing, it won’t make much difference. It’s really just meant as a guideline on how it could be done.

The general idea is to use code from (in order of preference):

  • the language or built-in libraries.
  • third-party libraries with suitable licenses.
  • your own collection.
  • something new you need to write (and save in your own collection for later).

回答 3

如果要使用不带0b前缀的文本表示形式,则可以使用以下代码:

get_bin = lambda x: format(x, 'b')

print(get_bin(3))
>>> '11'

print(get_bin(-3))
>>> '-11'

当您需要n位表示形式时:

get_bin = lambda x, n: format(x, 'b').zfill(n)
>>> get_bin(12, 32)
'00000000000000000000000000001100'
>>> get_bin(-12, 32)
'-00000000000000000000000000001100'

或者,如果您更喜欢具有以下功能:

def get_bin(x, n=0):
    """
    Get the binary representation of x.

    Parameters
    ----------
    x : int
    n : int
        Minimum number of digits. If x needs less digits in binary, the rest
        is filled with zeros.

    Returns
    -------
    str
    """
    return format(x, 'b').zfill(n)

If you want a textual representation without the 0b-prefix, you could use this:

get_bin = lambda x: format(x, 'b')

print(get_bin(3))
>>> '11'

print(get_bin(-3))
>>> '-11'

When you want a n-bit representation:

get_bin = lambda x, n: format(x, 'b').zfill(n)
>>> get_bin(12, 32)
'00000000000000000000000000001100'
>>> get_bin(-12, 32)
'-00000000000000000000000000001100'

Alternatively, if you prefer having a function:

def get_bin(x, n=0):
    """
    Get the binary representation of x.

    Parameters
    ----------
    x : int
    n : int
        Minimum number of digits. If x needs less digits in binary, the rest
        is filled with zeros.

    Returns
    -------
    str
    """
    return format(x, 'b').zfill(n)

回答 4

作为参考:

def toBinary(n):
    return ''.join(str(1 & int(n) >> i) for i in range(64)[::-1])

此函数可以转换一个大的正整数18446744073709551615,以string表示'1111111111111111111111111111111111111111111111111111111111111111'

可以修改它以使用更大的整数,尽管它可能不如"{0:b}".format()或方便bin()

As a reference:

def toBinary(n):
    return ''.join(str(1 & int(n) >> i) for i in range(64)[::-1])

This function can convert a positive integer as large as 18446744073709551615, represented as string '1111111111111111111111111111111111111111111111111111111111111111'.

It can be modified to serve a much larger integer, though it may not be as handy as "{0:b}".format() or bin().


回答 5

一种简单的方法是使用字符串格式,请参见本页

>> "{0:b}".format(10)
'1010'

如果要固定长度的二进制字符串,则可以使用以下命令:

>> "{0:{fill}8b}".format(10, fill='0')
'00001010'

如果需要二进制补码,则可以使用以下行:

'{0:{fill}{width}b}'.format((x + 2**n) % 2**n, fill='0', width=n)

其中n是二进制字符串的宽度。

A simple way to do that is to use string format, see this page.

>> "{0:b}".format(10)
'1010'

And if you want to have a fixed length of the binary string, you can use this:

>> "{0:{fill}8b}".format(10, fill='0')
'00001010'

If two’s complement is required, then the following line can be used:

'{0:{fill}{width}b}'.format((x + 2**n) % 2**n, fill='0', width=n)

where n is the width of the binary string.


回答 6

这是针对python 3的,它保持前导零!

print(format(0, '08b'))

在此处输入图片说明

This is for python 3 and it keeps the leading zeros !

print(format(0, '08b'))

enter image description here


回答 7

lambda的单线

>>> binary = lambda n: '' if n==0 else binary(n/2) + str(n%2)

测试:

>>> binary(5)
'101'



编辑

但是之后 :(

t1 = time()
for i in range(1000000):
     binary(i)
t2 = time()
print(t2 - t1)
# 6.57236599922

相较于

t1 = time()
for i in range(1000000):
    '{0:b}'.format(i)
t2 = time()
print(t2 - t1)
# 0.68017411232

one-liner with lambda:

>>> binary = lambda n: '' if n==0 else binary(n/2) + str(n%2)

test:

>>> binary(5)
'101'



EDIT:

but then :(

t1 = time()
for i in range(1000000):
     binary(i)
t2 = time()
print(t2 - t1)
# 6.57236599922

in compare to

t1 = time()
for i in range(1000000):
    '{0:b}'.format(i)
t2 = time()
print(t2 - t1)
# 0.68017411232

回答 8

替代方案摘要:

n=42
assert  "-101010" == format(-n, 'b')
assert  "-101010" == "{0:b}".format(-n)
assert  "-101010" == (lambda x: x >= 0 and str(bin(x))[2:] or "-" + str(bin(x))[3:])(-n)
assert "0b101010" == bin(n)
assert   "101010" == bin(n)[2:]   # But this won't work for negative numbers.

贡献者包括John FouhyTung NguyenmVChrMartin Thoma。和马丁·彼得斯(Martijn Pieters)。

Summary of alternatives:

n=42
assert  "-101010" == format(-n, 'b')
assert  "-101010" == "{0:b}".format(-n)
assert  "-101010" == (lambda x: x >= 0 and str(bin(x))[2:] or "-" + str(bin(x))[3:])(-n)
assert "0b101010" == bin(n)
assert   "101010" == bin(n)[2:]   # But this won't work for negative numbers.

Contributors include John Fouhy, Tung Nguyen, mVChr, Martin Thoma. and Martijn Pieters.


回答 9

由于前面的答案大多使用format(),因此这是f字符串实现。

integer = 7
bit_count = 5
print(f'{integer:0{bit_count}b}')

输出:

00111

为方便起见,这里是格式化字符串文字的python docs链接:https : //docs.python.org/3/reference/lexical_analysis.html#f-strings

As the preceding answers mostly used format(), here is an f-string implementation.

integer = 7
bit_count = 5
print(f'{integer:0{bit_count}b}')

Output:

00111

For convenience here is the python docs link for formatted string literals: https://docs.python.org/3/reference/lexical_analysis.html#f-strings.


回答 10

>>> format(123, 'b')
'1111011'
>>> format(123, 'b')
'1111011'

回答 11

使用numpy pack / unpackbits,它们是您最好的朋友。

Examples
--------
>>> a = np.array([[2], [7], [23]], dtype=np.uint8)
>>> a
array([[ 2],
       [ 7],
       [23]], dtype=uint8)
>>> b = np.unpackbits(a, axis=1)
>>> b
array([[0, 0, 0, 0, 0, 0, 1, 0],
       [0, 0, 0, 0, 0, 1, 1, 1],
       [0, 0, 0, 1, 0, 1, 1, 1]], dtype=uint8)

Using numpy pack/unpackbits, they are your best friends.

Examples
--------
>>> a = np.array([[2], [7], [23]], dtype=np.uint8)
>>> a
array([[ 2],
       [ 7],
       [23]], dtype=uint8)
>>> b = np.unpackbits(a, axis=1)
>>> b
array([[0, 0, 0, 0, 0, 0, 1, 0],
       [0, 0, 0, 0, 0, 1, 1, 1],
       [0, 0, 0, 1, 0, 1, 1, 1]], dtype=uint8)

回答 12

对于我们这些需要将带符号整数(范围-2 **(digits-1)到2 **(digits-1)-1)转换为2的补码二进制字符串的人来说,这可行:

def int2bin(integer, digits):
if integer >= 0:
    return bin(integer)[2:].zfill(digits)
else:
    return bin(2**digits + integer)[2:]

这将生成:

>>> int2bin(10, 8)
'00001010'
>>> int2bin(-10, 8)
'11110110'
>>> int2bin(-128, 8)
'10000000'
>>> int2bin(127, 8)
'01111111'

For those of us who need to convert signed integers (range -2**(digits-1) to 2**(digits-1)-1) to 2’s complement binary strings, this works:

def int2bin(integer, digits):
if integer >= 0:
    return bin(integer)[2:].zfill(digits)
else:
    return bin(2**digits + integer)[2:]

This produces:

>>> int2bin(10, 8)
'00001010'
>>> int2bin(-10, 8)
'11110110'
>>> int2bin(-128, 8)
'10000000'
>>> int2bin(127, 8)
'01111111'

回答 13

除非我误解了二进制字符串的含义,否则我认为您要查找的模块是struct

Unless I’m misunderstanding what you mean by binary string I think the module you are looking for is struct


回答 14

通过使用按位运算符,使用另一种算法的另一种解决方案。

def int2bin(val):
    res=''
    while val>0:
        res += str(val&1)
        val=val>>1     # val=val/2 
    return res[::-1]   # reverse the string

更快的版本而无需反转字符串。

def int2bin(val):
   res=''
   while val>0:
       res = chr((val&1) + 0x30) + res
       val=val>>1    
   return res 

Yet another solution with another algorithm, by using bitwise operators.

def int2bin(val):
    res=''
    while val>0:
        res += str(val&1)
        val=val>>1     # val=val/2 
    return res[::-1]   # reverse the string

A faster version without reversing the string.

def int2bin(val):
   res=''
   while val>0:
       res = chr((val&1) + 0x30) + res
       val=val>>1    
   return res 

回答 15

def binary(decimal) :
    otherBase = ""
    while decimal != 0 :
        otherBase  =  str(decimal % 2) + otherBase
        decimal    //=  2
    return otherBase

print binary(10)

输出:

1010

def binary(decimal) :
    otherBase = ""
    while decimal != 0 :
        otherBase  =  str(decimal % 2) + otherBase
        decimal    //=  2
    return otherBase

print binary(10)

output:

1010


回答 16

你可以这样:

bin(10)[2:]

要么 :

f = str(bin(10))
c = []
c.append("".join(map(int, f[2:])))
print c

you can do like that :

bin(10)[2:]

or :

f = str(bin(10))
c = []
c.append("".join(map(int, f[2:])))
print c

回答 17

这是我刚刚实现的代码。这不是一种方法,但是您可以将其用作现成的功能

def inttobinary(number):
  if number == 0:
    return str(0)
  result =""
  while (number != 0):
      remainder = number%2
      number = number/2
      result += str(remainder)
  return result[::-1] # to invert the string

Here is the code I’ve just implemented. This is not a method but you can use it as a ready-to-use function!

def inttobinary(number):
  if number == 0:
    return str(0)
  result =""
  while (number != 0):
      remainder = number%2
      number = number/2
      result += str(remainder)
  return result[::-1] # to invert the string

回答 18

这是使用divmod()功能的简单解决方案,该功能返回提醒和不带分数的除法结果。

def dectobin(number):
    bin = ''
    while (number >= 1):
        number, rem = divmod(number, 2)
        bin = bin + str(rem)
    return bin

here is simple solution using the divmod() fucntion which returns the reminder and the result of a division without the fraction.

def dectobin(number):
    bin = ''
    while (number >= 1):
        number, rem = divmod(number, 2)
        bin = bin + str(rem)
    return bin

回答 19

n=input()
print(bin(n).replace("0b", ""))
n=input()
print(bin(n).replace("0b", ""))

回答 20

numpy.binary_repr(num, width=None)

上面的文档链接中的示例:

>>> np.binary_repr(3)
'11'
>>> np.binary_repr(-3)
'-11'
>>> np.binary_repr(3, width=4)
'0011'

当输入数字为负并且指定了宽度时,将返回二进制补码:

>>> np.binary_repr(-3, width=3)
'101'
>>> np.binary_repr(-3, width=5)
'11101'

numpy.binary_repr(num, width=None)

Examples from the documentation link above:

>>> np.binary_repr(3)
'11'
>>> np.binary_repr(-3)
'-11'
>>> np.binary_repr(3, width=4)
'0011'

The two’s complement is returned when the input number is negative and width is specified:

>>> np.binary_repr(-3, width=3)
'101'
>>> np.binary_repr(-3, width=5)
'11101'

回答 21

有点类似的解决方案

def to_bin(dec):
    flag = True
    bin_str = ''
    while flag:
        remainder = dec % 2
        quotient = dec / 2
        if quotient == 0:
            flag = False
        bin_str += str(remainder)
        dec = quotient
    bin_str = bin_str[::-1] # reverse the string
    return bin_str 

Somewhat similar solution

def to_bin(dec):
    flag = True
    bin_str = ''
    while flag:
        remainder = dec % 2
        quotient = dec / 2
        if quotient == 0:
            flag = False
        bin_str += str(remainder)
        dec = quotient
    bin_str = bin_str[::-1] # reverse the string
    return bin_str 

回答 22

这是使用常规数学的另一种方式,没有循环,只有递归。(特殊情况0不返回任何内容)。

def toBin(num):
  if num == 0:
    return ""
  return toBin(num//2) + str(num%2)

print ([(toBin(i)) for i in range(10)])

['', '1', '10', '11', '100', '101', '110', '111', '1000', '1001']

Here’s yet another way using regular math, no loops, only recursion. (Trivial case 0 returns nothing).

def toBin(num):
  if num == 0:
    return ""
  return toBin(num//2) + str(num%2)

print ([(toBin(i)) for i in range(10)])

['', '1', '10', '11', '100', '101', '110', '111', '1000', '1001']

回答 23

计算器,具有DEC,BIN,HEX的所有必要功能:(使用Python 3.5进行制造和测试)

您可以更改输入的测试编号并获得转换后的编号。

# CONVERTER: DEC / BIN / HEX

def dec2bin(d):
    # dec -> bin
    b = bin(d)
    return b

def dec2hex(d):
    # dec -> hex
    h = hex(d)
    return h

def bin2dec(b):
    # bin -> dec
    bin_numb="{0:b}".format(b)
    d = eval(bin_numb)
    return d,bin_numb

def bin2hex(b):
    # bin -> hex
    h = hex(b)
    return h

def hex2dec(h):
    # hex -> dec
    d = int(h)
    return d

def hex2bin(h):
    # hex -> bin
    b = bin(h)
    return b


## TESTING NUMBERS
numb_dec = 99
numb_bin = 0b0111 
numb_hex = 0xFF


## CALCULATIONS
res_dec2bin = dec2bin(numb_dec)
res_dec2hex = dec2hex(numb_dec)

res_bin2dec,bin_numb = bin2dec(numb_bin)
res_bin2hex = bin2hex(numb_bin)

res_hex2dec = hex2dec(numb_hex)
res_hex2bin = hex2bin(numb_hex)



## PRINTING
print('------- DECIMAL to BIN / HEX -------\n')
print('decimal:',numb_dec,'\nbin:    ',res_dec2bin,'\nhex:    ',res_dec2hex,'\n')

print('------- BINARY to DEC / HEX -------\n')
print('binary: ',bin_numb,'\ndec:    ',numb_bin,'\nhex:    ',res_bin2hex,'\n')

print('----- HEXADECIMAL to BIN / HEX -----\n')
print('hexadec:',hex(numb_hex),'\nbin:    ',res_hex2bin,'\ndec:    ',res_hex2dec,'\n')

Calculator with all neccessary functions for DEC,BIN,HEX: (made and tested with Python 3.5)

You can change the input test numbers and get the converted ones.

# CONVERTER: DEC / BIN / HEX

def dec2bin(d):
    # dec -> bin
    b = bin(d)
    return b

def dec2hex(d):
    # dec -> hex
    h = hex(d)
    return h

def bin2dec(b):
    # bin -> dec
    bin_numb="{0:b}".format(b)
    d = eval(bin_numb)
    return d,bin_numb

def bin2hex(b):
    # bin -> hex
    h = hex(b)
    return h

def hex2dec(h):
    # hex -> dec
    d = int(h)
    return d

def hex2bin(h):
    # hex -> bin
    b = bin(h)
    return b


## TESTING NUMBERS
numb_dec = 99
numb_bin = 0b0111 
numb_hex = 0xFF


## CALCULATIONS
res_dec2bin = dec2bin(numb_dec)
res_dec2hex = dec2hex(numb_dec)

res_bin2dec,bin_numb = bin2dec(numb_bin)
res_bin2hex = bin2hex(numb_bin)

res_hex2dec = hex2dec(numb_hex)
res_hex2bin = hex2bin(numb_hex)



## PRINTING
print('------- DECIMAL to BIN / HEX -------\n')
print('decimal:',numb_dec,'\nbin:    ',res_dec2bin,'\nhex:    ',res_dec2hex,'\n')

print('------- BINARY to DEC / HEX -------\n')
print('binary: ',bin_numb,'\ndec:    ',numb_bin,'\nhex:    ',res_bin2hex,'\n')

print('----- HEXADECIMAL to BIN / HEX -----\n')
print('hexadec:',hex(numb_hex),'\nbin:    ',res_hex2bin,'\ndec:    ',res_hex2dec,'\n')

回答 24

要计算数字的二进制数:

print("Binary is {0:>08b}".format(16))

要计算数字的十六进制十进制

print("Hexa Decimal is {0:>0x}".format(15))

要计算所有二进制数,直到16 ::

for i in range(17):
   print("{0:>2}: binary is {0:>08b}".format(i))

计算十六进制小数,直到17

 for i in range(17):
    print("{0:>2}: Hexa Decimal is {0:>0x}".format(i))
##as 2 digit is enogh for hexa decimal representation of a number

To calculate binary of numbers:

print("Binary is {0:>08b}".format(16))

To calculate the Hexa decimal of a number:

print("Hexa Decimal is {0:>0x}".format(15))

To Calculate all the binary no till 16::

for i in range(17):
   print("{0:>2}: binary is {0:>08b}".format(i))

To calculate Hexa decimal no till 17

 for i in range(17):
    print("{0:>2}: Hexa Decimal is {0:>0x}".format(i))
##as 2 digit is enogh for hexa decimal representation of a number

回答 25

如果你愿意放弃“纯” Python的,但收获了很多火力,有贤者这里的例子

sage: a = 15
sage: a.binary()
'1111'

您会注意到它以字符串形式返回,因此要将其用作数字,您需要执行以下操作

sage: eval('0b'+b)
15

If you are willing to give up “pure” Python but gain a lot of firepower, there is Sageexample here:

sage: a = 15
sage: a.binary()
'1111'

You’ll note that it returns as a string, so to use it as a number you’d want to do something like

sage: eval('0b'+b)
15

回答 26

try:
    while True:
        p = ""
        a = input()
        while a != 0:
            l = a % 2
            b = a - l
            a = b / 2
            p = str(l) + p
        print(p)
except:
    print ("write 1 number")
try:
    while True:
        p = ""
        a = input()
        while a != 0:
            l = a % 2
            b = a - l
            a = b / 2
            p = str(l) + p
        print(p)
except:
    print ("write 1 number")

回答 27

我发现了一种使用矩阵运算将十进制转换为二进制的方法。

import numpy as np
E_mat = np.tile(E,[1,M])
M_order = pow(2,(M-1-np.array(range(M)))).T
bindata = np.remainder(np.floor(E_mat /M_order).astype(np.int),2)

E是输入十进制数据,M是二进制顺序。bindata是输出二进制数据,格式为1 x M二进制矩阵。

I found a method using matrix operation to convert decimal to binary.

import numpy as np
E_mat = np.tile(E,[1,M])
M_order = pow(2,(M-1-np.array(range(M)))).T
bindata = np.remainder(np.floor(E_mat /M_order).astype(np.int),2)

Eis input decimal data,M is the binary orders. bindata is output binary data, which is in a format of 1 by M binary matrix.


回答 28

这是一个不断循环的简单的二进制到十进制转换器

t = 1
while t > 0:
    binaryNumber = input("Enter a binary No.")
    convertedNumber = int(binaryNumber, 2)

    print(convertedNumber)

print("")

Here’s a simple binary to decimal converter that continuously loops

t = 1
while t > 0:
    binaryNumber = input("Enter a binary No.")
    convertedNumber = int(binaryNumber, 2)

    print(convertedNumber)

print("")

回答 29

这是我的回答,效果很好..!

def binary(value) :
    binary_value = ''
    while value !=1  :
        binary_value += str(value%2)
        value = value//2
    return '1'+binary_value[::-1]

This is my answer it works well..!

def binary(value) :
    binary_value = ''
    while value !=1  :
        binary_value += str(value%2)
        value = value//2
    return '1'+binary_value[::-1]