标签归档:Python

如何使用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。

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.


回答 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.


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


回答 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]

在Python中,“ SyntaxError:调用’print’时缺少括号”是什么意思?

问题:在Python中,“ SyntaxError:调用’print’时缺少括号”是什么意思?

当我尝试print在Python中使用语句时,它给了我这个错误:

>>> print "Hello, World!"
  File "<stdin>", line 1
    print "Hello, World!"
                        ^
SyntaxError: Missing parentheses in call to 'print'

这意味着什么?

When I try to use a print statement in Python, it gives me this error:

>>> print "Hello, World!"
  File "<stdin>", line 1
    print "Hello, World!"
                        ^
SyntaxError: Missing parentheses in call to 'print'

What does that mean?


回答 0

此错误消息表示您尝试使用Python 3遵循示例或运行使用Python 2 print语句的程序:

print "Hello, World!"

上面的语句在Python 3中不起作用。在Python 3中,您需要在要打印的值周围添加括号:

print("Hello, World!")

“ SyntaxError:对’print’的调用中缺少括号”是Python 3.4.2中新增的一条错误消息,主要是为了帮助试图在运行Python 3时遵循Python 2教程的用户。

在Python 3中,打印值已从一个独特的语句变为一个普通的函数调用,因此现在需要括号:

>>> print("Hello, World!")
Hello, World!

在Python 3的早期版本中,解释器仅报告通用语法错误,而没有提供任何有用的提示来提示可能出了什么问题:

>>> print "Hello, World!"
  File "<stdin>", line 1
    print "Hello, World!"
                        ^
SyntaxError: invalid syntax

至于为什么 print在Python 3中成为普通函数,这与语句的基本形式无关,而是与如何执行更复杂的事情类似,例如将多个项目打印到带有尾部空格的stderr而不是结束行。

在Python 2中:

>>> import sys
>>> print >> sys.stderr, 1, 2, 3,; print >> sys.stderr, 4, 5, 6
1 2 3 4 5 6

在Python 3中:

>>> import sys
>>> print(1, 2, 3, file=sys.stderr, end=" "); print(4, 5, 6, file=sys.stderr)
1 2 3 4 5 6

从2017年9月的Python 3.6.3版本开始,一些与Python 2.x打印语法有关的错误消息已更新,以推荐与之对应的Python 3.x:

>>> print "Hello!"
  File "<stdin>", line 1
    print "Hello!"
                 ^
SyntaxError: Missing parentheses in call to 'print'. Did you mean print("Hello!")?

由于“在打印输出中缺少括号”情况是编译时语法错误,因此可以访问原始源代码,因此可以在建议的替换内容中在行的其余部分包含全文。但是,它目前并未尝试找出适合该表达式的引号(这不是不可能的,只是足够复杂以至于尚未完成)。

TypeError募投向右移位运算符也被定制:

>>> print >> sys.stderr
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for >>: 'builtin_function_or_method' and '_io.TextIOWrapper'. Did you mean "print(<message>, file=<output_stream>)"?

由于此错误是在代码运行时(而不是在编译时)引发的,因此它无法访问原始源代码,因此在建议的替换表达式中使用元变量(<message><output_stream>),而不是用户实际键入的内容。与语法错误的情况不同,在自定义右移错误消息中将引号放在Python表达式周围很简单。

This error message means that you are attempting to use Python 3 to follow an example or run a program that uses the Python 2 print statement:

print "Hello, World!"

The statement above does not work in Python 3. In Python 3 you need to add parentheses around the value to be printed:

print("Hello, World!")

“SyntaxError: Missing parentheses in call to ‘print’” is a new error message that was added in Python 3.4.2 primarily to help users that are trying to follow a Python 2 tutorial while running Python 3.

In Python 3, printing values changed from being a distinct statement to being an ordinary function call, so it now needs parentheses:

>>> print("Hello, World!")
Hello, World!

In earlier versions of Python 3, the interpreter just reports a generic syntax error, without providing any useful hints as to what might be going wrong:

>>> print "Hello, World!"
  File "<stdin>", line 1
    print "Hello, World!"
                        ^
SyntaxError: invalid syntax

As for why print became an ordinary function in Python 3, that didn’t relate to the basic form of the statement, but rather to how you did more complicated things like printing multiple items to stderr with a trailing space rather than ending the line.

In Python 2:

>>> import sys
>>> print >> sys.stderr, 1, 2, 3,; print >> sys.stderr, 4, 5, 6
1 2 3 4 5 6

In Python 3:

>>> import sys
>>> print(1, 2, 3, file=sys.stderr, end=" "); print(4, 5, 6, file=sys.stderr)
1 2 3 4 5 6

Starting with the Python 3.6.3 release in September 2017, some error messages related to the Python 2.x print syntax have been updated to recommend their Python 3.x counterparts:

>>> print "Hello!"
  File "<stdin>", line 1
    print "Hello!"
                 ^
SyntaxError: Missing parentheses in call to 'print'. Did you mean print("Hello!")?

Since the “Missing parentheses in call to print” case is a compile time syntax error and hence has access to the raw source code, it’s able to include the full text on the rest of the line in the suggested replacement. However, it doesn’t currently try to work out the appropriate quotes to place around that expression (that’s not impossible, just sufficiently complicated that it hasn’t been done).

The TypeError raised for the right shift operator has also been customised:

>>> print >> sys.stderr
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for >>: 'builtin_function_or_method' and '_io.TextIOWrapper'. Did you mean "print(<message>, file=<output_stream>)"?

Since this error is raised when the code runs, rather than when it is compiled, it doesn’t have access to the raw source code, and hence uses meta-variables (<message> and <output_stream>) in the suggested replacement expression instead of whatever the user actually typed. Unlike the syntax error case, it’s straightforward to place quotes around the Python expression in the custom right shift error message.


回答 1

不幸的是,旧的xkcd漫画不再完全是最新的。

从Python 3.0开始,您必须编写:

print("Hello, World!")

而且仍然有人要编写该antigravity库:(

Unfortunately, the old xkcd comic isn’t completely up to date anymore.

Since Python 3.0 you have to write:

print("Hello, World!")

And someone has still to write that antigravity library :(


回答 2

语法从Python 2更改为Python3。在Python 2中,

print "Hello, World!" 

可以使用,但是在Python 3中,使用括号作为

print("Hello, World!")

这与Scala等效,与Java差不多。

There is a change in syntax from Python 2 to Python 3. In Python 2,

print "Hello, World!" 

will work but in Python 3, use parentheses as

print("Hello, World!")

This is equivalent syntax to Scala and near to Java.


回答 3

如果您的代码在Python 2和3中都可以使用,则可以通过在程序开始时加载以下代码来实现:

from __future__ import print_function   # If code has to work in Python 2 and 3!

然后,您可以使用Python 3方式进行打印:

print("python")

如果要打印某些内容而不创建新行,则可以执行以下操作:

for number in range(0, 10):
    print(number, end=', ')

If your code should work in both Python 2 and 3, you can achieve this by loading this at the beginning of your program:

from __future__ import print_function   # If code has to work in Python 2 and 3!

Then you can print in the Python 3 way:

print("python")

If you want to print something without creating a new line – you can do this:

for number in range(0, 10):
    print(number, end=', ')

回答 4

在Python 3中,您只能将其打印为:

print("STRING")

但是在Python 2中,不需要括号。

In Python 3, you can only print as:

print("STRING")

But in Python 2, the parentheses are not necessary.


回答 5

基本上,从Python 3.x开始,您需要使用 print括号。

Python 2.x:打印“指环王”

Python 3.x:print(“指环王”)


讲解

print2.x中是一个语句,但在3.x中是一个函数。现在,有很多充分的理由。

  1. 使用Python 3.x的函数格式,当打印多个用逗号分隔的项目时,灵活性更高。
  2. 您不能在语句中使用参数展开。在3.x中,如果有要使用分隔符打印的项目列表,则可以执行以下操作:
>>> items = ['foo', 'bar', 'baz']
>>> print(*items, sep='+') 
foo+bar+baz
  1. 您不能覆盖语句。如果要更改print的行为,则可以在它是一个函数时执行此操作,但在声明时不可以。

Basically, since Python 3.x you need to use print with parenthesis.

Python 2.x: print “Lord of the Rings”

Python 3.x: print(“Lord of the Rings”)


Explaination

print was a statement in 2.x, but it’s a function in 3.x. Now, there are a number of good reasons for this.

  1. With function format of Python 3.x, more flexibility comes when printing multiple items with comman separated.
  2. You can’t use argument splatting with a statement. In 3.x if you have a list of items that you want to print with a separator, you can do this:
>>> items = ['foo', 'bar', 'baz']
>>> print(*items, sep='+') 
foo+bar+baz
  1. You can’t override a statement. If you want to change the behavior of print, you can do that when it’s a function but not when it’s a statement.

回答 6

我还可以补充一点,我知道Python2.7和之间有关语法更改的所有知识Python3,并且我的代码正确编写为as print("string")甚至 print(f"string")

但是经过一段时间的调试后,我意识到我的bash脚本正在像这样调用python:

python file_name.py

这具有默认情况下使用python调用我的python脚本的作用,从而产生python2.7了错误。因此,我将bash脚本更改为:

python3 file_name.py

哪个使用python3来运行修复了错误的脚本。

I could also just add that I knew everything about the syntax change between Python2.7 and Python3, and my code was correctly written as print("string") and even print(f"string")

But after some time of debugging I realized that my bash script was calling python like:

python file_name.py

which had the effect of calling my python script by default using python2.7 which gave the error. So I changed my bash script to:

python3 file_name.py

which of coarse uses python3 to run the script which fixed the error.


回答 7

除了这里的直接答案外,还应注意python 2和3之间的另一个主要区别。官方python Wiki涵盖了几乎所有主要区别,并着重于何时应使用这两个版本。这篇博客文章也很好地解释了当前的python宇宙以及迁移到python 3时仍未解决的难题。

据我所知,您正在开始学习python语言。在继续进行python 3路由之前,您应该考虑上述文章。您不仅需要更改某些语法,还需要考虑哪些包对您可用(python 2的优点)以及可以在代码中进行的潜在优化(python 3的优点) 。

Outside of the direct answers here, one should note the other key difference between python 2 and 3. The official python wiki goes into almost all of the major differences and focuses on when you should use either of the versions. This blog post also does a fine job of explaining the current python universe and the somehow unsolved puzzle of moving to python 3.

As far as I can tell, you are beginning to learn the python language. You should consider the aforementioned articles before you continue down the python 3 route. Not only will you have to change some of your syntax, you will also need to think about which packages will be available to you (an advantage of python 2) and potential optimizations that could be made in your code (an advantage of python 3).


如何在Python中进行相对导入?

问题:如何在Python中进行相对导入?

想象一下这个目录结构:

app/
   __init__.py
   sub1/
      __init__.py
      mod1.py
   sub2/
      __init__.py
      mod2.py

我正在编码mod1,我需要从中导入一些东西mod2。我该怎么办?

我尝试过,from ..sub2 import mod2但是得到了“未打包的相对导入尝试”。

我四处搜寻,但只发现“ sys.path操纵”骇客。有没有一种干净的方法?


编辑:我所有__init__.py的当前为空

EDIT2:我想这样做,因为SUB2包含了为子包(共享类sub1subX等等)。

Edit3:我要寻找的行为与PEP 366中描述的相同(感谢John B)

Imagine this directory structure:

app/
   __init__.py
   sub1/
      __init__.py
      mod1.py
   sub2/
      __init__.py
      mod2.py

I’m coding mod1, and I need to import something from mod2. How should I do it?

I tried from ..sub2 import mod2 but I’m getting an “Attempted relative import in non-package”.

I googled around but found only “sys.path manipulation” hacks. Isn’t there a clean way?


Edit: all my __init__.py‘s are currently empty

Edit2: I’m trying to do this because sub2 contains classes that are shared across sub packages (sub1, subX, etc.).

Edit3: The behaviour I’m looking for is the same as described in PEP 366 (thanks John B)


回答 0

每个人似乎都想告诉您应该做什么,而不仅仅是回答问题。

问题是您通过将mod1.py作为参数传递给解释器,从而以“ __main__”的身份运行模块。

PEP 328

相对导入使用模块的__name__属性来确定该模块在包层次结构中的位置。如果模块的名称不包含任何包信息(例如,将其设置为“ __main__”),则相对导入将被视为模块是顶级模块,而不论该模块实际位于文件系统上的哪个位置。

在Python 2.6中,他们添加了相对于主模块引用模块的功能。 PEP 366说明了更改。

更新:根据Nick Coghlan的建议,推荐的替代方法是使用-m开关运行软件包中的模块。

Everyone seems to want to tell you what you should be doing rather than just answering the question.

The problem is that you’re running the module as ‘__main__’ by passing the mod1.py as an argument to the interpreter.

From PEP 328:

Relative imports use a module’s __name__ attribute to determine that module’s position in the package hierarchy. If the module’s name does not contain any package information (e.g. it is set to ‘__main__’) then relative imports are resolved as if the module were a top level module, regardless of where the module is actually located on the file system.

In Python 2.6, they’re adding the ability to reference modules relative to the main module. PEP 366 describes the change.

Update: According to Nick Coghlan, the recommended alternative is to run the module inside the package using the -m switch.


回答 1

这是对我有效的解决方案:

我执行as的相对导入 from ..sub2 import mod2 ,然后,如果要运行,mod1.py则转到的父目录,app并使用python -m开关as运行模块 python -m app.sub1.mod1

相对导入发生此问题的真正原因是,相对导入通过获取__name__模块的属性起作用。如果模块直接运行,则__name__设置为__main__,并且不包含有关包结构的任何信息。并且,这就是为什么python抱怨该relative import in non-package错误的原因。

因此,通过使用-m开关,您可以将包结构信息提供给python,通过它可以成功解析相对导入。

在进行相对导入时,我多次遇到此问题。而且,在阅读了所有先前的答案之后,我仍然无法弄清楚如何解决此问题,而无需在所有文件中添加样板代码。(尽管有些评论确实很有帮助,这要感谢@ncoghlan和@XiongChiamiov)

希望这对正在解决相对进口问题的人有所帮助,因为通过PEP确实很有趣。

Here is the solution which works for me:

I do the relative imports as from ..sub2 import mod2 and then, if I want to run mod1.py then I go to the parent directory of app and run the module using the python -m switch as python -m app.sub1.mod1.

The real reason why this problem occurs with relative imports, is that relative imports works by taking the __name__ property of the module. If the module is being directly run, then __name__ is set to __main__ and it doesn’t contain any information about package structure. And, thats why python complains about the relative import in non-package error.

So, by using the -m switch you provide the package structure information to python, through which it can resolve the relative imports successfully.

I have encountered this problem many times while doing relative imports. And, after reading all the previous answers, I was still not able to figure out how to solve it, in a clean way, without needing to put boilerplate code in all files. (Though some of the comments were really helpful, thanks to @ncoghlan and @XiongChiamiov)

Hope this helps someone who is fighting with relative imports problem, because going through PEP is really not fun.


回答 2

main.py
setup.py
app/ ->
    __init__.py
    package_a/ ->
       __init__.py
       module_a.py
    package_b/ ->
       __init__.py
       module_b.py
  1. 你跑python main.py
  2. main.py 确实: import app.package_a.module_a
  3. module_a.py 确实 import app.package_b.module_b

另外2或3可以使用: from app.package_a import module_a

只要您app在PYTHONPATH中具有此功能,便可以使用。main.py可能在那时的任何地方。

因此,您编写了一个setup.py将整个应用程序包和子包复制(安装)到目标系统的python文件夹以及main.py目标系统的脚本文件夹的代码。

main.py
setup.py
app/ ->
    __init__.py
    package_a/ ->
       __init__.py
       module_a.py
    package_b/ ->
       __init__.py
       module_b.py
  1. You run python main.py.
  2. main.py does: import app.package_a.module_a
  3. module_a.py does import app.package_b.module_b

Alternatively 2 or 3 could use: from app.package_a import module_a

That will work as long as you have app in your PYTHONPATH. main.py could be anywhere then.

So you write a setup.py to copy (install) the whole app package and subpackages to the target system’s python folders, and main.py to target system’s script folders.


回答 3

“ Guido将程序包中正在运行的脚本视为反模式”(被拒绝的 PEP-3122

我花了很多时间试图找到解决方案,在Stack Overflow上阅读了相关文章,并对自己说:“一定有更好的方法!”。好像没有。

“Guido views running scripts within a package as an anti-pattern” (rejected PEP-3122)

I have spent so much time trying to find a solution, reading related posts here on Stack Overflow and saying to myself “there must be a better way!”. Looks like there is not.


回答 4

这可以100%解决:

  • 应用/
    • main.py
  • 设置/
    • local_setings.py

在app / main.py中导入settings / local_setting.py:

main.py:

import sys
sys.path.insert(0, "../settings")


try:
    from local_settings import *
except ImportError:
    print('No Import')

This is solved 100%:

  • app/
    • main.py
  • settings/
    • local_setings.py

Import settings/local_setting.py in app/main.py:

main.py:

import sys
sys.path.insert(0, "../settings")


try:
    from local_settings import *
except ImportError:
    print('No Import')

回答 5

def import_path(fullpath):
    """ 
    Import a file with full path specification. Allows one to
    import from anywhere, something __import__ does not do. 
    """
    path, filename = os.path.split(fullpath)
    filename, ext = os.path.splitext(filename)
    sys.path.append(path)
    module = __import__(filename)
    reload(module) # Might be out of date
    del sys.path[-1]
    return module

我正在使用此代码片段从路径导入模块,希望对您有所帮助

def import_path(fullpath):
    """ 
    Import a file with full path specification. Allows one to
    import from anywhere, something __import__ does not do. 
    """
    path, filename = os.path.split(fullpath)
    filename, ext = os.path.splitext(filename)
    sys.path.append(path)
    module = __import__(filename)
    reload(module) # Might be out of date
    del sys.path[-1]
    return module

I’m using this snippet to import modules from paths, hope that helps


回答 6

nosklo's举例说明答案

注意:所有__init__.py文件均为空。

main.py
app/ ->
    __init__.py
    package_a/ ->
       __init__.py
       fun_a.py
    package_b/ ->
       __init__.py
       fun_b.py

app / package_a / fun_a.py

def print_a():
    print 'This is a function in dir package_a'

app / package_b / fun_b.py

from app.package_a.fun_a import print_a
def print_b():
    print 'This is a function in dir package_b'
    print 'going to call a function in dir package_a'
    print '-'*30
    print_a()

main.py

from app.package_b import fun_b
fun_b.print_b()

如果运行,$ python main.py它将返回:

This is a function in dir package_b
going to call a function in dir package_a
------------------------------
This is a function in dir package_a
  • main.py可以: from app.package_b import fun_b
  • fun_b.py确实 from app.package_a.fun_a import print_a

所以文件夹中的文件package_b使用了文件夹中的文件package_a,这就是您想要的。对??

explanation of nosklo's answer with examples

note: all __init__.py files are empty.

main.py
app/ ->
    __init__.py
    package_a/ ->
       __init__.py
       fun_a.py
    package_b/ ->
       __init__.py
       fun_b.py

app/package_a/fun_a.py

def print_a():
    print 'This is a function in dir package_a'

app/package_b/fun_b.py

from app.package_a.fun_a import print_a
def print_b():
    print 'This is a function in dir package_b'
    print 'going to call a function in dir package_a'
    print '-'*30
    print_a()

main.py

from app.package_b import fun_b
fun_b.print_b()

if you run $ python main.py it returns:

This is a function in dir package_b
going to call a function in dir package_a
------------------------------
This is a function in dir package_a
  • main.py does: from app.package_b import fun_b
  • fun_b.py does from app.package_a.fun_a import print_a

so file in folder package_b used file in folder package_a, which is what you want. Right??


回答 7

不幸的是,这是一个sys.path hack,但是效果很好。

我在另一层遇到了这个问题:我已经有一个具有指定名称的模块,但这是错误的模块。

我想要做的是以下操作(我正在使用的模块是module3):

mymodule\
   __init__.py
   mymodule1\
      __init__.py
      mymodule1_1
   mymodule2\
      __init__.py
      mymodule2_1


import mymodule.mymodule1.mymodule1_1  

请注意,我已经安装了mymodule,但是在我的安装中我没有“ mymodule1”

而且我会收到一个ImportError,因为它试图从安装的模块中导入。

我试图做一个sys.path.append,但是没有用。起作用的是sys.path.insert

if __name__ == '__main__':
    sys.path.insert(0, '../..')

有点骇客,但一切正常!因此请记住,如果要决定覆盖其他路径,则需要使用sys.path.insert(0,pathname)使其起作用!这对我来说是一个非常令人沮丧的症结所在,有人说要在sys.path中使用“ append”功能,但是如果您已经定义了一个模块,那是行不通的(我发现这是非常奇怪的行为)

This is unfortunately a sys.path hack, but it works quite well.

I encountered this problem with another layer: I already had a module of the specified name, but it was the wrong module.

what I wanted to do was the following (the module I was working from was module3):

mymodule\
   __init__.py
   mymodule1\
      __init__.py
      mymodule1_1
   mymodule2\
      __init__.py
      mymodule2_1


import mymodule.mymodule1.mymodule1_1  

Note that I have already installed mymodule, but in my installation I do not have “mymodule1”

and I would get an ImportError because it was trying to import from my installed modules.

I tried to do a sys.path.append, and that didn’t work. What did work was a sys.path.insert

if __name__ == '__main__':
    sys.path.insert(0, '../..')

So kind of a hack, but got it all to work! So keep in mind, if you want your decision to override other paths then you need to use sys.path.insert(0, pathname) to get it to work! This was a very frustrating sticking point for me, allot of people say to use the “append” function to sys.path, but that doesn’t work if you already have a module defined (I find it very strange behavior)


回答 8

让我将其放在此处以供我自己参考。我知道这不是很好的Python代码,但是我需要一个脚本来处理我正在处理的项目,所以我想将脚本放在scripts目录中。

import os.path
import sys
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))

Let me just put this here for my own reference. I know that it is not good Python code, but I needed a script for a project I was working on and I wanted to put the script in a scripts directory.

import os.path
import sys
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))

回答 9

正如@EvgeniSergeev在对OP的注释中所说,您可以使用以下.py命令从任意位置的文件导入代码:

import imp

foo = imp.load_source('module.name', '/path/to/file.py')
foo.MyClass()

这是从此SO答案中获取的

As @EvgeniSergeev says in the comments to the OP, you can import code from a .py file at an arbitrary location with:

import imp

foo = imp.load_source('module.name', '/path/to/file.py')
foo.MyClass()

This is taken from this SO answer.


回答 10


回答 11

Python文档中

在Python 2.5中,您可以使用from __future__ import absolute_import指令将导入的行为切换为绝对导入。在将来的版本(可能是Python 2.7)中,此绝对导入行为将成为默认设置。一旦将绝对导入设置为默认设置,import string就将始终找到标准库的版本。建议用户应尽可能多地开始使用绝对导入,因此最好开始编写from pkg import string代码

From Python doc,

In Python 2.5, you can switch import‘s behaviour to absolute imports using a from __future__ import absolute_import directive. This absolute- import behaviour will become the default in a future version (probably Python 2.7). Once absolute imports are the default, import string will always find the standard library’s version. It’s suggested that users should begin using absolute imports as much as possible, so it’s preferable to begin writing from pkg import string in your code


回答 12

我发现将“ PYTHONPATH”环境变量设置为顶层文件夹更容易:

bash$ export PYTHONPATH=/PATH/TO/APP

然后:

import sub1.func1
#...more import

当然,PYTHONPATH是“全局”的,但它并没有给我带来麻烦。

I found it’s more easy to set “PYTHONPATH” enviroment variable to the top folder:

bash$ export PYTHONPATH=/PATH/TO/APP

then:

import sub1.func1
#...more import

of course, PYTHONPATH is “global”, but it didn’t raise trouble for me yet.


回答 13

除了John B所说的,似乎设置__package__变量应该有帮助,而不是更改变量__main__可能会搞砸其他事情。但是据我测试,它并不能完全正常工作。

我遇到了同样的问题sys.path,而据我所知,PEP 328或366都无法完全解决问题,因为两者在一天结束时都需要将包装的标头包括在其中。

我还要提及的是,我没有找到如何格式化应该放入这些变量的字符串的格式。是"package_head.subfolder.module_name"还是什么?

On top of what John B said, it seems like setting the __package__ variable should help, instead of changing __main__ which could screw up other things. But as far as I could test, it doesn’t completely work as it should.

I have the same problem and neither PEP 328 or 366 solve the problem completely, as both, by the end of the day, need the head of the package to be included in sys.path, as far as I could understand.

I should also mention that I did not find how to format the string that should go into those variables. Is it "package_head.subfolder.module_name" or what?


回答 14

您必须将模块的路径附加到PYTHONPATH

export PYTHONPATH="${PYTHONPATH}:/path/to/your/module/"

You have to append the module’s path to PYTHONPATH:

export PYTHONPATH="${PYTHONPATH}:/path/to/your/module/"

re.search和re.match有什么区别?

问题:re.search和re.match有什么区别?

search()Python 模块中的match()函数和有什么区别?re

我已经阅读了文档当前文档),但是我似乎从未记得它。我一直在查找并重新学习它。我希望有人会用示例清楚地回答它,以便(也许)它会贴在我的头上。或者至少我将有一个更好的地方来回答我的问题,并且重新学习它所花的时间会更少。

What is the difference between the search() and match() functions in the Python re module?

I’ve read the documentation (current documentation), but I never seem to remember it. I keep having to look it up and re-learn it. I’m hoping that someone will answer it clearly with examples so that (perhaps) it will stick in my head. Or at least I’ll have a better place to return with my question and it will take less time to re-learn it.


回答 0

re.match锚定在字符串的开头。这与换行无关,因此它与^在模式中使用的方式不同。

重新匹配文档所述

如果字符串开头的零个或多个字符 与正则表达式模式匹配,则返回相应的MatchObject实例。None如果字符串与模式不匹配,则返回;否则返回false。请注意,这与零长度匹配不同。

注意:如果要在字符串中的任何位置找到匹配项,请search() 改用。

re.search搜索整个字符串,如文档所述

扫描字符串以查找正则表达式模式产生匹配项的位置,然后返回相应的MatchObject实例。None如果字符串中没有位置与模式匹配,则返回;否则返回false。请注意,这与在字符串中的某个点找到零长度匹配不同。

因此,如果您需要匹配字符串的开头,或者匹配整个字符串,请使用match。它更快。否则使用search

该文档中有一个专门针对matchvs.的部分search,还涵盖了多行字符串:

基于正则表达式的Python提供两种不同的基本操作:match检查是否有比赛 才刚刚开始的字符串,同时search检查是否有匹配 的任何地方的字符串(这是Perl并默认情况下)。

请注意, 即使使用以:开头的正则表达式match也可能仅在字符串的开头,或者在模式下也紧接换行符之后才匹配 。仅当模式在字符串开头 无论模式如何)或在可选 参数给定的起始位置匹配(无论换行符是否在其前面)时,“ ”操作才会成功。search'^''^'MULTILINEmatchpos

现在,足够的讨论。现在来看一些示例代码:

# example code:
string_with_newlines = """something
someotherthing"""

import re

print re.match('some', string_with_newlines) # matches
print re.match('someother', 
               string_with_newlines) # won't match
print re.match('^someother', string_with_newlines, 
               re.MULTILINE) # also won't match
print re.search('someother', 
                string_with_newlines) # finds something
print re.search('^someother', string_with_newlines, 
                re.MULTILINE) # also finds something

m = re.compile('thing$', re.MULTILINE)

print m.match(string_with_newlines) # no match
print m.match(string_with_newlines, pos=4) # matches
print m.search(string_with_newlines, 
               re.MULTILINE) # also matches

re.match is anchored at the beginning of the string. That has nothing to do with newlines, so it is not the same as using ^ in the pattern.

As the re.match documentation says:

If zero or more characters at the beginning of string match the regular expression pattern, return a corresponding MatchObject instance. Return None if the string does not match the pattern; note that this is different from a zero-length match.

Note: If you want to locate a match anywhere in string, use search() instead.

re.search searches the entire string, as the documentation says:

Scan through string looking for a location where the regular expression pattern produces a match, and return a corresponding MatchObject instance. Return None if no position in the string matches the pattern; note that this is different from finding a zero-length match at some point in the string.

So if you need to match at the beginning of the string, or to match the entire string use match. It is faster. Otherwise use search.

The documentation has a specific section for match vs. search that also covers multiline strings:

Python offers two different primitive operations based on regular expressions: match checks for a match only at the beginning of the string, while search checks for a match anywhere in the string (this is what Perl does by default).

Note that match may differ from search even when using a regular expression beginning with '^': '^' matches only at the start of the string, or in MULTILINE mode also immediately following a newline. The “match” operation succeeds only if the pattern matches at the start of the string regardless of mode, or at the starting position given by the optional pos argument regardless of whether a newline precedes it.

Now, enough talk. Time to see some example code:

# example code:
string_with_newlines = """something
someotherthing"""

import re

print re.match('some', string_with_newlines) # matches
print re.match('someother', 
               string_with_newlines) # won't match
print re.match('^someother', string_with_newlines, 
               re.MULTILINE) # also won't match
print re.search('someother', 
                string_with_newlines) # finds something
print re.search('^someother', string_with_newlines, 
                re.MULTILINE) # also finds something

m = re.compile('thing$', re.MULTILINE)

print m.match(string_with_newlines) # no match
print m.match(string_with_newlines, pos=4) # matches
print m.search(string_with_newlines, 
               re.MULTILINE) # also matches

回答 1

search ⇒在字符串中的任何地方找到东西,然后返回一个匹配对象。

match⇒ 在字符串的开头找到一些内容,然后返回匹配对象。

search ⇒ find something anywhere in the string and return a match object.

match ⇒ find something at the beginning of the string and return a match object.


回答 2

re.search 搜索 ES该模式在整个字符串,而re.match没有搜索不到的格局; 如果没有,则除了在字符串开头匹配外,别无选择。

re.search searches for the pattern throughout the string, whereas re.match does not search the pattern; if it does not, it has no other choice than to match it at start of the string.


回答 3

match比搜索快得多,因此如果不使用regex.search(“ word”),则可以执行regex.match((。*?)word(。*?)),如果您使用数百万个样品。

@ivan_bilan在上面接受的答案下的评论让我开始思考是否有这样的hack是否真的在加速任何事情,所以让我们找出您将真正获得多少性能。

我准备了以下测试套件:

import random
import re
import string
import time

LENGTH = 10
LIST_SIZE = 1000000

def generate_word():
    word = [random.choice(string.ascii_lowercase) for _ in range(LENGTH)]
    word = ''.join(word)
    return word

wordlist = [generate_word() for _ in range(LIST_SIZE)]

start = time.time()
[re.search('python', word) for word in wordlist]
print('search:', time.time() - start)

start = time.time()
[re.match('(.*?)python(.*?)', word) for word in wordlist]
print('match:', time.time() - start)

我进行了10次测量(1M,2M,…,10M个单词),得出以下图表:

产生的直线令人惊讶地(实际上并不那么令人惊讶)直线。鉴于这种特定的模式组合,该search功能(略)更快。该测试的实质是避免过度优化代码。

match is much faster than search, so instead of doing regex.search(“word”) you can do regex.match((.*?)word(.*?)) and gain tons of performance if you are working with millions of samples.

This comment from @ivan_bilan under the accepted answer above got me thinking if such hack is actually speeding anything up, so let’s find out how many tons of performance you will really gain.

I prepared the following test suite:

import random
import re
import string
import time

LENGTH = 10
LIST_SIZE = 1000000

def generate_word():
    word = [random.choice(string.ascii_lowercase) for _ in range(LENGTH)]
    word = ''.join(word)
    return word

wordlist = [generate_word() for _ in range(LIST_SIZE)]

start = time.time()
[re.search('python', word) for word in wordlist]
print('search:', time.time() - start)

start = time.time()
[re.match('(.*?)python(.*?)', word) for word in wordlist]
print('match:', time.time() - start)

I made 10 measurements (1M, 2M, …, 10M words) which gave me the following plot:

The resulting lines are surprisingly (actually not that surprisingly) straight. And the search function is (slightly) faster given this specific pattern combination. The moral of this test: Avoid overoptimizing your code.


回答 4

您可以参考以下示例以了解re.matchand.search 的工作原理

a = "123abc"
t = re.match("[a-z]+",a)
t = re.search("[a-z]+",a)

re.match会回来none,但是re.search会回来abc

You can refer the below example to understand the working of re.match and re.search

a = "123abc"
t = re.match("[a-z]+",a)
t = re.search("[a-z]+",a)

re.match will return none, but re.search will return abc.


回答 5

区别在于,re.match()误导习惯于Perlgrepsed正则表达式匹配的任何人,并且re.search()不会。:-)

正如约翰·D·库克(John D. Cook)所说,要更加清醒一些,re.match()“表现得好像每个模式都以^开头。” 换句话说,re.match('pattern')等于re.search('^pattern')。因此,它锚定了图案的左侧。但这也没有固定模式的右侧:仍然需要终止$

坦白地说,我认为re.match()应该弃用。我很想知道应该保留它的原因。

The difference is, re.match() misleads anyone accustomed to Perl, grep, or sed regular expression matching, and re.search() does not. :-)

More soberly, As John D. Cook remarks, re.match() “behaves as if every pattern has ^ prepended.” In other words, re.match('pattern') equals re.search('^pattern'). So it anchors a pattern’s left side. But it also doesn’t anchor a pattern’s right side: that still requires a terminating $.

Frankly given the above, I think re.match() should be deprecated. I would be interested to know reasons it should be retained.


回答 6

re.match尝试匹配字符串开头的模式。re.search尝试在整个字符串中匹配模式直到找到匹配项。

re.match attempts to match a pattern at the beginning of the string. re.search attempts to match the pattern throughout the string until it finds a match.


回答 7

矮得多:

  • search 扫描整个字符串。

  • match 仅扫描字符串的开头。

以下Ex表示:

>>> a = "123abc"
>>> re.match("[a-z]+",a)
None
>>> re.search("[a-z]+",a)
abc

Much shorter:

  • search scans through the whole string.

  • match scans only the beginning of the string.

Following Ex says it:

>>> a = "123abc"
>>> re.match("[a-z]+",a)
None
>>> re.search("[a-z]+",a)
abc

您如何从字符串列表中创建逗号分隔的字符串?

问题:您如何从字符串列表中创建逗号分隔的字符串?

您最好采用哪种方法来连接序列中的字符串,以便在每两个连续对之间添加一个逗号。也就是说,例如,您如何映射['a', 'b', 'c']'a,b,c'?(案例['s'][]应该分别映射到's'''。)

我通常最终会使用类似的东西''.join(map(lambda x: x+',',l))[:-1],但也会感到有些不满意。

What would be your preferred way to concatenate strings from a sequence such that between every two consecutive pairs a comma is added. That is, how do you map, for instance, ['a', 'b', 'c'] to 'a,b,c'? (The cases ['s'] and [] should be mapped to 's' and '', respectively.)

I usually end up using something like ''.join(map(lambda x: x+',',l))[:-1], but also feeling somewhat unsatisfied.


回答 0

my_list = ['a', 'b', 'c', 'd']
my_string = ','.join(my_list)
'a,b,c,d'

如果列表包含整数,则此方法无效


并且如果列表包含非字符串类型(例如整数,浮点数,布尔值,无),则请执行以下操作:

my_string = ','.join(map(str, my_list)) 
my_list = ['a', 'b', 'c', 'd']
my_string = ','.join(my_list)
'a,b,c,d'

This won’t work if the list contains integers


And if the list contains non-string types (such as integers, floats, bools, None) then do:

my_string = ','.join(map(str, my_list)) 

回答 1

为什么map/ lambda魔术?这不行吗?

>>> foo = ['a', 'b', 'c']
>>> print(','.join(foo))
a,b,c
>>> print(','.join([]))

>>> print(','.join(['a']))
a

如果列表中有数字,则可以使用列表理解:

>>> ','.join([str(x) for x in foo])

或生成器表达式:

>>> ','.join(str(x) for x in foo)

Why the map/lambda magic? Doesn’t this work?

>>> foo = ['a', 'b', 'c']
>>> print(','.join(foo))
a,b,c
>>> print(','.join([]))

>>> print(','.join(['a']))
a

In case if there are numbers in the list, you could use list comprehension:

>>> ','.join([str(x) for x in foo])

or a generator expression:

>>> ','.join(str(x) for x in foo)

回答 2

",".join(l)不适用于所有情况。我建议将CSV模块与StringIO一起使用

import StringIO
import csv

l = ['list','of','["""crazy"quotes"and\'',123,'other things']

line = StringIO.StringIO()
writer = csv.writer(line)
writer.writerow(l)
csvcontent = line.getvalue()
# 'list,of,"[""""""crazy""quotes""and\'",123,other things\r\n'

",".join(l) will not work for all cases. I’d suggest using the csv module with StringIO

import StringIO
import csv

l = ['list','of','["""crazy"quotes"and\'',123,'other things']

line = StringIO.StringIO()
writer = csv.writer(line)
writer.writerow(l)
csvcontent = line.getvalue()
# 'list,of,"[""""""crazy""quotes""and\'",123,other things\r\n'

回答 3

这是Python 3.0中允许非字符串列表项的替代解决方案:

>>> alist = ['a', 1, (2, 'b')]
  • 标准方式

    >>> ", ".join(map(str, alist))
    "a, 1, (2, 'b')"
  • 替代解决方案

    >>> import io
    >>> s = io.StringIO()
    >>> print(*alist, file=s, sep=', ', end='')
    >>> s.getvalue()
    "a, 1, (2, 'b')"

注意:逗号后的空格是故意的。

Here is a alternative solution in Python 3.0 which allows non-string list items:

>>> alist = ['a', 1, (2, 'b')]
  • a standard way

    >>> ", ".join(map(str, alist))
    "a, 1, (2, 'b')"
    
  • the alternative solution

    >>> import io
    >>> s = io.StringIO()
    >>> print(*alist, file=s, sep=', ', end='')
    >>> s.getvalue()
    "a, 1, (2, 'b')"
    

NOTE: The space after comma is intentional.


回答 4

你不只是想要:

",".join(l)

显然,如果您需要在值中引用/转义逗号等,它将变得更加复杂。在这种情况下,我建议您查看标准库中的csv模块:

https://docs.python.org/library/csv.html

Don’t you just want:

",".join(l)

Obviously it gets more complicated if you need to quote/escape commas etc in the values. In that case I would suggest looking at the csv module in the standard library:

https://docs.python.org/library/csv.html


回答 5

彼得·霍夫曼(Peter Hoffmann)

使用生成器表达式的好处是还可以生成迭代器,但可以节省导入itertools的时间。此外,列表推导通常首选映射,因此,我希望生成器表达式比imap首选。

>>> l = [1, "foo", 4 ,"bar"]
>>> ",".join(str(bit) for bit in l)
'1,foo,4,bar' 

@Peter Hoffmann

Using generator expressions has the benefit of also producing an iterator but saves importing itertools. Furthermore, list comprehensions are generally preferred to map, thus, I’d expect generator expressions to be preferred to imap.

>>> l = [1, "foo", 4 ,"bar"]
>>> ",".join(str(bit) for bit in l)
'1,foo,4,bar' 

回答 6

>>> my_list = ['A', '', '', 'D', 'E',]
>>> ",".join([str(i) for i in my_list if i])
'A,D,E'

my_list可以包含任何类型的变量。这样可以避免结果'A,,,D,E'

>>> my_list = ['A', '', '', 'D', 'E',]
>>> ",".join([str(i) for i in my_list if i])
'A,D,E'

my_list may contain any type of variables. This avoid the result 'A,,,D,E'.


回答 7

l=['a', 1, 'b', 2]

print str(l)[1:-1]

Output: "'a', 1, 'b', 2"
l=['a', 1, 'b', 2]

print str(l)[1:-1]

Output: "'a', 1, 'b', 2"

回答 8

使用列表推导的@ jmanning2k不利于创建新的临时列表。更好的解决方案是使用itertools.imap返回一个迭代器

from itertools import imap
l = [1, "foo", 4 ,"bar"]
",".join(imap(str, l))

@jmanning2k using a list comprehension has the downside of creating a new temporary list. The better solution would be using itertools.imap which returns an iterator

from itertools import imap
l = [1, "foo", 4 ,"bar"]
",".join(imap(str, l))

回答 9

这是清单的例子

>>> myList = [['Apple'],['Orange']]
>>> myList = ','.join(map(str, [i[0] for i in myList])) 
>>> print "Output:", myList
Output: Apple,Orange

更准确的:-

>>> myList = [['Apple'],['Orange']]
>>> myList = ','.join(map(str, [type(i) == list and i[0] for i in myList])) 
>>> print "Output:", myList
Output: Apple,Orange

示例2:

myList = ['Apple','Orange']
myList = ','.join(map(str, myList)) 
print "Output:", myList
Output: Apple,Orange

Here is an example with list

>>> myList = [['Apple'],['Orange']]
>>> myList = ','.join(map(str, [i[0] for i in myList])) 
>>> print "Output:", myList
Output: Apple,Orange

More Accurate:-

>>> myList = [['Apple'],['Orange']]
>>> myList = ','.join(map(str, [type(i) == list and i[0] for i in myList])) 
>>> print "Output:", myList
Output: Apple,Orange

Example 2:-

myList = ['Apple','Orange']
myList = ','.join(map(str, myList)) 
print "Output:", myList
Output: Apple,Orange

回答 10

我要说的csv是,库是这里唯一明智的选择,因为它是为应对所有csv用例(例如字符串中的逗号)而构建的。

要将列表输出l到.csv文件,请执行以下操作:

import csv
with open('some.csv', 'w', newline='') as f:
    writer = csv.writer(f)
    writer.writerow(l)  # this will output l as a single row.  

也可以用于writer.writerows(iterable)将多行输出到csv。

此示例与Python 3兼容,此处使用的另一个答案StringIO是Python 2。

I would say the csv library is the only sensible option here, as it was built to cope with all csv use cases such as commas in a string, etc.

To output a list l to a .csv file:

import csv
with open('some.csv', 'w', newline='') as f:
    writer = csv.writer(f)
    writer.writerow(l)  # this will output l as a single row.  

It is also possible to use writer.writerows(iterable) to output multiple rows to csv.

This example is compatible with Python 3, as the other answer here used StringIO which is Python 2.


回答 11

除非我缺少任何东西,否则','.join(foo)应该做您所要的。

>>> ','.join([''])
''
>>> ','.join(['s'])
's'
>>> ','.join(['a','b','c'])
'a,b,c'

(编辑:正如jmanning2k指出的那样,

','.join([str(x) for x in foo])

是更安全且相当Pythonic的,尽管如果元素可以包含逗号,则生成的字符串将很难解析-那时,您需要csv模块的全部功能,正如Douglas在他的回答中指出的那样。)

Unless I’m missing something, ','.join(foo) should do what you’re asking for.

>>> ','.join([''])
''
>>> ','.join(['s'])
's'
>>> ','.join(['a','b','c'])
'a,b,c'

(edit: and as jmanning2k points out,

','.join([str(x) for x in foo])

is safer and quite Pythonic, though the resulting string will be difficult to parse if the elements can contain commas — at that point, you need the full power of the csv module, as Douglas points out in his answer.)


回答 12

我的两分钱。我喜欢更简单的python单行代码:

>>> from itertools import imap, ifilter
>>> l = ['a', '', 'b', 1, None]
>>> ','.join(imap(str, ifilter(lambda x: x, l)))
a,b,1
>>> m = ['a', '', None]
>>> ','.join(imap(str, ifilter(lambda x: x, m)))
'a'

这是pythonic,适用于字符串,数字,无和空字符串。它很短并且满足要求。如果列表中不包含数字,则可以使用以下更简单的变体:

>>> ','.join(ifilter(lambda x: x, l))

同样,该解决方案不会创建新列表,而是使用迭代器,如@Peter Hoffmann指出的(谢谢)。

My two cents. I like simpler an one-line code in python:

>>> from itertools import imap, ifilter
>>> l = ['a', '', 'b', 1, None]
>>> ','.join(imap(str, ifilter(lambda x: x, l)))
a,b,1
>>> m = ['a', '', None]
>>> ','.join(imap(str, ifilter(lambda x: x, m)))
'a'

It’s pythonic, works for strings, numbers, None and empty string. It’s short and satisfies the requirements. If the list is not going to contain numbers, we can use this simpler variation:

>>> ','.join(ifilter(lambda x: x, l))

Also this solution doesn’t create a new list, but uses an iterator, like @Peter Hoffmann pointed (thanks).


如何获得字符在Python中的位置?

问题:如何获得字符在Python中的位置?

如何在python中的字符串中获取字符的位置?

How can I get the position of a character inside a string in python?


回答 0

这有两个String的方法,find()index()。两者之间的区别在于找不到搜索字符串时会发生什么。 find()回报-1index()加薪ValueError

使用 find()

>>> myString = 'Position of a character'
>>> myString.find('s')
2
>>> myString.find('x')
-1

使用 index()

>>> myString = 'Position of a character'
>>> myString.index('s')
2
>>> myString.index('x')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: substring not found

Python手册

string.find(s, sub[, start[, end]])
返回s中找到子字符串sub的最低索引,使sub完全包含在中s[start:end]-1失败返回。开始结束以及负值的解释默认值与切片相同。

和:

string.index(s, sub[, start[, end]])
喜欢,find()但是ValueError在找不到子字符串时提高。

There are two string methods for this, find() and index(). The difference between the two is what happens when the search string isn’t found. find() returns -1 and index() raises ValueError.

Using find()

>>> myString = 'Position of a character'
>>> myString.find('s')
2
>>> myString.find('x')
-1

Using index()

>>> myString = 'Position of a character'
>>> myString.index('s')
2
>>> myString.index('x')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: substring not found

From the Python manual

string.find(s, sub[, start[, end]])
Return the lowest index in s where the substring sub is found such that sub is wholly contained in s[start:end]. Return -1 on failure. Defaults for start and end and interpretation of negative values is the same as for slices.

And:

string.index(s, sub[, start[, end]])
Like find() but raise ValueError when the substring is not found.


回答 1

仅出于完整性考虑,如果需要查找字符串中字符的所有位置,可以执行以下操作:

s = 'shak#spea#e'
c = '#'
print [pos for pos, char in enumerate(s) if char == c]

它将返回 [4, 9]

Just for a sake of completeness, if you need to find all positions of a character in a string, you can do the following:

s = 'shak#spea#e'
c = '#'
print [pos for pos, char in enumerate(s) if char == c]

which will return [4, 9]


回答 2

>>> s="mystring"
>>> s.index("r")
4
>>> s.find("r")
4

“长ed”方式

>>> for i,c in enumerate(s):
...   if "r"==c: print i
...
4

得到子串,

>>> s="mystring"
>>> s[4:10]
'ring'
>>> s="mystring"
>>> s.index("r")
4
>>> s.find("r")
4

“Long winded” way

>>> for i,c in enumerate(s):
...   if "r"==c: print i
...
4

to get substring,

>>> s="mystring"
>>> s[4:10]
'ring'

回答 3

只是为了完成,如果要在文件名中找到扩展名以进行检查,则需要找到最后一个“。”,在这种情况下,请使用rfind:

path = 'toto.titi.tata..xls'
path.find('.')
4
path.rfind('.')
15

就我而言,我使用以下命令,无论完整的文件名是什么,它都可以工作:

filename_without_extension = complete_name[:complete_name.rfind('.')]

Just for completion, in the case I want to find the extension in a file name in order to check it, I need to find the last ‘.’, in this case use rfind:

path = 'toto.titi.tata..xls'
path.find('.')
4
path.rfind('.')
15

in my case, I use the following, which works whatever the complete file name is:

filename_without_extension = complete_name[:complete_name.rfind('.')]

回答 4

当字符串包含重复字符时会发生什么?从我的经验中,index()我看到重复的结果会返回相同的索引。

例如:

s = 'abccde'
for c in s:
    print('%s, %d' % (c, s.index(c)))

会返回:

a, 0
b, 1
c, 2
c, 2
d, 4

在这种情况下,您可以执行以下操作:

for i, character in enumerate(my_string):
   # i is the position of the character in the string

What happens when the string contains a duplicate character? from my experience with index() I saw that for duplicate you get back the same index.

For example:

s = 'abccde'
for c in s:
    print('%s, %d' % (c, s.index(c)))

would return:

a, 0
b, 1
c, 2
c, 2
d, 4

In that case you can do something like that:

for i, character in enumerate(my_string):
   # i is the position of the character in the string

回答 5

string.find(character)  
string.index(character)  

也许您想看一下文档,找出两者之间的区别。

string.find(character)  
string.index(character)  

Perhaps you’d like to have a look at the documentation to find out what the difference between the two is.


回答 6

一个字符可能在字符串中多次出现。例如,在字符串中sentence,位置eis是1, 4, 7(因为索引通常从零开始)。但是我发现这是两个函数,find()并且index()返回字符的第一个位置。因此,这样做可以解决此问题:

def charposition(string, char):
    pos = [] #list to store positions for each 'char' in 'string'
    for n in range(len(string)):
        if string[n] == char:
            pos.append(n)
    return pos

s = "sentence"
print(charposition(s, 'e')) 

#Output: [1, 4, 7]

A character might appear multiple times in a string. For example in a string sentence, position of e is 1, 4, 7 (because indexing usually starts from zero). but what I find is both of the functions find() and index() returns first position of a character. So, this can be solved doing this:

def charposition(string, char):
    pos = [] #list to store positions for each 'char' in 'string'
    for n in range(len(string)):
        if string[n] == char:
            pos.append(n)
    return pos

s = "sentence"
print(charposition(s, 'e')) 

#Output: [1, 4, 7]

回答 7

more_itertools.locate 是一种第三方工具,用于查找满足条件的所有项目的索引。

在这里,我们找到字母的所有索引位置"i"

import more_itertools as mit


s = "supercalifragilisticexpialidocious"
list(mit.locate(s, lambda x: x == "i"))
# [8, 13, 15, 18, 23, 26, 30]

more_itertools.locate is a third-party tool that finds all indicies of items that satisfy a condition.

Here we find all index locations of the letter "i".

import more_itertools as mit


s = "supercalifragilisticexpialidocious"
list(mit.locate(s, lambda x: x == "i"))
# [8, 13, 15, 18, 23, 26, 30]

回答 8

使用numpy的解决方案可以快速访问所有索引:

string_array = np.array(list(my_string))
char_indexes = np.where(string_array == 'C')

A solution with numpy for quick access to all indexes:

string_array = np.array(list(my_string))
char_indexes = np.where(string_array == 'C')

用户输入和命令行参数

问题:用户输入和命令行参数

我如何拥有a)可以接受用户输入的Python脚本,以及如何使b)从命令行运行时读取参数?

How do I have a Python script that a) can accept user input and how do I make it b) read in arguments if run from the command line?


回答 0

要读取用户输入,您可以尝试使用cmd模块轻松创建一个迷你命令行解释器(带有帮助文本和自动完成功能),以及raw_inputinput用于Python 3+)从用户读取一行文本的模块。

text = raw_input("prompt")  # Python 2
text = input("prompt")  # Python 3

命令行输入在中sys.argv。在脚本中尝试:

import sys
print (sys.argv)

有两个用于解析命令行选项的模块:(optparse自Python 2.7起不推荐使用,argparse而是使用)和getopt。如果只想向脚本输入文件,请注意的功能fileinput

Python库参考是你的朋友。

To read user input you can try the cmd module for easily creating a mini-command line interpreter (with help texts and autocompletion) and raw_input (input for Python 3+) for reading a line of text from the user.

text = raw_input("prompt")  # Python 2
text = input("prompt")  # Python 3

Command line inputs are in sys.argv. Try this in your script:

import sys
print (sys.argv)

There are two modules for parsing command line options: optparse (deprecated since Python 2.7, use argparse instead) and getopt. If you just want to input files to your script, behold the power of fileinput.

The Python library reference is your friend.


回答 1

var = raw_input("Please enter something: ")
print "you entered", var

或对于Python 3:

var = input("Please enter something: ")
print("You entered: " + var)
var = raw_input("Please enter something: ")
print "you entered", var

Or for Python 3:

var = input("Please enter something: ")
print("You entered: " + var)

回答 2

raw_input在Python 3.x中不再可用。但是raw_input已被重命名input,因此存在相同的功能。

input_var = input("Enter something: ")
print ("you entered " + input_var) 

变更文件

raw_input is no longer available in Python 3.x. But raw_input was renamed input, so the same functionality exists.

input_var = input("Enter something: ")
print ("you entered " + input_var) 

Documentation of the change


回答 3

处理命令行参数的最佳方法是argparse模块。

使用raw_input()来获取用户输入。如果导入,readline module您的用户将具有行编辑和历史记录。

The best way to process command line arguments is the argparse module.

Use raw_input() to get user input. If you import the readline module your users will have line editing and history.


回答 4

input除非您知道自己在做什么,否则请小心不要使用该功能。与不同raw_inputinput它将接受任何python表达式,因此有点像eval

Careful not to use the input function, unless you know what you’re doing. Unlike raw_input, input will accept any python expression, so it’s kinda like eval


回答 5

这个简单的程序可以帮助您了解如何从命令行输入用户输入以及如何显示有关传递无效参数的帮助。

import argparse
import sys

try:
     parser = argparse.ArgumentParser()
     parser.add_argument("square", help="display a square of a given number",
                type=int)
    args = parser.parse_args()

    #print the square of user input from cmd line.
    print args.square**2

    #print all the sys argument passed from cmd line including the program name.
    print sys.argv

    #print the second argument passed from cmd line; Note it starts from ZERO
    print sys.argv[1]
except:
    e = sys.exc_info()[0]
    print e

1)求5的平方根

C:\Users\Desktop>python -i emp.py 5
25
['emp.py', '5']
5

2)传递数字以外的无效参数

C:\Users\bgh37516\Desktop>python -i emp.py five
usage: emp.py [-h] square
emp.py: error: argument square: invalid int value: 'five'
<type 'exceptions.SystemExit'>

This simple program helps you in understanding how to feed the user input from command line and to show help on passing invalid argument.

import argparse
import sys

try:
     parser = argparse.ArgumentParser()
     parser.add_argument("square", help="display a square of a given number",
                type=int)
    args = parser.parse_args()

    #print the square of user input from cmd line.
    print args.square**2

    #print all the sys argument passed from cmd line including the program name.
    print sys.argv

    #print the second argument passed from cmd line; Note it starts from ZERO
    print sys.argv[1]
except:
    e = sys.exc_info()[0]
    print e

1) To find the square root of 5

C:\Users\Desktop>python -i emp.py 5
25
['emp.py', '5']
5

2) Passing invalid argument other than number

C:\Users\bgh37516\Desktop>python -i emp.py five
usage: emp.py [-h] square
emp.py: error: argument square: invalid int value: 'five'
<type 'exceptions.SystemExit'>

回答 6

使用“ raw_input”从控制台/终端输入。

如果您只想使用命令行参数,例如文件名或其他名称,例如

$ python my_prog.py file_name.txt

那么你可以使用sys.argv …

import sys
print sys.argv

sys.argv是一个列表,其中0是程序名称,因此在上面的示例中sys.argv [1]将是“ file_name.txt”

如果要使用命令行选项完整选项,请使用optparse模块。

佩夫

Use ‘raw_input’ for input from a console/terminal.

if you just want a command line argument like a file name or something e.g.

$ python my_prog.py file_name.txt

then you can use sys.argv…

import sys
print sys.argv

sys.argv is a list where 0 is the program name, so in the above example sys.argv[1] would be “file_name.txt”

If you want to have full on command line options use the optparse module.

Pev


回答 7

如果您运行的是Python <2.7,则需要optparse,如文档所述,它将创建一个接口,以连接在运行应用程序时调用的命令行参数。

但是,在python≥2.7中,不建议使用optparse,并如上所述将其替换为argparse。来自文档的快速示例…

以下代码是一个Python程序,它接收一个整数列表并产生总和或最大值:

import argparse

parser = argparse.ArgumentParser(description='Process some integers.')
parser.add_argument('integers', metavar='N', type=int, nargs='+',
                   help='an integer for the accumulator')
parser.add_argument('--sum', dest='accumulate', action='store_const',
                   const=sum, default=max,
                   help='sum the integers (default: find the max)')

args = parser.parse_args()
print args.accumulate(args.integers)

If you are running Python <2.7, you need optparse, which as the doc explains will create an interface to the command line arguments that are called when your application is run.

However, in Python ≥2.7, optparse has been deprecated, and was replaced with the argparse as shown above. A quick example from the docs…

The following code is a Python program that takes a list of integers and produces either the sum or the max:

import argparse

parser = argparse.ArgumentParser(description='Process some integers.')
parser.add_argument('integers', metavar='N', type=int, nargs='+',
                   help='an integer for the accumulator')
parser.add_argument('--sum', dest='accumulate', action='store_const',
                   const=sum, default=max,
                   help='sum the integers (default: find the max)')

args = parser.parse_args()
print args.accumulate(args.integers)

回答 8

从Python开始 3.22.7中,现在有用于处理命令行参数的argparse

As of Python 3.2 2.7, there is now argparse for processing command line arguments.


回答 9

如果是3.x版本,则只需使用:

variantname = input()

例如,您要输入8:

x = input()
8

x等于8,但是它将是一个字符串,除非您另行定义。

因此,您可以使用convert命令,例如:

a = int(x) * 1.1343
print(round(a, 2)) # '9.07'
9.07

If it’s a 3.x version then just simply use:

variantname = input()

For example, you want to input 8:

x = input()
8

x will equal 8 but it’s going to be a string except if you define it otherwise.

So you can use the convert command, like:

a = int(x) * 1.1343
print(round(a, 2)) # '9.07'
9.07

回答 10

在Python 2中:

data = raw_input('Enter something: ')
print data

在Python 3中:

data = input('Enter something: ')
print(data)

In Python 2:

data = raw_input('Enter something: ')
print data

In Python 3:

data = input('Enter something: ')
print(data)

回答 11

import six

if six.PY2:
    input = raw_input

print(input("What's your name? "))
import six

if six.PY2:
    input = raw_input

print(input("What's your name? "))

如何从虚拟环境内部更新点子本身?

问题:如何从虚拟环境内部更新点子本身?

我可以更新点子管理的软件包,但是如何更新点子本身?据介绍pip --version,我目前在virtualenv中安装了pip 1.1,我想更新到最新版本。

这是什么命令?我需要使用distribute还是本机pip或virtualenv命令?我已经尝试过pip update,并pip update pip没有成功。

I’m able to update pip-managed packages, but how do I update pip itself? According to pip --version, I currently have pip 1.1 installed in my virtualenv and I want to update to the latest version.

What’s the command for that? Do I need to use distribute or is there a native pip or virtualenv command? I’ve already tried pip update and pip update pip with no success.


回答 0

pip仅仅是一个的PyPI包像任何其他; 您可以像升级任何软件包一样使用它来升级自身:

pip install --upgrade pip

在Windows上,推荐的命令是:

python -m pip install --upgrade pip

pip is just a PyPI package like any other; you could use it to upgrade itself the same way you would upgrade any package:

pip install --upgrade pip

On Windows the recommended command is:

python -m pip install --upgrade pip

回答 1

更安全的方法是通过python模块运行pip

python -m pip install -U pip

在Windows上,尝试替换自身的二进制文件似乎存在问题,此方法可解决该限制。

The more safe method is to run pip though a python module:

python -m pip install -U pip

On windows there seem to be a problem with binaries that try to replace themselves, this method works around that limitation.


回答 2

就我而言,我的pip版本已损坏,因此更新本身无法进行。

固定:

(inside virtualenv):easy_install -U pip

In my case my pip version was broken so the update by itself would not work.

Fix:

(inside virtualenv):easy_install -U pip

回答 3

我在Debian Jessie下尝试了上面提到的所有这些解决方案。它们不起作用,因为它只需要由debian软件包管理器编译的最新版本1.5.6相当于6.0.x版本。某些使用pip作为前提条件的软件包将无法正常运行,例如spaCy(需要使用–no-cache-dir选项才能正常运行)。

因此,解决这些问题的实际最佳方法是运行从wget下载的get-pip.py,它是从网站或使用curl进行的,如下所示:

 wget https://bootstrap.pypa.io/get-pip.py -O ./get-pip.py
 python ./get-pip.py
 python3 ./get-pip.py

这将安装当前版本,在编写此解决方案时为9.0.1,这远远超出了Debian提供的功能。

 $ pip --version
 pip 9.0.1 from /home/myhomedir/myvirtualenvdir/lib/python2.7/dist-packages (python 2.7)
 $ pip3 --version
 pip 9.0.1 from /home/myhomedir/myvirtualenvdir/lib/python3.4/site-packages (python 3.4)

I tried all of these solutions mentioned above under Debian Jessie. They don’t work, because it just takes the latest version compile by the debian package manager which is 1.5.6 which equates to version 6.0.x. Some packages that use pip as prerequisites will not work as a results, such as spaCy (which needs the option –no-cache-dir to function correctly).

So the actual best way to solve these problems is to run get-pip.py downloaded using wget, from the website or using curl as follows:

 wget https://bootstrap.pypa.io/get-pip.py -O ./get-pip.py
 python ./get-pip.py
 python3 ./get-pip.py

This will install the current version which at the time of writing this solution is 9.0.1 which is way beyond what Debian provides.

 $ pip --version
 pip 9.0.1 from /home/myhomedir/myvirtualenvdir/lib/python2.7/dist-packages (python 2.7)
 $ pip3 --version
 pip 9.0.1 from /home/myhomedir/myvirtualenvdir/lib/python3.4/site-packages (python 3.4)

回答 4

由于可怕的证书问题,使用’ pip install –upgrade pip ‘ 升级pip 并不总是有效:确认ssl证书时出现问题:[SSL:TLSV1_ALERT_PROTOCOL_VERSION] tlsv1警报协议版本

我喜欢对虚拟环境使用单行命令:

curl https://bootstrap.pypa.io/get-pip.py | python -

或者,如果您想将其安装在宽盒中,则需要

curl https://bootstrap.pypa.io/get-pip.py | sudo python -

如果要在自动化脚本中运行时使输出静音,则可以给curl -s标志。

Upgrading pip using ‘pip install –upgrade pip‘ does not always work because of the dreaded cert issue: There was a problem confirming the ssl certificate: [SSL: TLSV1_ALERT_PROTOCOL_VERSION] tlsv1 alert protocol version

I like to use the one line command for virtual envs:

curl https://bootstrap.pypa.io/get-pip.py | python -

Or if you want to install it box wide you will need

curl https://bootstrap.pypa.io/get-pip.py | sudo python -

you can give curl a -s flag if you want to silence the output when running in an automation script.


回答 5

就我而言,这是从Debian Stable中的终端命令行执行的

python3 -m pip install --upgrade pip

In my case this worked from the terminal command line in Debian Stable

python3 -m pip install --upgrade pip

回答 6

为了使它对我有用,我必须使用Python命令提示符(在VS CODE的WIN10上)在Python目录中进行深入研究。就我而言,它位于我的“ AppData \ Local \ Programs \ Python \ python35-32”目录中。从现在开始,我执行命令…

python -m pip install --upgrade pip

这很有效,我很好。

To get this to work for me I had to drill down in the Python directory using the Python command prompt (on WIN10 from VS CODE). In my case it was in my “AppData\Local\Programs\Python\python35-32” directory. From there now I ran the command…

python -m pip install --upgrade pip

This worked and I’m good to go.


回答 7

使用管理员权限打开命令提示符,然后重复以下命令:

python -m pip install --upgrade pip

Open Command Prompt with Administrator Permissions, and repeat the command:

python -m pip install --upgrade pip

回答 8

pip版本10有问题。它将显示为错误:

ubuntu@mymachine-:~/mydir$ sudo pip install --upgrade pip
Traceback (most recent call last):
  File "/usr/bin/pip", line 9, in <module>
    from pip import main
ImportError: cannot import name main

解决方案是在要升级的venv中,然后运行:

sudo myvenv/bin/pip install --upgrade pip

而不只是

sudo pip install --upgrade pip

pip version 10 has an issue. It will manifest as the error:

ubuntu@mymachine-:~/mydir$ sudo pip install --upgrade pip
Traceback (most recent call last):
  File "/usr/bin/pip", line 9, in <module>
    from pip import main
ImportError: cannot import name main

The solution is to be in the venv you want to upgrade and then run:

sudo myvenv/bin/pip install --upgrade pip

rather than just

sudo pip install --upgrade pip

回答 9

如果您使用venv,则任何更新到pip的安装都将导致升级系统pip,而不是venv pip。您还需要升级pip引导程序包。

  python3 -m pip install --upgrade pip setuptools wheel

In case you are using venv any update to pip install will result in upgrading the system pip instead of the venv pip. You need to upgrade the pip bootstrapping packages as well.

  python3 -m pip install --upgrade pip setuptools wheel

回答 10

我已经在C:\ Python \ Python36中安装了Python,因此转到Windows命令提示符并键入“ cd C:\ Python \ Python36”以获取正确的目录。然后输入“ python -m install –upgrade pip”全部好!

I had installed Python in C:\Python\Python36 so I went to the Windows command prompt and typed “cd C:\Python\Python36 to get to the right directory. Then entered the “python -m install –upgrade pip” all good!


回答 11

在Windows 7笔记本电脑上,正确安装最新版本的pip的正确方法是:

python.exe -m pip install --upgrade pip

On my lap-top with Windows 7 the right way to install latest version of pip is:

python.exe -m pip install --upgrade pip

回答 12

单行Python程序
我发现的最好方法是编写一个单行程序,该程序可以下载并运行官方的get-pip脚本。参见下面的代码。

官方文档建议使用curl下载get-pip脚本,但是由于我在Windows上工作且未安装curl,因此我更喜欢使用python本身来下载和运行脚本。

这是可以使用Python 3通过命令行运行的单行程序:

python -c "import urllib.request; exec(urllib.request.urlopen('https://bootstrap.pypa.io/get-pip.py').read())"

根据安装说明,该行将获取官方的“ get-pip.py”脚本,并使用“ exec”命令执行该脚本。

对于Python2,您可以将“ urllib.request”替换为“ urllib2”:

python -c "import urllib2; exec(urllib2.urlopen('https://bootstrap.pypa.io/get-pip.py').read())"

预防措施
值得注意的是,盲目运行任何python脚本本质上都是危险的。因此,官方说明建议在运行之前下载脚本并进行检查。

就是说,许多人实际上并不检查代码,而只是运行它。这一单行程序使这一过程变得更加容易。

Single Line Python Program
The best way I have found is to write a single line program that downloads and runs the official get-pip script. See below for the code.

The official docs recommend using curl to download the get-pip script, but since I work on windows and don’t have curl installed I prefer using python itself to download and run the script.

Here is the single line program that can be run via the command line using Python 3:

python -c "import urllib.request; exec(urllib.request.urlopen('https://bootstrap.pypa.io/get-pip.py').read())"

This line gets the official “get-pip.py” script as per the installation notes and executes the script with the “exec” command.

For Python2 you would replace “urllib.request” with “urllib2”:

python -c "import urllib2; exec(urllib2.urlopen('https://bootstrap.pypa.io/get-pip.py').read())"

Precautions
It’s worth noting that running any python script blindly is inherently dangerous. For this reason, the official instructions recommend downloading the script and inspecting it before running.

That said, many people don’t actually inspect the code and just run it. This one-line program makes that easier.


回答 13

我在树莓派上遇到了类似的问题。

问题在于http需要SSL,因此我需要强制它使用https来解决此要求。

sudo pip install --upgrade pip --index-url=https://pypi.python.org/simple

要么

sudo pip-3.2 --upgrade pip --index-url=https://pypi.python.org/simple/

I had a similar problem on a raspberry pi.

The problem was that http requires SSL and so I needed to force it to use https to get around this requirement.

sudo pip install --upgrade pip --index-url=https://pypi.python.org/simple

or

sudo pip-3.2 --upgrade pip --index-url=https://pypi.python.org/simple/

回答 14

我处于类似情况,想更新urllib3软件包。对我有用的是:

pip3 install --upgrade --force-reinstall --ignore-installed urllib3==1.25.3

I was in a similar situation and wanted to update urllib3 package. What worked for me was:

pip3 install --upgrade --force-reinstall --ignore-installed urllib3==1.25.3

回答 15

很简单。只需从https://bootstrap.pypa.io/get-pip.py下载pip 。将文件保存在forlder或dekstop中。我将文件保存在D盘中,然后从命令提示符导航到下载pip的文件夹。然后在那打

python -get-pip.py

Very Simple. Just download pip from https://bootstrap.pypa.io/get-pip.py . Save the file in some forlder or dekstop. I saved the file in my D drive.Then from your command prompt navigate to the folder where you have downloaded pip. Then type there

python -get-pip.py


获取map()以在Python 3.x中返回列表

问题:获取map()以在Python 3.x中返回列表

我正在尝试将列表映射为十六进制,然后在其他地方使用该列表。在python 2.6中,这很简单:

答: Python 2.6:

>>> map(chr, [66, 53, 0, 94])
['B', '5', '\x00', '^']

但是,在Python 3.1中,以上代码返回一个map对象。

B: Python 3.1:

>>> map(chr, [66, 53, 0, 94])
<map object at 0x00AF5570>

如何在Python 3.x上检索映射列表(如上面的A所示)?

另外,还有更好的方法吗?我的初始列表对象大约有45个项目,并且id喜欢将它们转换为十六进制。

I’m trying to map a list into hex, and then use the list elsewhere. In python 2.6, this was easy:

A: Python 2.6:

>>> map(chr, [66, 53, 0, 94])
['B', '5', '\x00', '^']

However, in Python 3.1, the above returns a map object.

B: Python 3.1:

>>> map(chr, [66, 53, 0, 94])
<map object at 0x00AF5570>

How do I retrieve the mapped list (as in A above) on Python 3.x?

Alternatively, is there a better way of doing this? My initial list object has around 45 items and id like to convert them to hex.


回答 0

做这个:

list(map(chr,[66,53,0,94]))

在Python 3+中,许多迭代可迭代对象的进程本身都会返回迭代器。在大多数情况下,这最终会节省内存,并且应该使处理速度更快。

如果您要做的只是最终遍历此列表,则无需将其转换为列表,因为您仍然可以map像这样遍历该对象:

# Prints "ABCD"
for ch in map(chr,[65,66,67,68]):
    print(ch)

Do this:

list(map(chr,[66,53,0,94]))

In Python 3+, many processes that iterate over iterables return iterators themselves. In most cases, this ends up saving memory, and should make things go faster.

If all you’re going to do is iterate over this list eventually, there’s no need to even convert it to a list, because you can still iterate over the map object like so:

# Prints "ABCD"
for ch in map(chr,[65,66,67,68]):
    print(ch)

回答 1

Python 3.5的新功能:

[*map(chr, [66, 53, 0, 94])]

多亏了其他拆包概述

更新

一直在寻找更短的途径,我发现这也行得通:

*map(chr, [66, 53, 0, 94]),

开箱也适用于元组。注意最后的逗号。这使其成为1个元素的元组。也就是说,它相当于(*map(chr, [66, 53, 0, 94]),)

它比带有方括号的版本短一个字符,但我认为最好写,因为您从星号-扩展语法开始,所以我觉得它比较软。:)

New and neat in Python 3.5:

[*map(chr, [66, 53, 0, 94])]

Thanks to Additional Unpacking Generalizations

UPDATE

Always seeking for shorter ways, I discovered this one also works:

*map(chr, [66, 53, 0, 94]),

Unpacking works in tuples too. Note the comma at the end. This makes it a tuple of 1 element. That is, it’s equivalent to (*map(chr, [66, 53, 0, 94]),)

It’s shorter by only one char from the version with the list-brackets, but, in my opinion, better to write, because you start right ahead with the asterisk – the expansion syntax, so I feel it’s softer on the mind. :)


回答 2

您为什么不这样做:

[chr(x) for x in [66,53,0,94]]

这称为列表理解。您可以在Google上找到很多信息,但是这里是list comprehensions上的Python(2.6)文档的链接。不过,您可能对Python 3文档更感兴趣。

Why aren’t you doing this:

[chr(x) for x in [66,53,0,94]]

It’s called a list comprehension. You can find plenty of information on Google, but here’s the link to the Python (2.6) documentation on list comprehensions. You might be more interested in the Python 3 documenation, though.


回答 3

返回列表的地图功能具有保存键入的优点,尤其是在交互式会话期间。您可以定义返回列表的lmap函数(类似于python2的函数imap):

lmap = lambda func, *iterable: list(map(func, *iterable))

然后打电话 lmap而不是即可map完成工作:比 lmap(str, x)短5个字符(在这种情况下为30%),list(map(str, x))并且肯定比短[str(v) for v in x]。您也可以创建类似的功能filter

对原始问题有一条评论:

我建议重命名为Geting map()以返回Python 3. *中的列表,因为它适用于所有Python3版本。有没有办法做到这一点?– meawoppl 1月24日17:58

有可能做到这一点,但它是一个非常糟糕的主意。只是为了好玩,您可以(但不应)执行以下操作:

__global_map = map #keep reference to the original map
lmap = lambda func, *iterable: list(__global_map(func, *iterable)) # using "map" here will cause infinite recursion
map = lmap
x = [1, 2, 3]
map(str, x) #test
map = __global_map #restore the original map and don't do that again
map(str, x) #iterator

List-returning map function has the advantage of saving typing, especially during interactive sessions. You can define lmap function (on the analogy of python2’s imap) that returns list:

lmap = lambda func, *iterable: list(map(func, *iterable))

Then calling lmap instead of map will do the job: lmap(str, x) is shorter by 5 characters (30% in this case) than list(map(str, x)) and is certainly shorter than [str(v) for v in x]. You may create similar functions for filter too.

There was a comment to the original question:

I would suggest a rename to Getting map() to return a list in Python 3.* as it applies to all Python3 versions. Is there a way to do this? – meawoppl Jan 24 at 17:58

It is possible to do that, but it is a very bad idea. Just for fun, here’s how you may (but should not) do it:

__global_map = map #keep reference to the original map
lmap = lambda func, *iterable: list(__global_map(func, *iterable)) # using "map" here will cause infinite recursion
map = lmap
x = [1, 2, 3]
map(str, x) #test
map = __global_map #restore the original map and don't do that again
map(str, x) #iterator

回答 4

我的旧注释转换为更好的可见性:为了更好地“更好地做到这一点” map,如果您的输入已知为ASCII序数,则通常可以更快地转换为bytesla bytes(list_of_ordinals).decode('ascii')。这样就可以得到一个str值,但是如果您需要a list来实现可变性或类似功能,则可以将其转换(并且转换速度仍然更快)。例如,在微ipython基准中转换45个输入:

>>> %%timeit -r5 ordinals = list(range(45))
... list(map(chr, ordinals))
...
3.91 µs ± 60.2 ns per loop (mean ± std. dev. of 5 runs, 100000 loops each)

>>> %%timeit -r5 ordinals = list(range(45))
... [*map(chr, ordinals)]
...
3.84 µs ± 219 ns per loop (mean ± std. dev. of 5 runs, 100000 loops each)

>>> %%timeit -r5 ordinals = list(range(45))
... [*bytes(ordinals).decode('ascii')]
...
1.43 µs ± 49.7 ns per loop (mean ± std. dev. of 5 runs, 1000000 loops each)

>>> %%timeit -r5 ordinals = list(range(45))
... bytes(ordinals).decode('ascii')
...
781 ns ± 15.9 ns per loop (mean ± std. dev. of 5 runs, 1000000 loops each)

如果您将其保留为str,则最快的map解决方案会花费大约20%的时间;即使转换回列表,它仍然不到最快map解决方案的40%。批量转换通过bytesbytes.decode然后批量转换回以list节省大量工作,但是如上所述,仅当您所有的输入都是ASCII序号(或每个字符特定于区域设置编码的字节中的序号latin-1)时,该方法才有效。

Converting my old comment for better visibility: For a “better way to do this” without map entirely, if your inputs are known to be ASCII ordinals, it’s generally much faster to convert to bytes and decode, a la bytes(list_of_ordinals).decode('ascii'). That gets you a str of the values, but if you need a list for mutability or the like, you can just convert it (and it’s still faster). For example, in ipython microbenchmarks converting 45 inputs:

>>> %%timeit -r5 ordinals = list(range(45))
... list(map(chr, ordinals))
...
3.91 µs ± 60.2 ns per loop (mean ± std. dev. of 5 runs, 100000 loops each)

>>> %%timeit -r5 ordinals = list(range(45))
... [*map(chr, ordinals)]
...
3.84 µs ± 219 ns per loop (mean ± std. dev. of 5 runs, 100000 loops each)

>>> %%timeit -r5 ordinals = list(range(45))
... [*bytes(ordinals).decode('ascii')]
...
1.43 µs ± 49.7 ns per loop (mean ± std. dev. of 5 runs, 1000000 loops each)

>>> %%timeit -r5 ordinals = list(range(45))
... bytes(ordinals).decode('ascii')
...
781 ns ± 15.9 ns per loop (mean ± std. dev. of 5 runs, 1000000 loops each)

If you leave it as a str, it takes ~20% of the time of the fastest map solutions; even converting back to list it’s still less than 40% of the fastest map solution. Bulk convert via bytes and bytes.decode then bulk converting back to list saves a lot of work, but as noted, only works if all your inputs are ASCII ordinals (or ordinals in some one byte per character locale specific encoding, e.g. latin-1).


回答 5

list(map(chr, [66, 53, 0, 94]))

map(func,* iterables)->地图对象创建一个迭代器,该迭代器使用每个可迭代对象的参数来计算函数。当最短的迭代次数用尽时停止。

“进行迭代”

表示它将返回迭代器。

“使用每个可迭代对象的参数来计算函数”

意味着迭代器的next()函数将为每个可迭代对象取一个值,并将每个值传递给该函数的一个位置参数。

因此,您可以从map()函数中获得一个迭代器,然后jsut将其传递给内置函数list()或使用列表推导。

list(map(chr, [66, 53, 0, 94]))

map(func, *iterables) –> map object Make an iterator that computes the function using arguments from each of the iterables. Stops when the shortest iterable is exhausted.

“Make an iterator”

means it will return an iterator.

“that computes the function using arguments from each of the iterables”

means that the next() function of the iterator will take one value of each iterables and pass each of them to one positional parameter of the function.

So you get an iterator from the map() funtion and jsut pass it to the list() builtin function or use list comprehensions.


回答 6

除了上述答案外Python 3,我们还可以简单地listmapas中创建结果值a

li = []
for x in map(chr,[66,53,0,94]):
    li.append(x)

print (li)
>>>['B', '5', '\x00', '^']

我们可以通过另一个例子来概括我被打动的情况,对地图的操作也可以像regex问题中一样的方式处理,我们可以编写函数以获取list要映射的项目并同时获取结果集。例如

b = 'Strings: 1,072, Another String: 474 '
li = []
for x in map(int,map(int, re.findall('\d+', b))):
    li.append(x)

print (li)
>>>[1, 72, 474]

In addition to above answers in Python 3, we may simply create a list of result values from a map as

li = []
for x in map(chr,[66,53,0,94]):
    li.append(x)

print (li)
>>>['B', '5', '\x00', '^']

We may generalize by another example where I was struck, operations on map can also be handled in similar fashion like in regex problem, we can write function to obtain list of items to map and get result set at the same time. Ex.

b = 'Strings: 1,072, Another String: 474 '
li = []
for x in map(int,map(int, re.findall('\d+', b))):
    li.append(x)

print (li)
>>>[1, 72, 474]

回答 7

您可以尝试通过仅迭代对象中的每个项目并将其存储在另一个变量中来从地图对象获取列表。

a = map(chr, [66, 53, 0, 94])
b = [item for item in a]
print(b)
>>>['B', '5', '\x00', '^']

You can try getting a list from the map object by just iterating each item in the object and store it in a different variable.

a = map(chr, [66, 53, 0, 94])
b = [item for item in a]
print(b)
>>>['B', '5', '\x00', '^']

回答 8

使用python中的列表理解和基本的地图函数实用程序,还可以做到这一点:

chi = [x for x in map(chr,[66,53,0,94])]

Using list comprehension in python and basic map function utility, one can do this also:

chi = [x for x in map(chr,[66,53,0,94])]