标签归档:python-3.x

Pipenv:找不到命令

问题:Pipenv:找不到命令

我是Python开发的新手,正在尝试使用pipenv。我运行了命令pip install pipenv,该命令成功运行:

...
Successfully built pipenv pathlib shutilwhich pythonz-bd virtualenv-clone
Installing collected packages: virtualenv, pathlib, shutilwhich, backports.shutil-get-terminal-size, pythonz-bd, virtualenv-clone, pew, first, six, click, pip-tools, certifi, chardet, idna, urllib3, requests, pipenv
...

但是,当我pipenv install在新的根项目目录中运行命令时,收到以下消息:-bash: pipenv: command not found。我怀疑可能需要修改.bashrc,但是不清楚要添加到文件中的内容还是不清楚是否需要修改。

I’m new to Python development and attempting to use pipenv. I ran the command pip install pipenv, which ran successfully:

...
Successfully built pipenv pathlib shutilwhich pythonz-bd virtualenv-clone
Installing collected packages: virtualenv, pathlib, shutilwhich, backports.shutil-get-terminal-size, pythonz-bd, virtualenv-clone, pew, first, six, click, pip-tools, certifi, chardet, idna, urllib3, requests, pipenv
...

However, when I run the command pipenv install in a fresh root project directory I receive the following message: -bash: pipenv: command not found. I suspect that I might need to modify my .bashrc, but I’m unclear about what to add to the file or if modification is even necessary.


回答 0

发生这种情况是因为您没有在全局范围内安装它(系统范围内)。为了使它可用,您path需要使用进行安装sudo,如下所示:

$ sudo pip install pipenv

That happens because you are not installing it globally (system wide). For it to be available in your path you need to install it using sudo, like this:

$ sudo pip install pipenv

回答 1

这为我解决了:

sudo -H pip install -U pipenv

This fixed it for me:

sudo -H pip install -U pipenv

回答 2

如果完成了用户安装,则需要将正确的文件夹添加到PATH变量中。

PYTHON_BIN_PATH="$(python3 -m site --user-base)/bin"
PATH="$PATH:$PYTHON_BIN_PATH"

看到 pipenv的安装说明

If you’ve done a user installation, you’ll need to add the right folder to your PATH variable.

PYTHON_BIN_PATH="$(python3 -m site --user-base)/bin"
PATH="$PATH:$PYTHON_BIN_PATH"

See pipenv’s installation instructions


回答 3

我尝试了这个:

python -m pipenv # for python2

python3 -m pipenv # for python3

希望这可以帮到你。

I tried this:

python -m pipenv # for python2

python3 -m pipenv # for python3

Hope this can help you.


回答 4

pipenv在Mac OS X 10.13 High Seirra上也有同样的问题,另一台Mac可以正常工作。我使用Heroku部署Django服务器,其中一些部署在2.7中,有些部署在3.6中。因此,我需要2.7和3.6。当HomeBrew安装Python时,它将python指向原始2.7,并且python3指向3.6。

问题可能是由于$ pip install pipenv。我检查了/ usr / local / bin,pipenv不存在。因此,我尝试了完全卸载:

$ pip uninstall pipenv

Cannot uninstall requirement pipenv, not installed
You are using pip version 9.0.1, however version 10.0.1 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.

$ pip3 uninstall pipenv
Skipping pipenv as it is not installed.

然后重新安装即可立即使用:

$ pip3 install pipenv
Collecting pipenv

I have same problem with pipenv on Mac OS X 10.13 High Seirra, another Mac works just fine. I use Heroku to deploy my Django servers, some in 2.7 and some in 3.6. So, I need both 2.7 and 3.6. When HomeBrew install Python, it keeps python points to original 2.7, and python3 points to 3.6.

The problem might due to $ pip install pipenv. I checked /usr/local/bin and pipenv isn’t there. So, I tried a full uninstall:

$ pip uninstall pipenv

Cannot uninstall requirement pipenv, not installed
You are using pip version 9.0.1, however version 10.0.1 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.

$ pip3 uninstall pipenv
Skipping pipenv as it is not installed.

Then reinstall and works now:

$ pip3 install pipenv
Collecting pipenv

回答 5

OSX的家伙,在这里!!!

正如@charlax回答的那样(对我而言,这是最好的),您可以使用更动态的命令来设置PATH,但对于mac用户而言,buuut 无法正常工作,有时从站点获取的USER_BASE路径错误,因此您需要找出您的位置python安装是。

$ which python3
/usr/local/bin/python3.6

您将获得一个符号链接,然后需要找到源的符号链接。

$ ls -la /usr/local/bin/python3.6
  lrwxr-xr-x  1 root  wheel  71 Mar 14 17:56 /usr/local/bin/python3.6 -> ../../../Library/Frameworks/Python.framework/Versions/3.6/bin/python3.6

(这../../../意味着根)

因此,您找到了python路径(/Library/Frameworks/Python.framework/Versions/3.6/bin/python3.6),然后只需将〜/ .bashrc放入其中,如下所示:

export PATH="$PATH:/Library/Frameworks/Python.framework/Versions/3.6/bin"

OSX GUYS, OVER HERE!!!

As @charlax answered (for me the best one), you can use a more dynamic command to set PATH, buuut for mac users this could not work, sometimes your USER_BASE path got from site is wrong, so you need to find out where your python installation is.

$ which python3
/usr/local/bin/python3.6

you’ll get a symlink, then you need to find the source’s symlink.

$ ls -la /usr/local/bin/python3.6
  lrwxr-xr-x  1 root  wheel  71 Mar 14 17:56 /usr/local/bin/python3.6 -> ../../../Library/Frameworks/Python.framework/Versions/3.6/bin/python3.6

(this ../../../ means root)

So you found the python path (/Library/Frameworks/Python.framework/Versions/3.6/bin/python3.6), then you just need to put in you ~/.bashrc as follows:

export PATH="$PATH:/Library/Frameworks/Python.framework/Versions/3.6/bin"


回答 6

通过覆盖全局/系统管理的pip安装,全局安装pipenv可能会产生不利影响,从而在尝试运行pip时导致导入错误。

您可以在用户级别安装pipenv:

pip install --user pipenv

这应该在/home/username/.local中的用户级别安装pipenv,以使其与pip的全局版本不冲突。就我而言,在运行’–user’开关后仍然无法正常工作,因此我运行了更长的“修复我搞砸的东西”命令一次,以恢复系统管理的环境:

sudo python3 -m pip uninstall pip && sudo apt install python3-pip --reinstall

^在这里找到:升级pip后出错:无法导入名称’main’

然后执行以下操作:

mkdir /home/username/.local …如果还不存在

export PYTHONUSERBASE=/home/username/.local

确保导出生效(在此过程中,只对我进行一次咬合):

echo $PYTHONUSERBASE

然后,我跑了pip install --user pipenv,一切都很好。然后,我可以从CLI运行pipenv,它不会覆盖全局/系统管理的pip模块。当然,这是特定于用户的,因此您要确保在以希望使用pipenv的用户身份工作时以这种方式安装pipenv。

参考文献:

https://pipenv.readthedocs.io/en/latest/diagnose/#no-module-named-module-name https://pipenv.readthedocs.io/en/latest/install/#pragmatic-installation-of-pipenv https://pip.pypa.io/zh_CN/stable/user_guide/#user-installs

Installing pipenv globally can have an adverse effect by overwriting the global/system-managed pip installation, thus resulting in import errors when trying to run pip.

You can install pipenv at the user level:

pip install --user pipenv

This should install pipenv at a user-level in /home/username/.local so that it does not conflict with the global version of pip. In my case, that still did not work after running the ‘–user’ switch, so I ran the longer ‘fix what I screwed up’ command once to restore the system managed environment:

sudo python3 -m pip uninstall pip && sudo apt install python3-pip --reinstall

^ found here: Error after upgrading pip: cannot import name ‘main’

and then did the following:

mkdir /home/username/.local … if it doesn’t already exist

export PYTHONUSERBASE=/home/username/.local

Make sure the export took effect (bit me once during this process):

echo $PYTHONUSERBASE

Then, I ran the pip install --user pipenv and all was well. I could then run pipenv from the CLI and it did not overwrite the global/system-managed pip module. Of course, this is specific to the user so you want to make sure you install pipenv this way while working as the user you wish to use pipenv.

References:

https://pipenv.readthedocs.io/en/latest/diagnose/#no-module-named-module-name https://pipenv.readthedocs.io/en/latest/install/#pragmatic-installation-of-pipenv https://pip.pypa.io/en/stable/user_guide/#user-installs


回答 7

Python存储包的位置

在进入将要安装的命令之前pipenv,值得了解pip Python软件包的安装位置

全局站点软件包是Python安装软件包的地方,这些软件包将可供系统上的所有用户和所有Python应用程序使用。您可以使用以下命令检查全局站点包

python -m site

例如,在具有Python 3.7的Linux上,路径通常是

/usr/lib/python3.7/dist-packages/setuptools

用户站点软件包是Python安装仅对您可用的软件包的地方。但是,这些包对您创建的所有Python项目仍然可见。您可以使用以下方法

python -m site --user-base

在具有Python 3.7的Linux上,路径通常是

~/.local/lib/python3.7/site-packages

使用Python 3.x

在大多数Linux和其他Unices上,通常并行安装Python 2和Python 3。默认的Python 3可执行文件几乎总是python3pip根据您的Linux发行版本,可能提供以下任一版本

pip3
python3-pip
python36-pip
python3.6-pip

的Linux

避免pipsudo!是的,这是安装Python软件包的最方便的方法,可执行文件位于/usr/local/bin/pipenv,但也意味着特定的软件包始终对所有用户和您创建的所有Python项目可见。而是使用按用户站点包,而不是--user

pip3 install --user pipenv

pipenv 在以下位置可用

~/.local/bin/pipenv

苹果系统

在macOS上,建议使用Homebrew来安装Python。您可以轻松升级Python,安装多个版本的Python,以及使用Homebrew在版本之间切换。

如果您使用的是自制软件的Python,则已pip install --user禁用。全局站点包位于

/usr/local/lib/python3.y/site-packages

并且您可以在此处安全地安装Python软件包。Python 3.y还在以下位置搜索模块:

 /Library/Python/3.y/site-packages
 ~/Library/Python/3.y/lib/python/site-packages

视窗

出于传统原因,Python安装在中C:\Python37。Python可执行文件通常被命名为py.exe,并且可以pip使用来运行py -m pip

全局站点包安装在

C:\Python37\lib\site-packages

由于通常不共享Windows设备,因此也可以在全局范围内安装软件包

py -m pip install pipenv

pipenv 现在可以在

C:\Python37\Scripts\pipenv.exe

我不建议使用Windows在Windows中安装Python软件包--user,因为默认的用户site-package目录位于Windows漫游配置文件中

C:\Users\user\AppData\Roaming\Python\Python37\site-packages 

在终端服务(远程桌面,Citrix等)中以及在公司环境中登录/注销时,将使用漫游配置文件。大型漫游配置文件可能导致Windows中缓慢的登录,注销和重新启动。

Where Python store packages

Before jumping into the command that will install pipenv, it is worth understanding where pip installs Python packages.

Global site-packages is where Python installs packages that will be available to all users and all Python applications on the system. You can check the global site package with the command

python -m site

For example, on Linux with Python 3.7 the path is usually

/usr/lib/python3.7/dist-packages/setuptools

User site-packages is where Python installs packages available only for you. But the packages will still be visible to all Python projects that you create. You can get the path with

python -m site --user-base

On Linux with Python 3.7 the path is usually

~/.local/lib/python3.7/site-packages

Using Python 3.x

On most Linux and other Unices, usually Python 2 and Python 3 is installed side-by-side. The default Python 3 executable is almost always python3. pip may be available as either of the following, depending on your Linux distribution

pip3
python3-pip
python36-pip
python3.6-pip

Linux

Avoid using pip with sudo! Yes, it’s the most convenient way to install Python packages and the executable is available at /usr/local/bin/pipenv, but it also mean that specific package is always visible for all users, and all Python projects that you create. Instead, use per-user site packages instead with --user

pip3 install --user pipenv

pipenv is available at

~/.local/bin/pipenv

macOS

On macOS, Homebrew is the recommended way to install Python. You can easily upgrade Python, install multiple versions of Python and switch between versions using Homebrew.

If you are using Homebrew’ed Python, pip install --user is disabled. The global site-package is located at

/usr/local/lib/python3.y/site-packages

and you can safely install Python packages here. Python 3.y also searches for modules in:

 /Library/Python/3.y/site-packages
 ~/Library/Python/3.y/lib/python/site-packages

Windows

For legacy reasons, Python is installed in C:\Python37. The Python executable is usually named py.exe, and you can run pip with py -m pip.

Global site packages is installed in

C:\Python37\lib\site-packages

Since you don’t usually share your Windows devices, it is also OK to install a package globally

py -m pip install pipenv

pipenv is now available at

C:\Python37\Scripts\pipenv.exe

I don’t recommend install Python packages in Windows with --user, because the default user site-package directory is in your Windows roaming profile

C:\Users\user\AppData\Roaming\Python\Python37\site-packages 

The roaming profile is used in Terminal Services (Remote Desktop, Citrix, etc) and when you log on / off in a corporate environment. Slow login, logoff and reboot in Windows can be caused by a large roaming profile.


回答 8

我已将其固定为:

sudo -H pip install -U pipenv

This is fixed for me to:

sudo -H pip install -U pipenv

回答 9

安装pipenv(sudo pip install pipenv)后,尝试运行Windows XP时,始终出现“找不到命令”错误pipenv shell命令。

我终于用以下代码修复了它:

pip3 install pipenv
pipenv shell

After installing pipenv (sudo pip install pipenv), I kept getting the “Command Not Found” error when attempting to run the pipenv shell command.

I finally fixed it with the following code:

pip3 install pipenv
pipenv shell

回答 10

您可以考虑pipenv通过安装pipsi

curl https://raw.githubusercontent.com/mitsuhiko/pipsi/master/get -pipsi.py | python3
pipsi install pew
pipsi install pipenv

不幸的是有一些问题与写作时的MacOS + python3,看到12。就我而言,我必须将bashprompt更改为#!/Users/einselbst/.local/venvs/pipsi/bin/python

You might consider installing pipenv via pipsi.

curl https://raw.githubusercontent.com/mitsuhiko/pipsi/master/get -pipsi.py | python3
pipsi install pew
pipsi install pipenv

Unfortunately there are some issues with macOS + python3 at the time of writing, see 1, 2. In my case I had to change the bashprompt to #!/Users/einselbst/.local/venvs/pipsi/bin/python


回答 11

在旧pip版本的某些情况下:

sudo easy_install pip
sudo pip install pipenv

In some cases of old pip version:

sudo easy_install pip
sudo pip install pipenv

回答 12

对于Windows用户,这可能是由于与virtualenv的安装冲突。对我来说,它在我先卸载virtualenv和pipenv,然后仅安装pipenv时起作用。

pip uninstall virtualenv
pip uninstall pipenv
pip install pipenv

现在pipenv install xxx为我工作

For window users this may be due to conflicting installation with virtualenv. For me it worked when I uninstalled virtualenv and pipenv first, and then install only pipenv.

pip uninstall virtualenv
pip uninstall pipenv
pip install pipenv

Now pipenv install xxx worked for me


回答 13

在Mac OS X Catalina上,它似乎遵循Linux路径。使用以下任何一种:

pip install pipenv
pip3 install pipenv
sudo pip install pipenv
sudo pip3 install pipenv

本质上在这里安装pipenv:

/Users/mike/Library/Python/3.7/lib/python/site-packages/pipenv

但是它不是可执行文件,因此永远找不到。唯一对我有用的是

pip install --user pipenv

这似乎导致__init__.py上述目录中的文件包含正确显示pipenv命令的内容。

当有关此问题的所有其他发布和评论建议都失败时,一切都开始起作用。

pipenv软件包当然看起来很挑剔。

On Mac OS X Catalina it appears to follow the Linux path. Using any of:

pip install pipenv
pip3 install pipenv
sudo pip install pipenv
sudo pip3 install pipenv

Essentially installs pipenv here:

/Users/mike/Library/Python/3.7/lib/python/site-packages/pipenv

But its not the executable and so is never found. The only thing that worked for me was

pip install --user pipenv

This seems to result in an __init__.py file in the above directory that has contents to correctly expose the pipenv command.

and everything started working, when all other posted and commented suggestions on this question failed.

The pipenv package certainly seems quite picky.


pip或pip3为Python 3安装软件包?

问题:pip或pip3为Python 3安装软件包?

我有一台配备OS X El Captain的Macbook。我认为那Python 2.7是预装的。但是,我也安装Python 3.5了。开始使用时Python 3,我读到要安装软件包,应输入:

pip3 install some_package

无论如何,现在当我使用

pip install some_package

some_package安装了Python 3。我的意思是我可以导入它,并且可以毫无问题地使用它。而且,当我只pip3输入时Terminal,我得到以下关于用法的消息:

Usage:   
  pip <command> [options]

这是我输入just时得到的相同信息pip

这是否意味着在previos版本,事情是不同的,现在pippip3可以互换使用?如果是这样,并且为了参数起见,我该如何安装软件包Python 2而不是Python 3

I have a Macbook with OS X El Captain. I think that Python 2.7 comes preinstalled on it. However, I installed Python 3.5 too. When I started using Python 3, I read that if I want to install a package, I should type:

pip3 install some_package

Anyway, now when I use

pip install some_package

I get some_package installed for Python 3. I mean I can import it and use it without problems. Moreover, when I type just pip3 in Terminal, I got this message about the usage:

Usage:   
  pip <command> [options]

which is the same message I get when I type just pip.

Does it mean that in previos versions, things were different, and now pip and pip3 can be used interchangeably? If so, and for the sake of argument, how can I install packages for Python 2 instead of Python 3?


回答 0

pip是使用链接到同一可执行文件路径的软链接pip3。您可以使用以下命令来检查您的真实路径pippip3实际路径:

$ ls -l `which pip`
$ ls -l `which pip3`

您也可以使用以下命令了解更多详细信息:

$ pip show pip
$ pip3 show pip

当我们安装不同版本的python时,我们可能会创建以下软链接到

  • 将默认点设置为某些版本。
  • 为不同的版本创建不同的链接。

这是同样的情况pythonpython2python3

如果您对在不同情况下如何发生感兴趣,可以在下面获取更多信息:

Your pip is a soft link to the same executable file path with pip3. you can use the commands below to check where your pip and pip3 real paths are:

$ ls -l `which pip`
$ ls -l `which pip3`

You may also use the commands below to know more details:

$ pip show pip
$ pip3 show pip

When we install different versions of python, we may create such soft links to

  • set default pip to some version.
  • make different links for different versions.

It is the same situation with python, python2, python3

More information below if you’re interested in how it happens in different cases:


回答 1

如果您安装了python 2.x,然后安装了python3,则您的pip将指向pip3。您可以通过键入来验证pip --version与相同pip3 --version

在您的系统上,现在有了pip,pip2和pip3

如果需要,可以将pip更改为指向pip2而不是pip3。

If you had python 2.x and then installed python3, your pip will be pointing to pip3. you can verify that by typing pip --version which would be the same as pip3 --version.

On your system you have now pip, pip2 and pip3.

If you want you can change pip to point to pip2 instead of pip3.


回答 2

安装后python3,即pip3会安装。如果你没有其他的Python安装(如python2.7),然后链接创建这点pippip3

所以pip是一个链接pip3,如果有Python安装的任何其他版本(比python3等)。 pip通常指向首次安装。

When you install python3, pip3 gets installed. And if you don’t have another python installation(like python2.7) then a link is created which points pip to pip3.

So pip is a link to to pip3 if there is no other version of python installed(other than python3). pip generally points to the first installation.


回答 3

这是一个棘手的问题。最后,如果您调用pip它,则将调用pip2pip3,具体取决于您如何设置系统。

This is a tricky subject. In the end, if you invoke pip it will invoke either pip2 or pip3, depending on how you set your system up.


回答 4

我认为pippip2并且pip3不是指向同一可执行文件路径的软链接。请注意以下命令并在我的linux终端中显示结果:

mrz@mrz-pc ~ $ ls -l `which pip`
-rwxr-xr-x 1 root root 292 Nov 10  2016 /usr/bin/pip
mrz@mrz-pc ~ $ ls -l `which pip2`
-rwxr-xr-x 1 root root 283 Nov 10  2016 /usr/bin/pip2
mrz@mrz-pc ~ $ ls -l `which pip3`
-rwxr-xr-x 1 root root 293 Nov 10  2016 /usr/bin/pip3
mrz@mrz-pc ~ $ pip -V
pip 9.0.1 from /home/mrz/.local/lib/python2.7/site-packages (python 2.7)
mrz@mrz-pc ~ $ pip2 -V
pip 8.1.1 from /usr/lib/python2.7/dist-packages (python 2.7)
mrz@mrz-pc ~ $ pip3 -V
pip 9.0.1 from /home/mrz/.local/lib/python3.5/site-packages (python 3.5)

如您所见,它们存在于不同的路径中。

pip3始终仅在Python3环境上运行,就像pip2在Python2上一样。pip在适合上下文的任何环境下运行。例如,如果您在Python3平台上,pip将在Python3环境下运行。

I think pip, pip2 and pip3 are not soft links to the same executable file path. Note these commands and results in my Linux terminal:

mrz@mrz-pc ~ $ ls -l `which pip`
-rwxr-xr-x 1 root root 292 Nov 10  2016 /usr/bin/pip
mrz@mrz-pc ~ $ ls -l `which pip2`
-rwxr-xr-x 1 root root 283 Nov 10  2016 /usr/bin/pip2
mrz@mrz-pc ~ $ ls -l `which pip3`
-rwxr-xr-x 1 root root 293 Nov 10  2016 /usr/bin/pip3
mrz@mrz-pc ~ $ pip -V
pip 9.0.1 from /home/mrz/.local/lib/python2.7/site-packages (python 2.7)
mrz@mrz-pc ~ $ pip2 -V
pip 8.1.1 from /usr/lib/python2.7/dist-packages (python 2.7)
mrz@mrz-pc ~ $ pip3 -V
pip 9.0.1 from /home/mrz/.local/lib/python3.5/site-packages (python 3.5)

As you see they exist in different paths.

pip3 always operates on the Python3 environment only, as pip2 does with Python2. pip operates in whichever environment is appropriate to the context. For example, if you are in a Python3 venv, pip will operate on the Python3 environment.


回答 5

通过插图:

pip --version
  pip 19.0.3 from /usr/lib/python3.7/site-packages/pip (python 3.7)

pip3 --version
  pip 19.0.3 from /usr/lib/python3.7/site-packages/pip (python 3.7)

python --version
  Python 3.7.3

which python
  /usr/bin/python

ls -l '/usr/bin/python'
  lrwxrwxrwx 1 root root 7 Mar 26 14:43 /usr/bin/python -> python3

which python3
  /usr/bin/python3

ls -l /usr/bin/python3
  lrwxrwxrwx 1 root root 9 Mar 26 14:43 /usr/bin/python3 -> python3.7

ls -l /usr/bin/python3.7
  -rwxr-xr-x 2 root root 14120 Mar 26 14:43 /usr/bin/python3.7

因此,在我的默认系统python(Python 3.7.3)中,my pip pip3

By illustration:

pip --version
  pip 19.0.3 from /usr/lib/python3.7/site-packages/pip (python 3.7)

pip3 --version
  pip 19.0.3 from /usr/lib/python3.7/site-packages/pip (python 3.7)

python --version
  Python 3.7.3

which python
  /usr/bin/python

ls -l '/usr/bin/python'
  lrwxrwxrwx 1 root root 7 Mar 26 14:43 /usr/bin/python -> python3

which python3
  /usr/bin/python3

ls -l /usr/bin/python3
  lrwxrwxrwx 1 root root 9 Mar 26 14:43 /usr/bin/python3 -> python3.7

ls -l /usr/bin/python3.7
  -rwxr-xr-x 2 root root 14120 Mar 26 14:43 /usr/bin/python3.7

Thus, my in my default system python (Python 3.7.3), pip is pip3.


回答 6

如果您安装了Python 2.7,我想您可以使用pip2pip2.7安装专门针对Python 2的软件包,例如

pip2 install some_pacakge

要么

pip2.7 install some_package

您可以使用pip3pip3.5安装专门用于Python 3的pacakges。

If you installed Python 2.7, I think you could use pip2 and pip2.7 to install packages specifically for Python 2, like

pip2 install some_pacakge

or

pip2.7 install some_package

And you may use pip3 or pip3.5 to install pacakges specifically for Python 3.


回答 7

在我的Windows实例上-并且我不完全了解我的环境-使用pip3安装kaggle-cli程序包有效-而pip无效。我在conda环境中工作,环境似乎有所不同。

(fastai)C:\ Users \ redact \ Downloads \ fast.ai \ deeplearning1 \ nbs> pip –version

来自C:\ ProgramData \ Anaconda3 \ envs \ fastai \ lib \ site-packages的pip 9.0.1(python 3.6)

(fastai)C:\ Users \ redact \ Downloads \ fast.ai \ deeplearning1 \ nbs> pip3 –version

来自c:\ users \ redact \ appdata \ local \ programs \ python \ python36 \ lib \ site-packages(python 3.6)的pip 9.0.1

On my Windows instance – and I do not fully understand my environment – using pip3 to install the kaggle-cli package worked – whereas pip did not. I was working in a conda environment and the environments appear to be different.

(fastai) C:\Users\redact\Downloads\fast.ai\deeplearning1\nbs>pip –version

pip 9.0.1 from C:\ProgramData\Anaconda3\envs\fastai\lib\site-packages (python 3.6)

(fastai) C:\Users\redact\Downloads\fast.ai\deeplearning1\nbs>pip3 –version

pip 9.0.1 from c:\users\redact\appdata\local\programs\python\python36\lib\site-packages (python 3.6)


回答 8

somepath / venv中激活了Python 3.6 virtualenv后,以下别名解决了macOS Sierra上的各种问题,其中pip坚持指向Apple的2.7 Python。

alias pip='python somepath/venv/lib/python3.6/site-packages/pip/__main__.py'

当我不得不做的时候,这不是很好,sudo pip因为root用户对我的别名或virtualenv一无所知,所以我也不得不添加一个额外的别名来处理这个问题。这是一个hack,但是可以用,我知道它的作用:

alias sudopip='sudo somepath/venv/bin/python somepath/venv/lib/python3.6/site-packages/pip/__main__.py'

背景:

pip3不存在,无法启动(找不到命令),which pip它将返回Apple Python的/opt/local/Library/Frameworks/Python.framework/Versions/2.7/bin/pip

Python 3.6是通过macports安装的。

激活我想使用的3.6 virtualenv后,which python将返回somepath / venv / bin / python

以某种方式pip install可以做正确的事情并击中我的virtualenv,但pip list会使Python 2.7包感到不安。

对于Python而言,这对初学者友好程度比我期望的要低。

Given an activated Python 3.6 virtualenv in somepath/venv, the following aliases resolved the various issues on a macOS Sierra where pip insisted on pointing to Apple’s 2.7 Python.

alias pip='python somepath/venv/lib/python3.6/site-packages/pip/__main__.py'

This didn’t work so well when I had to do sudo pip as the root user doesn’t know anything about my alias or the virtualenv, so I had to add an extra alias to handle this as well. It’s a hack, but it works, and I know what it does:

alias sudopip='sudo somepath/venv/bin/python somepath/venv/lib/python3.6/site-packages/pip/__main__.py'

background:

pip3 did not exist to start (command not found) with and which pip would return /opt/local/Library/Frameworks/Python.framework/Versions/2.7/bin/pip, the Apple Python.

Python 3.6 was installed via macports.

After activation of the 3.6 virtualenv I wanted to work with, which python would return somepath/venv/bin/python

Somehow pip install would do the right thing and hit my virtualenv, but pip list would rattle off Python 2.7 packages.

For Python, this is batting way beneath my expectations in terms of beginner-friendliness.


为什么Python 3.6.1抛出AttributeError:模块’enum’没有属性’IntFlag’?

问题:为什么Python 3.6.1抛出AttributeError:模块’enum’没有属性’IntFlag’?

我刚刚为MacOS X安装了Python 3.6.1

当我尝试运行控制台(或使用Python3运行任何命令)时,抛出此错误:

  AttributeError: module 'enum' has no attribute 'IntFlag'

$ /Library/Frameworks/Python.framework/Versions/3.6/bin/python3  
Failed to import the site module  
Traceback (most recent call last):  
  File "/usr/local/Cellar/python3/3.6.1/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site.py", line 544, in <module>  
    main()  
  File "/usr/local/Cellar/python3/3.6.1/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site.py", line 530, in main  
    known_paths = addusersitepackages(known_paths)  
  File "/usr/local/Cellar/python3/3.6.1/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site.py", line 282, in addusersitepackages  
    user_site = getusersitepackages()  
  File "/usr/local/Cellar/python3/3.6.1/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site.py", line 258, in getusersitepackages  
    user_base = getuserbase() # this will also set USER_BASE  
  File "/usr/local/Cellar/python3/3.6.1/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site.py", line 248, in getuserbase  
    USER_BASE = get_config_var('userbase')  
  File "/usr/local/Cellar/python3/3.6.1/Frameworks/Python.framework/Versions/3.6/lib/python3.6/sysconfig.py", line 601, in get_config_var  
    return get_config_vars().get(name)  
  File "/usr/local/Cellar/python3/3.6.1/Frameworks/Python.framework/Versions/3.6/lib/python3.6/sysconfig.py", line 580, in get_config_vars  
    import _osx_support  
  File "/usr/local/Cellar/python3/3.6.1/Frameworks/Python.framework/Versions/3.6/lib/python3.6/_osx_support.py", line 4, in <module>  
    import re  
  File "/usr/local/Cellar/python3/3.6.1/Frameworks/Python.framework/Versions/3.6/lib/python3.6/re.py", line 142, in <module>  
    class RegexFlag(enum.IntFlag):  
AttributeError: module 'enum' has no attribute 'IntFlag'  

IntFlag类存在于enum.py中。那么,为什么会抛出AttributeError?

I just installed Python 3.6.1 for MacOS X

When I attempt to run the Console(or run anything with Python3), this error is thrown:

  AttributeError: module 'enum' has no attribute 'IntFlag'

$ /Library/Frameworks/Python.framework/Versions/3.6/bin/python3  
Failed to import the site module  
Traceback (most recent call last):  
  File "/usr/local/Cellar/python3/3.6.1/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site.py", line 544, in <module>  
    main()  
  File "/usr/local/Cellar/python3/3.6.1/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site.py", line 530, in main  
    known_paths = addusersitepackages(known_paths)  
  File "/usr/local/Cellar/python3/3.6.1/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site.py", line 282, in addusersitepackages  
    user_site = getusersitepackages()  
  File "/usr/local/Cellar/python3/3.6.1/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site.py", line 258, in getusersitepackages  
    user_base = getuserbase() # this will also set USER_BASE  
  File "/usr/local/Cellar/python3/3.6.1/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site.py", line 248, in getuserbase  
    USER_BASE = get_config_var('userbase')  
  File "/usr/local/Cellar/python3/3.6.1/Frameworks/Python.framework/Versions/3.6/lib/python3.6/sysconfig.py", line 601, in get_config_var  
    return get_config_vars().get(name)  
  File "/usr/local/Cellar/python3/3.6.1/Frameworks/Python.framework/Versions/3.6/lib/python3.6/sysconfig.py", line 580, in get_config_vars  
    import _osx_support  
  File "/usr/local/Cellar/python3/3.6.1/Frameworks/Python.framework/Versions/3.6/lib/python3.6/_osx_support.py", line 4, in <module>  
    import re  
  File "/usr/local/Cellar/python3/3.6.1/Frameworks/Python.framework/Versions/3.6/lib/python3.6/re.py", line 142, in <module>  
    class RegexFlag(enum.IntFlag):  
AttributeError: module 'enum' has no attribute 'IntFlag'  

The class IntFlag exists within enum.py. So, why is the AttributeError being thrown?


回答 0

这是因为您enum不是标准库enum模块。您可能已经enum34安装了软件包。

检查是否属于这种情况的一种方法是检查物业 enum.__file__

import enum
print(enum.__file__)  
# standard library location should be something like 
# /usr/local/lib/python3.6/enum.py

从python 3.6开始,enum34库不再与标准库兼容。该库也是不必要的,因此您可以简单地将其卸载。

pip uninstall -y enum34

如果您需要代码在<= 3.4和> 3.4的python版本上运行,则可以enum-compat根据需要尝试。它仅enum34针对没有标准库枚举的python较旧版本安装。

It’s because your enum is not the standard library enum module. You probably have the package enum34 installed.

One way check if this is the case is to inspect the property enum.__file__

import enum
print(enum.__file__)  
# standard library location should be something like 
# /usr/local/lib/python3.6/enum.py

Since python 3.6 the enum34 library is no longer compatible with the standard library. The library is also unnecessary, so you can simply uninstall it.

pip uninstall -y enum34

If you need the code to run on python versions both <=3.4 and >3.4, you can try having enum-compat as a requirement. It only installs enum34 for older versions of python without the standard library enum.


回答 1

不知道您是否仍然有此问题。我遇到了类似的问题,只需取消设置即可解决PYTHONPATH

$ unset PYTHONPATH

Not sure whether you still have this issue. I had a similar issue and I was able to resolve it simply by unsetting PYTHONPATH

$ unset PYTHONPATH


回答 2

对我来说,此错误是在安装gcloud组件app-engine-python以便集成到pycharm后发生的。即使pycharm现在不上传到app-engine,卸载模块也有帮助。

For me this error occured after installing of gcloud component app-engine-python in order to integrate into pycharm. Uninstalling the module helped, even if pycharm is now not uploading to app-engine.


回答 3

如果有人在PyCharm中运行Google App Engine Python 3.7标准环境项目时由于遇到此错误而来这里,那么您所需要做的就是

  • 确保要运行的配置适用于Flask,而不适用于Google App Engine配置。
  • 然后在偏好设置>>语言和框架>> Google App Engine下禁用Google App Engine支持

原因是根据此链接

总体目标是您的应用程序应具有完全可移植性,并可以在任何标准Python环境中运行。您编写的是标准Python应用程序,而不是App Engine Python应用程序。作为此转变的一部分,您不再需要为应用程序的核心功能使用专有的App Engine API和服务。目前,Python 3.7运行时中不提供App Engine API。

我猜想当我们在PyCharm中将python 3.7项目创建为Google应用引擎项目时,它仍会尝试以与python2.7应用相同的方式进行操作

If anyone coming here because of getting this error while running a google app engine Python 3.7 standard environment project in PyCharm then all you need to do is

  • Make sure the configuration to run is for Flask, not Google App Engine configuration.
  • Then disable Google App Engine support under Preferences >> Languages & Framework >> Google App Engine

The reason being as per this link

The overall goal is that your app should be fully portable and run in any standard Python environment. You write a standard Python app, not an App Engine Python app. As part of this shift, you are no longer required to use proprietary App Engine APIs and services for your app’s core functionality. At this time, App Engine APIs are not available in the Python 3.7 runtime.

I guess when we create a python 3.7 project in PyCharm as a Google app engine project it still tries to do the same way it does for a python2.7 app


回答 4

免责声明:请@ juanpa.arrivillaga,如果您看到此答案,请随时写自己的答案,我将删除此帖子。

@ juanpa.arrivillaga 上面已经提到过

您的工作目录中是否有文件名enum.py?

这就是我遇到的问题。我当时还不知道python上的enum模块,并已命名我的测试文件enum.py

由于文件名模块名,因此存在冲突。有关模块的更多信息,请参见:https : //docs.python.org/2/tutorial/modules.html

DISCLAIMER: Please, @juanpa.arrivillaga, if you see this answer, feel free to write your own and I will remove this post.

@juanpa.arrivillaga had mentioned above:

Is there a file name enum.py in your working directory, by any chance?

This was the issue I encountered. I was not aware of the enum module on python at the time and had named my test file enum.py.

Since the file name is the module name, there was a conflict. More info on modules here: https://docs.python.org/2/tutorial/modules.html


回答 5

在pycharm首选项中禁用“ Google App Engine支持”对我来说解决了这个问题。

Disabling “Google App Engine Support” in pycharm preferences fixed this issue for me.


回答 6

HåkenLid的回答帮助解决了我的问题(谢谢!),在本例中,在运行于Docker容器中的Flask的Python3.7中FROM tiangolo/uwsgi-nginx-flask:python3.7-alpine3.7

就我而言,enum34是由另一个库(pip install smartsheet-python-sdk)安装的。对于那些遇到类似Docker容器问题的人,这是我的最终Dockerfile(跳至相关行):

FROM tiangolo/uwsgi-nginx-flask:python3.7-alpine3.7
...
RUN pip install -r requirements.txt
RUN pip uninstall -y enum34
...

Håken Lid’s answer helped solved my problem (thanks!) , in my case present in Python3.7 running Flask in a Docker container (FROM tiangolo/uwsgi-nginx-flask:python3.7-alpine3.7).

In my case, enum34 was being installed by another library (pip install smartsheet-python-sdk). For those coming with a similar Docker container problem, here is my final Dockerfile (stripped to the relevant lines):

FROM tiangolo/uwsgi-nginx-flask:python3.7-alpine3.7
...
RUN pip install -r requirements.txt
RUN pip uninstall -y enum34
...

回答 7

如果必须同时为python2和python3保留PYTHONPATH,则可以编写别名语句以在bash_profile中设置适当的PYTHONPATH:

在〜/ .bash_profile中,对PYTHONPATH2和PYTHONPATH3变量进行硬编码,并在其末尾添加以下别名:

alias python='export PYTHONPATH=${PYTHONPATH2};python'
alias python3='export PYTHONPATH=${PYTHONPATH3};python3'

python(指python2),因为我更经常使用python2。

In case you have to keep PYTHONPATH for both python2 and python3, you can write alias statements to set the proper PYTHONPATH in your bash_profile:

Hardcode your PYTHONPATH2, and PYTHONPATH3 variables in your ~/.bash_profile, and add the following aliases at the end of it:

alias python='export PYTHONPATH=${PYTHONPATH2};python'
alias python3='export PYTHONPATH=${PYTHONPATH3};python3'

My python (refers to python2) as I use python2 more often.


回答 8

每当我遇到这个问题时:

AttributeError:模块“枚举”没有属性“ IntFlag”

只需首先运行命令:

unset PYTHONPATH 

然后运行我想要的命令,然后在其中成功。

When ever I got this problem:

AttributeError: module ‘enum’ has no attribute ‘IntFlag’

simply first i run the command:

unset PYTHONPATH 

and then run my desired command then got success in that.


回答 9

使用pip install <required-library> --ignore-installed enum34
安装所需的库后,在构建过程中查找警告。我收到这样的错误:
Using legacy setup.py install for future, since package 'wheel' is not installed
ERROR: pyejabberd 0.2.11 has requirement enum34==1.1.2, but you'll have enum34 1.1.10 which is incompatible.

要解决此问题,请运行以下命令:pip freeze | grep enum34。这将为您提供已安装的enum34的版本。现在将其卸载,pip uninstall enum34然后重新安装所需的版本
pip install "enum34==1.1.20"

I did by using pip install <required-library> --ignore-installed enum34
Once your required library is installed, look for warnings during the build. I got an Error like this:
Using legacy setup.py install for future, since package 'wheel' is not installed
ERROR: pyejabberd 0.2.11 has requirement enum34==1.1.2, but you'll have enum34 1.1.10 which is incompatible.

To fix this issue now run the command: pip freeze | grep enum34. This will give you the version of the installed enum34. Now uninstall it by pip uninstall enum34 and reinstall the required version as
pip install "enum34==1.1.20"


回答 10

我的计算机上安装了Python 2和Python 3。由于某些奇怪的原因,当调用re模块时,我在Python 3的sys.path中也有一个指向Python2的sitepackage库目录的路径。如果我运行Python 3并导入枚举,print(enum.__file__)并且系统未显示此Python 2站点包路径。因此,一个非常粗糙和肮脏的技巧是直接修改导入枚举的模块(遵循回溯路径)并在导入枚举之前插入以下代码:

import sys
for i, p in enumerate(sys.path):
    if "python27" in p.lower() or "python2.7" in p.lower(): sys.path.pop(i)
import enum

那解决了我的问题。

I have Python 2 and Python 3 installed on my computer. For some strange reason I have in the sys.path of Python 3 also a path to the sitepackage library directory of Python2 when the re module is called. If I run Python 3 and import enum and print(enum.__file__) the system does not show this Python 2 path to site-packages. So a very rough and dirty hack is, to directly modify the module in which enum is imported (follow the traceback paths) and insert the following code just before importing enum:

import sys
for i, p in enumerate(sys.path):
    if "python27" in p.lower() or "python2.7" in p.lower(): sys.path.pop(i)
import enum

That solved my problem.


回答 11

安装enum34的1.1.8版本对我有用。

我能够通过向pyproject.toml添加enum34 =“ == 1.1.8”来解决此问题。显然enum34在v1.1.8中具有避免此错误的功能,但在v1.1.9 +中已退步。不过,这只是一种解决方法。更好的解决方案是使程序包使用环境标记,因此除非需要,您根本不需要安装enum34。

来源:https//github.com/python-poetry/poetry/issues/1122

Installing version 1.1.8 of enum34 worked for me.

I was able to fix this by adding enum34 = “==1.1.8” to pyproject.toml. Apparently enum34 had a feature in v1.1.8 that avoided this error, but this regressed in v1.1.9+. This is just a workaround though. The better solution would be for packages to use environment markers so you don’t have to install enum34 at all unless needed.

Source: https://github.com/python-poetry/poetry/issues/1122


回答 12

即使我在运行python -m grpc_tools.protoc –version时遇到了这个问题,也必须设置PYTHONPATH直到站点包并关闭所有命令提示符窗口,然后它才能工作。希望它对gRPC用户有所帮助。

Even I had this issue while running python -m grpc_tools.protoc –version Had to set the PYTHONPATH till site-packages and shutdown all the command prompt windows and it worked. Hope it helps for gRPC users.


回答 13

我在使用python3.8和tensorflow 2.2.0的虚拟环境内核中的jupyterlab的ubuntu20.04中遇到了这个问题。错误消息原为

 Traceback (most recent call last):
  File "/usr/lib/python2.7/runpy.py", line 174, in _run_module_as_main
    "__main__", fname, loader, pkg_name)
  File "/usr/lib/python2.7/runpy.py", line 72, in _run_code
    exec code in run_globals
  File "/home/hu-mka/.local/lib/python2.7/site-packages/ipykernel_launcher.py", line 15, in <module>
    from ipykernel import kernelapp as app
  File "/home/hu-mka/.local/lib/python2.7/site-packages/ipykernel/__init__.py", line 2, in <module>
    from .connect import *
  File "/home/hu-mka/.local/lib/python2.7/site-packages/ipykernel/connect.py", line 13, in <module>
    from IPython.core.profiledir import ProfileDir
  File "/home/hu-mka/.local/lib/python2.7/site-packages/IPython/__init__.py", line 48, in <module>
    from .core.application import Application
  File "/home/hu-mka/.local/lib/python2.7/site-packages/IPython/core/application.py", line 23, in <module>
    from traitlets.config.application import Application, catch_config_error
  File "/home/hu-mka/.local/lib/python2.7/site-packages/traitlets/__init__.py", line 1, in <module>
    from .traitlets import *
  File "/home/hu-mka/.local/lib/python2.7/site-packages/traitlets/traitlets.py", line 49, in <module>
    import enum
ImportError: No module named enum

问题是在/ usr / bin / python中的符号链接中指向python2。解:

cd /usr/bin/
sudo ln -sf python3 python

我希望python2快死了!马库斯Terveisin

I had this problem in ubuntu20.04 in jupyterlab in my virtual env kernel with python3.8 and tensorflow 2.2.0. Error message was

 Traceback (most recent call last):
  File "/usr/lib/python2.7/runpy.py", line 174, in _run_module_as_main
    "__main__", fname, loader, pkg_name)
  File "/usr/lib/python2.7/runpy.py", line 72, in _run_code
    exec code in run_globals
  File "/home/hu-mka/.local/lib/python2.7/site-packages/ipykernel_launcher.py", line 15, in <module>
    from ipykernel import kernelapp as app
  File "/home/hu-mka/.local/lib/python2.7/site-packages/ipykernel/__init__.py", line 2, in <module>
    from .connect import *
  File "/home/hu-mka/.local/lib/python2.7/site-packages/ipykernel/connect.py", line 13, in <module>
    from IPython.core.profiledir import ProfileDir
  File "/home/hu-mka/.local/lib/python2.7/site-packages/IPython/__init__.py", line 48, in <module>
    from .core.application import Application
  File "/home/hu-mka/.local/lib/python2.7/site-packages/IPython/core/application.py", line 23, in <module>
    from traitlets.config.application import Application, catch_config_error
  File "/home/hu-mka/.local/lib/python2.7/site-packages/traitlets/__init__.py", line 1, in <module>
    from .traitlets import *
  File "/home/hu-mka/.local/lib/python2.7/site-packages/traitlets/traitlets.py", line 49, in <module>
    import enum
ImportError: No module named enum

problem was that in symbolic link in /usr/bin/python was pointing to python2. Solution:

cd /usr/bin/
sudo ln -sf python3 python

Hopefully Python 2 usage will drop off completely soon.


回答 14

如果在运行时有这个问题测试PyCharm,确保第二个框选中的配置。

If you having this issue when running tests in PyCharm, make sure the second box is unchecked in the configurations.


回答 15

如果有人有试图从virtualenv中运行Jupyter内核的时候这个问题,只需添加正确的PYTHONPATHkernel.json您的virtualenv内核(Python 3的例子)的:

{
 "argv": [
  "/usr/local/Cellar/python/3.6.5/bin/python3.6",
  "-m",
  "ipykernel_launcher",
  "-f",
  "{connection_file}"
 ],
 "display_name": "Python 3 (TensorFlow)",
 "language": "python",
 "env": {
     "PYTHONPATH":     "/Users/dimitrijer/git/mlai/.venv/lib/python3.6:/Users/dimitrijer/git/mlai/.venv/lib/python3.6/lib-dynload:/usr/local/Cellar/python/3.6.5/Frameworks/Python.framework/Versions/3.6/lib/python3.6:/Users/dimitrijer/git/mlai/.venv/lib/python3.6/site-packages"
}
}

If anyone is having this problem when trying to run Jupyter kernel from a virtualenv, just add correct PYTHONPATH to kernel.json of your virtualenv kernel (Python 3 in example):

{
 "argv": [
  "/usr/local/Cellar/python/3.6.5/bin/python3.6",
  "-m",
  "ipykernel_launcher",
  "-f",
  "{connection_file}"
 ],
 "display_name": "Python 3 (TensorFlow)",
 "language": "python",
 "env": {
     "PYTHONPATH":     "/Users/dimitrijer/git/mlai/.venv/lib/python3.6:/Users/dimitrijer/git/mlai/.venv/lib/python3.6/lib-dynload:/usr/local/Cellar/python/3.6.5/Frameworks/Python.framework/Versions/3.6/lib/python3.6:/Users/dimitrijer/git/mlai/.venv/lib/python3.6/site-packages"
}
}

2个数字列表之间的余弦相似度

问题:2个数字列表之间的余弦相似度

我需要计算两个列表之间的余弦相似度,比如说列表1是,列表2是。我不能使用任何东西,例如numpy或统计模块。我必须使用通用模块(数学等)(并尽可能减少模块数量,以减少花费的时间)。dataSetIdataSetII

假设dataSetIis [3, 45, 7, 2]dataSetIIis [2, 54, 13, 15]。列表的长度始终相等。

当然,余弦相似度在0到1之间,因此,它将用舍入到小数点后三位或四位format(round(cosine, 3))

预先非常感谢您的帮助。

I need to calculate the cosine similarity between two lists, let’s say for example list 1 which is dataSetI and list 2 which is dataSetII. I cannot use anything such as numpy or a statistics module. I must use common modules (math, etc) (and the least modules as possible, at that, to reduce time spent).

Let’s say dataSetI is [3, 45, 7, 2] and dataSetII is [2, 54, 13, 15]. The length of the lists are always equal.

Of course, the cosine similarity is between 0 and 1, and for the sake of it, it will be rounded to the third or fourth decimal with format(round(cosine, 3)).

Thank you very much in advance for helping.


回答 0

您应该尝试SciPy。它具有许多有用的科学例程,例如“用于数值计算积分,求解微分方程,优化和稀疏矩阵的例程”。它使用超快速优化的NumPy进行数字运算。请参阅此处进行安装。

注意space.distance.cosine计算的是distance,而不是相似度。因此,必须从1中减去该值才能获得相似性

from scipy import spatial

dataSetI = [3, 45, 7, 2]
dataSetII = [2, 54, 13, 15]
result = 1 - spatial.distance.cosine(dataSetI, dataSetII)

You should try SciPy. It has a bunch of useful scientific routines for example, “routines for computing integrals numerically, solving differential equations, optimization, and sparse matrices.” It uses the superfast optimized NumPy for its number crunching. See here for installing.

Note that spatial.distance.cosine computes the distance, and not the similarity. So, you must subtract the value from 1 to get the similarity.

from scipy import spatial

dataSetI = [3, 45, 7, 2]
dataSetII = [2, 54, 13, 15]
result = 1 - spatial.distance.cosine(dataSetI, dataSetII)

回答 1

numpy仅基于的另一个版本

from numpy import dot
from numpy.linalg import norm

cos_sim = dot(a, b)/(norm(a)*norm(b))

another version based on numpy only

from numpy import dot
from numpy.linalg import norm

cos_sim = dot(a, b)/(norm(a)*norm(b))

回答 2

您可以使用cosine_similarity功能表单sklearn.metrics.pairwise 文档

In [23]: from sklearn.metrics.pairwise import cosine_similarity

In [24]: cosine_similarity([[1, 0, -1]], [[-1,-1, 0]])
Out[24]: array([[-0.5]])

You can use cosine_similarity function form sklearn.metrics.pairwise docs

In [23]: from sklearn.metrics.pairwise import cosine_similarity

In [24]: cosine_similarity([[1, 0, -1]], [[-1,-1, 0]])
Out[24]: array([[-0.5]])

回答 3

我认为这里的性能并不重要,但是我无法抗拒。zip()函数完全复制了两个向量(实际上是更多的矩阵转置),只是以“ Pythonic”顺序获取数据。计时一下实现细节将是很有趣的:

import math
def cosine_similarity(v1,v2):
    "compute cosine similarity of v1 to v2: (v1 dot v2)/{||v1||*||v2||)"
    sumxx, sumxy, sumyy = 0, 0, 0
    for i in range(len(v1)):
        x = v1[i]; y = v2[i]
        sumxx += x*x
        sumyy += y*y
        sumxy += x*y
    return sumxy/math.sqrt(sumxx*sumyy)

v1,v2 = [3, 45, 7, 2], [2, 54, 13, 15]
print(v1, v2, cosine_similarity(v1,v2))

Output: [3, 45, 7, 2] [2, 54, 13, 15] 0.972284251712

这一次经历了像C一样的噪声,一次提取元素,但没有批量数组复制,并且所有重要的事情都在单个for循环中完成,并且使用单个平方根。

预计到达时间:将打印调用更新为功能。(原始版本是Python 2.7,而不是3.3。当前版本在带from __future__ import print_function声明的Python 2.7下运行。)两种方法的输出都是相同的。

在3.0GHz Core 2 Duo上的CPYthon 2.7.3:

>>> timeit.timeit("cosine_similarity(v1,v2)",setup="from __main__ import cosine_similarity, v1, v2")
2.4261788514654654
>>> timeit.timeit("cosine_measure(v1,v2)",setup="from __main__ import cosine_measure, v1, v2")
8.794677709375264

因此,在这种情况下,非Python方式要快3.6倍。

I don’t suppose performance matters much here, but I can’t resist. The zip() function completely recopies both vectors (more of a matrix transpose, actually) just to get the data in “Pythonic” order. It would be interesting to time the nuts-and-bolts implementation:

import math
def cosine_similarity(v1,v2):
    "compute cosine similarity of v1 to v2: (v1 dot v2)/{||v1||*||v2||)"
    sumxx, sumxy, sumyy = 0, 0, 0
    for i in range(len(v1)):
        x = v1[i]; y = v2[i]
        sumxx += x*x
        sumyy += y*y
        sumxy += x*y
    return sumxy/math.sqrt(sumxx*sumyy)

v1,v2 = [3, 45, 7, 2], [2, 54, 13, 15]
print(v1, v2, cosine_similarity(v1,v2))

Output: [3, 45, 7, 2] [2, 54, 13, 15] 0.972284251712

That goes through the C-like noise of extracting elements one-at-a-time, but does no bulk array copying and gets everything important done in a single for loop, and uses a single square root.

ETA: Updated print call to be a function. (The original was Python 2.7, not 3.3. The current runs under Python 2.7 with a from __future__ import print_function statement.) The output is the same, either way.

CPYthon 2.7.3 on 3.0GHz Core 2 Duo:

>>> timeit.timeit("cosine_similarity(v1,v2)",setup="from __main__ import cosine_similarity, v1, v2")
2.4261788514654654
>>> timeit.timeit("cosine_measure(v1,v2)",setup="from __main__ import cosine_measure, v1, v2")
8.794677709375264

So, the unpythonic way is about 3.6 times faster in this case.


回答 4

不使用任何进口

math.sqrt(x)

可以替换为

x ** .5

在不使用numpy.dot()的情况下,您必须使用列表理解来创建自己的点函数:

def dot(A,B): 
    return (sum(a*b for a,b in zip(A,B)))

然后只需应用余弦相似度公式即可:

def cosine_similarity(a,b):
    return dot(a,b) / ( (dot(a,a) **.5) * (dot(b,b) ** .5) )

without using any imports

math.sqrt(x)

can be replaced with

x** .5

without using numpy.dot() you have to create your own dot function using list comprehension:

def dot(A,B): 
    return (sum(a*b for a,b in zip(A,B)))

and then its just a simple matter of applying the cosine similarity formula:

def cosine_similarity(a,b):
    return dot(a,b) / ( (dot(a,a) **.5) * (dot(b,b) ** .5) )

回答 5

我根据问题中的几个答案进行了基准测试,以下代码段被认为是最佳选择:

def dot_product2(v1, v2):
    return sum(map(operator.mul, v1, v2))


def vector_cos5(v1, v2):
    prod = dot_product2(v1, v2)
    len1 = math.sqrt(dot_product2(v1, v1))
    len2 = math.sqrt(dot_product2(v2, v2))
    return prod / (len1 * len2)

结果使我感到惊讶的是,基于的实现scipy不是最快的。我进行了分析,发现scipy中的余弦需要大量时间才能将向量从python列表转换为numpy数组。

I did a benchmark based on several answers in the question and the following snippet is believed to be the best choice:

def dot_product2(v1, v2):
    return sum(map(operator.mul, v1, v2))


def vector_cos5(v1, v2):
    prod = dot_product2(v1, v2)
    len1 = math.sqrt(dot_product2(v1, v1))
    len2 = math.sqrt(dot_product2(v2, v2))
    return prod / (len1 * len2)

The result makes me surprised that the implementation based on scipy is not the fastest one. I profiled and find that cosine in scipy takes a lot of time to cast a vector from python list to numpy array.


回答 6

import math
from itertools import izip

def dot_product(v1, v2):
    return sum(map(lambda x: x[0] * x[1], izip(v1, v2)))

def cosine_measure(v1, v2):
    prod = dot_product(v1, v2)
    len1 = math.sqrt(dot_product(v1, v1))
    len2 = math.sqrt(dot_product(v2, v2))
    return prod / (len1 * len2)

您可以在计算后将其取整:

cosine = format(round(cosine_measure(v1, v2), 3))

如果您希望它真的很短,则可以使用以下一种格式:

from math import sqrt
from itertools import izip

def cosine_measure(v1, v2):
    return (lambda (x, y, z): x / sqrt(y * z))(reduce(lambda x, y: (x[0] + y[0] * y[1], x[1] + y[0]**2, x[2] + y[1]**2), izip(v1, v2), (0, 0, 0)))
import math
from itertools import izip

def dot_product(v1, v2):
    return sum(map(lambda x: x[0] * x[1], izip(v1, v2)))

def cosine_measure(v1, v2):
    prod = dot_product(v1, v2)
    len1 = math.sqrt(dot_product(v1, v1))
    len2 = math.sqrt(dot_product(v2, v2))
    return prod / (len1 * len2)

You can round it after computing:

cosine = format(round(cosine_measure(v1, v2), 3))

If you want it really short, you can use this one-liner:

from math import sqrt
from itertools import izip

def cosine_measure(v1, v2):
    return (lambda (x, y, z): x / sqrt(y * z))(reduce(lambda x, y: (x[0] + y[0] * y[1], x[1] + y[0]**2, x[2] + y[1]**2), izip(v1, v2), (0, 0, 0)))

回答 7

您可以使用简单的函数在Python中执行此操作:

def get_cosine(text1, text2):
  vec1 = text1
  vec2 = text2
  intersection = set(vec1.keys()) & set(vec2.keys())
  numerator = sum([vec1[x] * vec2[x] for x in intersection])
  sum1 = sum([vec1[x]**2 for x in vec1.keys()])
  sum2 = sum([vec2[x]**2 for x in vec2.keys()])
  denominator = math.sqrt(sum1) * math.sqrt(sum2)
  if not denominator:
     return 0.0
  else:
     return round(float(numerator) / denominator, 3)
dataSet1 = [3, 45, 7, 2]
dataSet2 = [2, 54, 13, 15]
get_cosine(dataSet1, dataSet2)

You can do this in Python using simple function:

def get_cosine(text1, text2):
  vec1 = text1
  vec2 = text2
  intersection = set(vec1.keys()) & set(vec2.keys())
  numerator = sum([vec1[x] * vec2[x] for x in intersection])
  sum1 = sum([vec1[x]**2 for x in vec1.keys()])
  sum2 = sum([vec2[x]**2 for x in vec2.keys()])
  denominator = math.sqrt(sum1) * math.sqrt(sum2)
  if not denominator:
     return 0.0
  else:
     return round(float(numerator) / denominator, 3)
dataSet1 = [3, 45, 7, 2]
dataSet2 = [2, 54, 13, 15]
get_cosine(dataSet1, dataSet2)

回答 8

使用numpy将一个数字列表与多个列表(矩阵)进行比较:

def cosine_similarity(vector,matrix):
   return ( np.sum(vector*matrix,axis=1) / ( np.sqrt(np.sum(matrix**2,axis=1)) * np.sqrt(np.sum(vector**2)) ) )[::-1]

Using numpy compare one list of numbers to multiple lists(matrix):

def cosine_similarity(vector,matrix):
   return ( np.sum(vector*matrix,axis=1) / ( np.sqrt(np.sum(matrix**2,axis=1)) * np.sqrt(np.sum(vector**2)) ) )[::-1]

回答 9

您可以使用以下简单函数来计算余弦相似度:

def cosine_similarity(a, b):
return sum([i*j for i,j in zip(a, b)])/(math.sqrt(sum([i*i for i in a]))* math.sqrt(sum([i*i for i in b])))

You can use this simple function to calculate the cosine similarity:

def cosine_similarity(a, b):
return sum([i*j for i,j in zip(a, b)])/(math.sqrt(sum([i*i for i in a]))* math.sqrt(sum([i*i for i in b])))

回答 10

如果您碰巧已经在使用PyTorch,则应使用其CosineSimilarity实现

假设你有两个nnumpy.ndarrayS,v1v2,即它们的形状都是(n,)。这就是它们的余弦相似度的方法:

import torch
import torch.nn as nn

cos = nn.CosineSimilarity()
cos(torch.tensor([v1]), torch.tensor([v2])).item()

或者,假设你有两个numpy.ndarray小号w1w2,其形状都是(m, n)。以下内容为您提供了余弦相似度列表,每一个都是in中的一行w1和in中的相应行之间的余弦相似性w2

cos(torch.tensor(w1), torch.tensor(w2)).tolist()

If you happen to be using PyTorch already, you should go with their CosineSimilarity implementation.

Suppose you have two n-dimensional numpy.ndarrays, v1 and v2, i.e. their shapes are both (n,). Here’s how you get their cosine similarity:

import torch
import torch.nn as nn

cos = nn.CosineSimilarity()
cos(torch.tensor([v1]), torch.tensor([v2])).item()

Or suppose you have two numpy.ndarrays w1 and w2, whose shapes are both (m, n). The following gets you a list of cosine similarities, each being the cosine similarity between a row in w1 and the corresponding row in w2:

cos(torch.tensor(w1), torch.tensor(w2)).tolist()

回答 11

对于无法使用NumPy的情况,所有答案都非常有用。如果可以的话,这是另一种方法:

def cosine(x, y):
    dot_products = np.dot(x, y.T)
    norm_products = np.linalg.norm(x) * np.linalg.norm(y)
    return dot_products / (norm_products + EPSILON)

也要牢记EPSILON = 1e-07确保分裂。

All the answers are great for situations where you cannot use NumPy. If you can, here is another approach:

def cosine(x, y):
    dot_products = np.dot(x, y.T)
    norm_products = np.linalg.norm(x) * np.linalg.norm(y)
    return dot_products / (norm_products + EPSILON)

Also bear in mind about EPSILON = 1e-07 to secure the division.


如何使用Python3读写INI文件?

问题:如何使用Python3读写INI文件?

我需要读取,写入和创建一个INI使用Python3文件。

文件文件

default_path = "/path/name/"
default_file = "file.txt"

Python档案:

#    Read file and and create if it not exists
config = iniFile( 'FILE.INI' )

#    Get "default_path"
config.default_path

#    Print (string)/path/name
print config.default_path

#    Create or Update
config.append( 'default_path', 'var/shared/' )
config.append( 'default_message', 'Hey! help me!!' )

更新的 FILE.INI

default_path    = "var/shared/"
default_file    = "file.txt"
default_message = "Hey! help me!!"

I need to read, write and create an INI file with Python3.

FILE.INI

default_path = "/path/name/"
default_file = "file.txt"

Python File:

#    Read file and and create if it not exists
config = iniFile( 'FILE.INI' )

#    Get "default_path"
config.default_path

#    Print (string)/path/name
print config.default_path

#    Create or Update
config.append( 'default_path', 'var/shared/' )
config.append( 'default_message', 'Hey! help me!!' )

UPDATED FILE.INI

default_path    = "var/shared/"
default_file    = "file.txt"
default_message = "Hey! help me!!"

回答 0

可以从以下开始:

import configparser

config = configparser.ConfigParser()
config.read('FILE.INI')
print(config['DEFAULT']['path'])     # -> "/path/name/"
config['DEFAULT']['path'] = '/var/shared/'    # update
config['DEFAULT']['default_message'] = 'Hey! help me!!'   # create

with open('FILE.INI', 'w') as configfile:    # save
    config.write(configfile)

您可以在官方configparser文档中找到更多信息

This can be something to start with:

import configparser

config = configparser.ConfigParser()
config.read('FILE.INI')
print(config['DEFAULT']['path'])     # -> "/path/name/"
config['DEFAULT']['path'] = '/var/shared/'    # update
config['DEFAULT']['default_message'] = 'Hey! help me!!'   # create

with open('FILE.INI', 'w') as configfile:    # save
    config.write(configfile)

You can find more at the official configparser documentation.


回答 1

这是一个完整的读取,更新和写入示例。

输入文件test.ini

[section_a]
string_val = hello
bool_val = false
int_val = 11
pi_val = 3.14

工作代码。

try:
    from configparser import ConfigParser
except ImportError:
    from ConfigParser import ConfigParser  # ver. < 3.0

# instantiate
config = ConfigParser()

# parse existing file
config.read('test.ini')

# read values from a section
string_val = config.get('section_a', 'string_val')
bool_val = config.getboolean('section_a', 'bool_val')
int_val = config.getint('section_a', 'int_val')
float_val = config.getfloat('section_a', 'pi_val')

# update existing value
config.set('section_a', 'string_val', 'world')

# add a new section and some values
config.add_section('section_b')
config.set('section_b', 'meal_val', 'spam')
config.set('section_b', 'not_found_val', '404')

# save to a file
with open('test_update.ini', 'w') as configfile:
    config.write(configfile)

输出文件test_update.ini

[section_a]
string_val = world
bool_val = false
int_val = 11
pi_val = 3.14

[section_b]
meal_val = spam
not_found_val = 404

原始输入文件保持不变。

Here’s a complete read, update and write example.

Input file, test.ini

[section_a]
string_val = hello
bool_val = false
int_val = 11
pi_val = 3.14

Working code.

try:
    from configparser import ConfigParser
except ImportError:
    from ConfigParser import ConfigParser  # ver. < 3.0

# instantiate
config = ConfigParser()

# parse existing file
config.read('test.ini')

# read values from a section
string_val = config.get('section_a', 'string_val')
bool_val = config.getboolean('section_a', 'bool_val')
int_val = config.getint('section_a', 'int_val')
float_val = config.getfloat('section_a', 'pi_val')

# update existing value
config.set('section_a', 'string_val', 'world')

# add a new section and some values
config.add_section('section_b')
config.set('section_b', 'meal_val', 'spam')
config.set('section_b', 'not_found_val', '404')

# save to a file
with open('test_update.ini', 'w') as configfile:
    config.write(configfile)

Output file, test_update.ini

[section_a]
string_val = world
bool_val = false
int_val = 11
pi_val = 3.14

[section_b]
meal_val = spam
not_found_val = 404

The original input file remains untouched.


回答 2

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

在这种情况下,Python的标准库可能会有所帮助。

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

Python’s standard library might be helpful in this case.


回答 3

该标准ConfigParser通常需要通过进行访问config['section_name']['key'],这很无聊。稍加修改即可实现属性访问:

class AttrDict(dict):
    def __init__(self, *args, **kwargs):
        super(AttrDict, self).__init__(*args, **kwargs)
        self.__dict__ = self

AttrDict是派生自该类的类,该类dict允许同时通过字典键和属性访问:a.x is a['x']

我们可以在以下类中使用此类ConfigParser

config = configparser.ConfigParser(dict_type=AttrDict)
config.read('application.ini')

现在我们得到application.ini

[general]
key = value

>>> config._sections.general.key
'value'

The standard ConfigParser normally requires access via config['section_name']['key'], which is no fun. A little modification can deliver attribute access:

class AttrDict(dict):
    def __init__(self, *args, **kwargs):
        super(AttrDict, self).__init__(*args, **kwargs)
        self.__dict__ = self

AttrDict is a class derived from dict which allows access via both dictionary keys and attribute access: that means a.x is a['x']

We can use this class in ConfigParser:

config = configparser.ConfigParser(dict_type=AttrDict)
config.read('application.ini')

and now we get application.ini with:

[general]
key = value

as

>>> config._sections.general.key
'value'

回答 4

ConfigObj是ConfigParser的很好替代品,它提供了更多的灵活性:

  • 嵌套的节(子节),任意级别
  • 列出值
  • 多行值
  • 字符串插值(替代)
  • 与功能强大的验证系统集成,包括自动类型检查/转换重复部分并允许使用默认值
  • 写出配置文件时,ConfigObj保留所有注释以及成员和节的顺序
  • 使用配置文件的许多有用方法和选项(例如“ reload”方法)
  • 完全支持Unicode

它有一些缺点:

  • 您不能设置定界符,它必须是=…(拉取请求
  • 您不能有空值,但是可以,但是它们看起来很喜欢:fuabr =而不是fubar看起来怪异和错误的值。

ConfigObj is a good alternative to ConfigParser which offers a lot more flexibility:

  • Nested sections (subsections), to any level
  • List values
  • Multiple line values
  • String interpolation (substitution)
  • Integrated with a powerful validation system including automatic type checking/conversion repeated sections and allowing default values
  • When writing out config files, ConfigObj preserves all comments and the order of members and sections
  • Many useful methods and options for working with configuration files (like the ‘reload’ method)
  • Full Unicode support

It has some draw backs:

  • You cannot set the delimiter, it has to be =… (pull request)
  • You cannot have empty values, well you can but they look liked: fuabr = instead of just fubar which looks weird and wrong.

回答 5

我的backup_settings.ini文件中的内容

[Settings]
year = 2020

用于阅读的python代码

import configparser
config = configparser.ConfigParser()
config.read('backup_settings.ini') #path of your .ini file
year = config.get("Settings","year") 
print(year)

用于编写或更新

from pathlib import Path
import configparser
myfile = Path('backup_settings.ini')  #Path of your .ini file
config.read(myfile)
config.set('Settings', 'year','2050') #Updating existing entry 
config.set('Settings', 'day','sunday') #Writing new entry
config.write(myfile.open("w"))

输出

[Settings]
year = 2050
day = sunday

contents in my backup_settings.ini file

[Settings]
year = 2020

python code for reading

import configparser
config = configparser.ConfigParser()
config.read('backup_settings.ini') #path of your .ini file
year = config.get("Settings","year") 
print(year)

for writing or updating

from pathlib import Path
import configparser
myfile = Path('backup_settings.ini')  #Path of your .ini file
config.read(myfile)
config.set('Settings', 'year','2050') #Updating existing entry 
config.set('Settings', 'day','sunday') #Writing new entry
config.write(myfile.open("w"))

output

[Settings]
year = 2050
day = sunday

避免默认参数为空列表的pythonic方法是什么?

问题:避免默认参数为空列表的pythonic方法是什么?

有时,使用默认参数(一个空列表)似乎很自然。但是Python在这些情况下会产生意外的行为

例如,如果我有一个功能:

def my_func(working_list = []):
    working_list.append("a")
    print(working_list)

第一次调用它时,默认设置将起作用,但是此后的调用将更新现有列表(每个调用一个“ a”)并打印更新的版本。

那么,什么是获得我想要的行为的Python方法(每次调用都会有一个新列表)?

Sometimes it seems natural to have a default parameter which is an empty list. Yet Python gives unexpected behavior in these situations.

If for example, I have a function:

def my_func(working_list = []):
    working_list.append("a")
    print(working_list)

The first time it is called the default will work, but calls after that will update the existing list (with one “a” each call) and print the updated version.

So, what is the pythonic way to get the behavior I desire (a fresh list on each call)?


回答 0

def my_func(working_list=None):
    if working_list is None: 
        working_list = []

    working_list.append("a")
    print(working_list)

文档说您应该将其None用作默认值,并在函数主体中对其进行显式测试

def my_func(working_list=None):
    if working_list is None: 
        working_list = []

    working_list.append("a")
    print(working_list)

The docs say you should use None as the default and explicitly test for it in the body of the function.


回答 1

现有答案已经按要求提供了直接解决方案。但是,由于这对于新Python程序员来说是一个非常常见的陷阱,因此有必要添加解释python为何采用这种方式的解释,在《Python的Hitchhikers指南》中很好地总结为“ Mutable Default Arguments ”: http:// docs .python-guide.org / en / latest / writing / gotchas /

Quote:“ Python的默认参数在定义函数时进行一次评估,而不是在每次调用函数时都进行评估(例如Ruby)。这意味着,如果您使用可变的默认参数并对它进行突变,您将拥有将该对象也更改为将来对函数的所有调用

实现它的示例代码:

def foo(element, to=None):
    if to is None:
        to = []
    to.append(element)
    return to

Other answers have already already provided the direct solutions as asked for, however, since this is a very common pitfall for new Python programmers, it’s worth adding the explanation of why Python behaves this way, which is nicely summarized in The Hitchhikers Guide to Python under Mutable Default Arguments:

Python’s default arguments are evaluated once when the function is defined, not each time the function is called (like it is in say, Ruby). This means that if you use a mutable default argument and mutate it, you will and have mutated that object for all future calls to the function as well.


回答 2

在这种情况下,这并不重要,但是您可以使用对象标识来测试None:

if working_list is None: working_list = []

您还可以利用布尔运算符or在python中的定义方式:

working_list = working_list or []

尽管如果调用者给您一个空列表(该列表为false)作为working_list并期望您的函数修改他提供的列表,这将出乎意料。

Not that it matters in this case, but you can use object identity to test for None:

if working_list is None: working_list = []

You could also take advantage of how the boolean operator or is defined in python:

working_list = working_list or []

Though this will behave unexpectedly if the caller gives you an empty list (which counts as false) as working_list and expects your function to modify the list he gave it.


回答 3

如果该函数的目的是修改作为参数传递的参数working_list,请参见HenryR的答案(= None,检查内部是否为None)。

但是,如果您不想改变该参数,只需将其用作列表的起点,则可以简单地将其复制:

def myFunc(starting_list = []):
    starting_list = list(starting_list)
    starting_list.append("a")
    print starting_list

(或者只是在这种简单情况下,print starting_list + ["a"]但我想那只是一个玩具示例)

通常,在Python中更改参数是不好的样式。完全期望使对象发生突变的唯一功能是该对象的方法。突变可选参数的情况更是罕见-仅在某些调用中发生的副作用确实是最好的接口吗?

  • 如果按照“输出参数”的C习惯执行此操作,则完全没有必要-您始终可以将多个值作为元组返回。

  • 如果这样做是为了有效地构建一长串结果而不创建中间列表,请考虑将其作为生成器编写并result_list.extend(myFunc())在调用时使用。这样,您的调用约定仍然非常干净。

经常更改可选arg的一种模式递归函数中的隐藏“ memo” arg:

def depth_first_walk_graph(graph, node, _visited=None):
    if _visited is None:
        _visited = set()  # create memo once in top-level call

    if node in _visited:
        return
    _visited.add(node)
    for neighbour in graph[node]:
        depth_first_walk_graph(graph, neighbour, _visited)

If the intent of the function is to modify the parameter passed as working_list, see HenryR’s answer (=None, check for None inside).

But if you didn’t intend to mutate the argument, just use it as starting point for a list, you can simply copy it:

def myFunc(starting_list = []):
    starting_list = list(starting_list)
    starting_list.append("a")
    print starting_list

(or in this simple case just print starting_list + ["a"] but I guess that was just a toy example)

In general, mutating your arguments is bad style in Python. The only functions that are fully expected to mutate an object are methods of the object. It’s even rarer to mutate an optional argument — is a side effect that happens only in some calls really the best interface?

  • If you do it from the C habit of “output arguments”, that’s completely unnecessary – you can always return multiple values as a tuple.

  • If you do this to efficiently build a long list of results without building intermediate lists, consider writing it as a generator and using result_list.extend(myFunc()) when you are calling it. This way your calling conventions remains very clean.

One pattern where mutating an optional arg is frequently done is a hidden “memo” arg in recursive functions:

def depth_first_walk_graph(graph, node, _visited=None):
    if _visited is None:
        _visited = set()  # create memo once in top-level call

    if node in _visited:
        return
    _visited.add(node)
    for neighbour in graph[node]:
        depth_first_walk_graph(graph, neighbour, _visited)

回答 4

我可能没什么意思,但是请记住,如果您只想传递可变数量的参数,则pythonic方法是传递元组*args或字典**kargs。这些是可选的,并且比语法更好myFunc([1, 2, 3])

如果要传递元组:

def myFunc(arg1, *args):
  print args
  w = []
  w += args
  print w
>>>myFunc(1, 2, 3, 4, 5, 6, 7)
(2, 3, 4, 5, 6, 7)
[2, 3, 4, 5, 6, 7]

如果您想通过字典:

def myFunc(arg1, **kargs):
   print kargs
>>>myFunc(1, option1=2, option2=3)
{'option2' : 2, 'option1' : 3}

I might be off-topic, but remember that if you just want to pass a variable number of arguments, the pythonic way is to pass a tuple *args or a dictionary **kargs. These are optional and are better than the syntax myFunc([1, 2, 3]).

If you want to pass a tuple:

def myFunc(arg1, *args):
  print args
  w = []
  w += args
  print w
>>>myFunc(1, 2, 3, 4, 5, 6, 7)
(2, 3, 4, 5, 6, 7)
[2, 3, 4, 5, 6, 7]

If you want to pass a dictionary:

def myFunc(arg1, **kargs):
   print kargs
>>>myFunc(1, option1=2, option2=3)
{'option2' : 2, 'option1' : 3}

回答 5

已经提供了正确的正确答案。我只是想提供另一种语法来编写您想做的事情,例如,当您想创建一个带有默认空列表的类时,我会发现它更漂亮:

class Node(object):
    def __init__(self, _id, val, parents=None, children=None):
        self.id = _id
        self.val = val
        self.parents = parents if parents is not None else []
        self.children = children if children is not None else []

此代码段使用if else运算符语法。我特别喜欢它,因为它是一个整齐的小单行,没有冒号等,而且读起来几乎像普通的英语句子。:)

您可以写

def myFunc(working_list=None):
    working_list = [] if working_list is None else working_list
    working_list.append("a")
    print working_list

There have already been good and correct answers provided. I just wanted to give another syntax to write what you want to do which I find more beautiful when you for instance want to create a class with default empty lists:

class Node(object):
    def __init__(self, _id, val, parents=None, children=None):
        self.id = _id
        self.val = val
        self.parents = parents if parents is not None else []
        self.children = children if children is not None else []

This snippet makes use of the if else operator syntax. I like it especially because it’s a neat little one-liner without colons, etc. involved and it nearly reads like a normal English sentence. :)

In your case you could write

def myFunc(working_list=None):
    working_list = [] if working_list is None else working_list
    working_list.append("a")
    print working_list

回答 6

我参加了UCSC扩展类 Python for programmer

def Fn(data = []):

a)是个好主意,这样您的数据列表在每次调用时都开始为空。

b)是一个好主意,以便对函数的所有调用(在调用中不提供任何参数)都将获得空列表作为数据。

c)是一个合理的想法,只要您的数据是字符串列表即可。

d)是个坏主意,因为默认[]将累积数据,而默认[]将随后续调用而改变。

回答:

d)是个坏主意,因为默认[]将累积数据,而默认[]将随后续调用而改变。

I took the UCSC extension class Python for programmer

Which is true of: def Fn(data = []):

a) is a good idea so that your data lists start empty with every call.

b) is a good idea so that all calls to the function that do not provide any arguments on the call will get the empty list as data.

c) is a reasonable idea as long as your data is a list of strings.

d) is a bad idea because the default [] will accumulate data and the default [] will change with subsequent calls.

Answer:

d) is a bad idea because the default [] will accumulate data and the default [] will change with subsequent calls.


为什么在Python 3.5中str.translate比Python 3.4更快?

问题:为什么在Python 3.5中str.translate比Python 3.4更快?

我试图使用text.translate()Python 3.4 从给定的字符串中删除不需要的字符。

最小的代码是:

import sys 
s = 'abcde12345@#@$#%$'
mapper = dict.fromkeys(i for i in range(sys.maxunicode) if chr(i) in '@#$')
print(s.translate(mapper))

它按预期工作。但是,在Python 3.4和Python 3.5中执行相同的程序会产生很大的不同。

计算时间的代码是

python3 -m timeit -s "import sys;s = 'abcde12345@#@$#%$'*1000 ; mapper = dict.fromkeys(i for i in range(sys.maxunicode) if chr(i) in '@#$'); "   "s.translate(mapper)"

Python 3.4程序花费1.3毫秒,而Python 3.5中的同一程序仅花费26.4μs

Python 3.5中有哪些改进使其比Python 3.4更快?

I was trying to remove unwanted characters from a given string using text.translate() in Python 3.4.

The minimal code is:

import sys 
s = 'abcde12345@#@$#%$'
mapper = dict.fromkeys(i for i in range(sys.maxunicode) if chr(i) in '@#$')
print(s.translate(mapper))

It works as expected. However the same program when executed in Python 3.4 and Python 3.5 gives a large difference.

The code to calculate timings is

python3 -m timeit -s "import sys;s = 'abcde12345@#@$#%$'*1000 ; mapper = dict.fromkeys(i for i in range(sys.maxunicode) if chr(i) in '@#$'); "   "s.translate(mapper)"

The Python 3.4 program takes 1.3ms whereas the same program in Python 3.5 takes only 26.4μs.

What has improved in Python 3.5 that makes it faster compared to Python 3.4?


回答 0

TL; DR- 问题21118


长篇故事

Josh Rosenberg发现str.translate()与相比,该功能非常慢bytes.translate,他提出了一个问题,并指出:

在Python 3中,str.translate()通常是性能悲观,而不是优化。

为什么str.translate()慢呢?

str.translate()速度很慢的主要原因是查找曾经在Python字典中进行。

使用maketrans此问题使情况变得更糟。类似的方法是使用bytes256个项目构建一个C数组以快速查找表。因此,较高级别的Python的使用dict使str.translate()Python 3.4中的速度非常慢。

现在发生什么事?

第一种方法是添加一个小的补丁,translate_writer,但是速度的提高并不令人满意。很快又测试了另一个补丁fast_translate,它产生了非常好的结果,加速了55%。

从文件中可以看到的主要变化是Python字典查找已更改为C级查找。

现在的速度几乎与 bytes

                                unpatched           patched

str.translate                   4.55125927699919    0.7898181750006188
str.translate from bytes trans  1.8910855210015143  0.779950579000797

这里需要注意的一点是,性能增强仅在ASCII字符串中突出。

正如JFSebastian在下面的注释中提到的,在3.5之前,对于ASCII和非ASCII情况,转换以前都以相同的方式工作。但是从3.5 ASCII起,大小写要快得多。

早期的ASCII与非ASCII几乎相同,但是现在我们可以看到性能有了很大的变化。

答案所示,它可以从71.6μs改善到2.33μs 。

以下代码演示了这一点

python3.5 -m timeit -s "text = 'mJssissippi'*100; d=dict(J='i')" "text.translate(d)"
100000 loops, best of 3: 2.3 usec per loop
python3.5 -m timeit -s "text = 'm\U0001F602ssissippi'*100; d={'\U0001F602': 'i'}" "text.translate(d)"
10000 loops, best of 3: 117 usec per loop

python3 -m timeit -s "text = 'm\U0001F602ssissippi'*100; d={'\U0001F602': 'i'}" "text.translate(d)"
10000 loops, best of 3: 91.2 usec per loop
python3 -m timeit -s "text = 'mJssissippi'*100; d=dict(J='i')" "text.translate(d)"
10000 loops, best of 3: 101 usec per loop

结果列表:

         Python 3.4    Python 3.5  
Ascii     91.2          2.3 
Unicode   101           117

TL;DR – ISSUE 21118


The long Story

Josh Rosenberg found out that the str.translate() function is very slow compared to the bytes.translate, he raised an issue, stating that:

In Python 3, str.translate() is usually a performance pessimization, not optimization.

Why was str.translate() slow?

The main reason for str.translate() to be very slow was that the lookup used to be in a Python dictionary.

The usage of maketrans made this problem worse. The similar approach using bytes builds a C array of 256 items to fast table lookup. Hence the usage of higher level Python dict makes the str.translate() in Python 3.4 very slow.

What happened now?

The first approach was to add a small patch, translate_writer, However the speed increase was not that pleasing. Soon another patch fast_translate was tested and it yielded very nice results of up to 55% speedup.

The main change as can be seen from the file is that the Python dictionary lookup is changed into a C level lookup.

The speeds now are almost the same as bytes

                                unpatched           patched

str.translate                   4.55125927699919    0.7898181750006188
str.translate from bytes trans  1.8910855210015143  0.779950579000797

A small note here is that the performance enhancement is only prominent in ASCII strings.

As J.F.Sebastian mentions in a comment below, Before 3.5, translate used to work in the same way for both ASCII and non-ASCII cases. However from 3.5 ASCII case is much faster.

Earlier ASCII vs non-ascii used to be almost same, however now we can see a great change in the performance.

It can be an improvement from 71.6μs to 2.33μs as seen in this answer.

The following code demonstrates this

python3.5 -m timeit -s "text = 'mJssissippi'*100; d=dict(J='i')" "text.translate(d)"
100000 loops, best of 3: 2.3 usec per loop
python3.5 -m timeit -s "text = 'm\U0001F602ssissippi'*100; d={'\U0001F602': 'i'}" "text.translate(d)"
10000 loops, best of 3: 117 usec per loop

python3 -m timeit -s "text = 'm\U0001F602ssissippi'*100; d={'\U0001F602': 'i'}" "text.translate(d)"
10000 loops, best of 3: 91.2 usec per loop
python3 -m timeit -s "text = 'mJssissippi'*100; d=dict(J='i')" "text.translate(d)"
10000 loops, best of 3: 101 usec per loop

Tabulation of the results:

         Python 3.4    Python 3.5  
Ascii     91.2          2.3 
Unicode   101           117

python3和python3m可执行文件之间的区别

问题:python3和python3m可执行文件之间的区别

是什么之间的区别/usr/bin/python3/usr/bin/python3mexecutibles?

我在Ubuntu 13.04上观察到了它们,但是Google建议它们也存在于其他发行版中。

这两个文件具有相同的md5sum,但似乎不是符号链接或硬链接。这两个文件返回的索引节点号不同,ls -li并且测试find -xdev -samefile /usr/bin/python3.3不返回任何其他文件。

有人在AskUbuntu上问了类似的问题,但我想更多地了解这两个文件之间的区别。

What is the difference between the /usr/bin/python3 and /usr/bin/python3m executibles?

I am observing them on Ubuntu 13.04, but Google suggests that they exist on other distributions too.

The two files have the same md5sum, but do not seem to be symbolic links or hard links; the two files have different inode numbers returned by ls -li and testing find -xdev -samefile /usr/bin/python3.3 does not return any other files.

Someone asked a similar question on AskUbuntu, but I wanted to find out more about the difference between the two files.


回答 0

值得称赞的chepner指出我已经拥有该解决方案的链接。

Python实现可以在文件名标签中适当地包含其他标志。例如,在POSIX系统上,这些标志也将有助于文件名:

–with-pydebug(标志:d)

–with-pymalloc(标志:m)

–with-wide-unicode(标志:u)

通过PEP 3149

关于m标志,这是Pymalloc的含义:

Pymalloc是由Vladimir Marangozov编写的专用对象分配器,它是Python 2.1中新增的一项功能。Pymalloc旨在比系统malloc()更快,并且对于Python程序典型的分配模式而言,具有较少的内存开销。分配器使用C的malloc()函数获取较大的内存池,然后从这些池执行较小的内存请求。

通过Python 2.3的新功能

最后,这两个文件可能在某些系统上被硬链接。虽然两个文件在我的Ubuntu 13.04系统上具有不同的inode编号(因此是不同的文件),但两年前comp.lang.python帖子显示它们曾经被硬链接过。

Credit for this goes to chepner for pointing out that I already had the link to the solution.

Python implementations MAY include additional flags in the file name tag as appropriate. For example, on POSIX systems these flags will also contribute to the file name:

–with-pydebug (flag: d)

–with-pymalloc (flag: m)

–with-wide-unicode (flag: u)

via PEP 3149.

Regarding the m flag specifically, this is what Pymalloc is:

Pymalloc, a specialized object allocator written by Vladimir Marangozov, was a feature added to Python 2.1. Pymalloc is intended to be faster than the system malloc() and to have less memory overhead for allocation patterns typical of Python programs. The allocator uses C’s malloc() function to get large pools of memory and then fulfills smaller memory requests from these pools.

via What’s New in Python 2.3

Finally, the two files may be hardlinked on some systems. While the two files have different inode numbers on my Ubuntu 13.04 system (thus are different files), a comp.lang.python post from two years ago shows that they once were hardlinked.


插入两个字符串的最pythonic方式

问题:插入两个字符串的最pythonic方式

将两个字符串网格化的最Python方式是什么?

例如:

输入:

u = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
l = 'abcdefghijklmnopqrstuvwxyz'

输出:

'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz'

What’s the most pythonic way to mesh two strings together?

For example:

Input:

u = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
l = 'abcdefghijklmnopqrstuvwxyz'

Output:

'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz'

回答 0

对我来说,最pythonic *的方式是以下代码,它几乎做同样的事情,但是使用+运算符来连接每个字符串中的各个字符:

res = "".join(i + j for i, j in zip(u, l))
print(res)
# 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz'

它也比使用两个join()调用更快:

In [5]: l1 = 'A' * 1000000; l2 = 'a' * 1000000

In [6]: %timeit "".join("".join(item) for item in zip(l1, l2))
1 loops, best of 3: 442 ms per loop

In [7]: %timeit "".join(i + j for i, j in zip(l1, l2))
1 loops, best of 3: 360 ms per loop

存在更快的方法,但是它们常常使代码模糊。

注:如果两个输入字符串是相同的长度,则较长的一个将被截断,zip停在较短字符串的结尾迭代。在这种情况下,zip应该使用模块中的zip_longestizip_longest在Python 2中)而不是一个itertools来确保两个字符串都已用尽。


*引用Python之禅可读性很重要
Pythonic = 对我而言可读性i + j至少对于我的眼睛来说,更容易从视觉上进行解析。

For me, the most pythonic* way is the following which pretty much does the same thing but uses the + operator for concatenating the individual characters in each string:

res = "".join(i + j for i, j in zip(u, l))
print(res)
# 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz'

It is also faster than using two join() calls:

In [5]: l1 = 'A' * 1000000; l2 = 'a' * 1000000

In [6]: %timeit "".join("".join(item) for item in zip(l1, l2))
1 loops, best of 3: 442 ms per loop

In [7]: %timeit "".join(i + j for i, j in zip(l1, l2))
1 loops, best of 3: 360 ms per loop

Faster approaches exist, but they often obfuscate the code.

Note: If the two input strings are not the same length then the longer one will be truncated as zip stops iterating at the end of the shorter string. In this case instead of zip one should use zip_longest (izip_longest in Python 2) from the itertools module to ensure that both strings are fully exhausted.


*To take a quote from the Zen of Python: Readability counts.
Pythonic = readability for me; i + j is just visually parsed more easily, at least for my eyes.


回答 1

更快的选择

其他方式:

res = [''] * len(u) * 2
res[::2] = u
res[1::2] = l
print(''.join(res))

输出:

'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz'

速度

看起来更快:

%%timeit
res = [''] * len(u) * 2
res[::2] = u
res[1::2] = l
''.join(res)

100000 loops, best of 3: 4.75 µs per loop

比迄今为止最快的解决方案:

%timeit "".join(list(chain.from_iterable(zip(u, l))))

100000 loops, best of 3: 6.52 µs per loop

同样对于较大的字符串:

l1 = 'A' * 1000000; l2 = 'a' * 1000000

%timeit "".join(list(chain.from_iterable(zip(l1, l2))))
1 loops, best of 3: 151 ms per loop


%%timeit
res = [''] * len(l1) * 2
res[::2] = l1
res[1::2] = l2
''.join(res)

10 loops, best of 3: 92 ms per loop

Python 3.5.1。

不同长度字符串的变化

u = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
l = 'abcdefghijkl'

较短的一个确定长度(zip()等效)

min_len = min(len(u), len(l))
res = [''] * min_len * 2 
res[::2] = u[:min_len]
res[1::2] = l[:min_len]
print(''.join(res))

输出:

AaBbCcDdEeFfGgHhIiJjKkLl

更长的长度决定长度(itertools.zip_longest(fillvalue='')等效)

min_len = min(len(u), len(l))
res = [''] * min_len * 2 
res[::2] = u[:min_len]
res[1::2] = l[:min_len]
res += u[min_len:] + l[min_len:]
print(''.join(res))

输出:

AaBbCcDdEeFfGgHhIiJjKkLlMNOPQRSTUVWXYZ

Faster Alternative

Another way:

res = [''] * len(u) * 2
res[::2] = u
res[1::2] = l
print(''.join(res))

Output:

'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz'

Speed

Looks like it is faster:

%%timeit
res = [''] * len(u) * 2
res[::2] = u
res[1::2] = l
''.join(res)

100000 loops, best of 3: 4.75 µs per loop

than the fastest solution so far:

%timeit "".join(list(chain.from_iterable(zip(u, l))))

100000 loops, best of 3: 6.52 µs per loop

Also for the larger strings:

l1 = 'A' * 1000000; l2 = 'a' * 1000000

%timeit "".join(list(chain.from_iterable(zip(l1, l2))))
1 loops, best of 3: 151 ms per loop


%%timeit
res = [''] * len(l1) * 2
res[::2] = l1
res[1::2] = l2
''.join(res)

10 loops, best of 3: 92 ms per loop

Python 3.5.1.

Variation for strings with different lengths

u = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
l = 'abcdefghijkl'

Shorter one determines length (zip() equivalent)

min_len = min(len(u), len(l))
res = [''] * min_len * 2 
res[::2] = u[:min_len]
res[1::2] = l[:min_len]
print(''.join(res))

Output:

AaBbCcDdEeFfGgHhIiJjKkLl

Longer one determines length (itertools.zip_longest(fillvalue='') equivalent)

min_len = min(len(u), len(l))
res = [''] * min_len * 2 
res[::2] = u[:min_len]
res[1::2] = l[:min_len]
res += u[min_len:] + l[min_len:]
print(''.join(res))

Output:

AaBbCcDdEeFfGgHhIiJjKkLlMNOPQRSTUVWXYZ

回答 2

join()zip()

>>> ''.join(''.join(item) for item in zip(u,l))
'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz'

With join() and zip().

>>> ''.join(''.join(item) for item in zip(u,l))
'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz'

回答 3

在Python 2上,到目前为止,做事的最快方法是小字符串列表切片的速度大约是3倍,长字符串列表切片的速度大约是30倍。

res = bytearray(len(u) * 2)
res[::2] = u
res[1::2] = l
str(res)

但是,这在Python 3上不起作用。您可以实现类似

res = bytearray(len(u) * 2)
res[::2] = u.encode("ascii")
res[1::2] = l.encode("ascii")
res.decode("ascii")

但是到那时,您已经失去了对小型字符串进行列表切片所获得的收益(对于长字符串而言,它的速度仍然是20倍),并且这甚至还不适用于非ASCII字符。

FWIW,如果您在大量字符串上执行此操作并且需要每个周期,并且由于某种原因必须使用Python字符串…以下是操作方法:

res = bytearray(len(u) * 4 * 2)

u_utf32 = u.encode("utf_32_be")
res[0::8] = u_utf32[0::4]
res[1::8] = u_utf32[1::4]
res[2::8] = u_utf32[2::4]
res[3::8] = u_utf32[3::4]

l_utf32 = l.encode("utf_32_be")
res[4::8] = l_utf32[0::4]
res[5::8] = l_utf32[1::4]
res[6::8] = l_utf32[2::4]
res[7::8] = l_utf32[3::4]

res.decode("utf_32_be")

特殊情况下,较小类型的外壳也将有所帮助。FWIW,这只是长字符串列表切片速度的3倍,而小字符串则 4到5倍。

无论哪种方式,我都喜欢join解决方案,但是由于在其他地方提到了时间安排,我认为我也应该加入。

On Python 2, by far the faster way to do things, at ~3x the speed of list slicing for small strings and ~30x for long ones, is

res = bytearray(len(u) * 2)
res[::2] = u
res[1::2] = l
str(res)

This wouldn’t work on Python 3, though. You could implement something like

res = bytearray(len(u) * 2)
res[::2] = u.encode("ascii")
res[1::2] = l.encode("ascii")
res.decode("ascii")

but by then you’ve already lost the gains over list slicing for small strings (it’s still 20x the speed for long strings) and this doesn’t even work for non-ASCII characters yet.

FWIW, if you are doing this on massive strings and need every cycle, and for some reason have to use Python strings… here’s how to do it:

res = bytearray(len(u) * 4 * 2)

u_utf32 = u.encode("utf_32_be")
res[0::8] = u_utf32[0::4]
res[1::8] = u_utf32[1::4]
res[2::8] = u_utf32[2::4]
res[3::8] = u_utf32[3::4]

l_utf32 = l.encode("utf_32_be")
res[4::8] = l_utf32[0::4]
res[5::8] = l_utf32[1::4]
res[6::8] = l_utf32[2::4]
res[7::8] = l_utf32[3::4]

res.decode("utf_32_be")

Special-casing the common case of smaller types will help too. FWIW, this is only 3x the speed of list slicing for long strings and a factor of 4 to 5 slower for small strings.

Either way I prefer the join solutions, but since timings were mentioned elsewhere I thought I might as well join in.


回答 4

如果您想要最快的方法,可以将itertools与结合使用operator.add

In [36]: from operator import add

In [37]: from itertools import  starmap, izip

In [38]: timeit "".join([i + j for i, j in uzip(l1, l2)])
1 loops, best of 3: 142 ms per loop

In [39]: timeit "".join(starmap(add, izip(l1,l2)))
1 loops, best of 3: 117 ms per loop

In [40]: timeit "".join(["".join(item) for item in zip(l1, l2)])
1 loops, best of 3: 196 ms per loop

In [41]:  "".join(starmap(add, izip(l1,l2))) ==  "".join([i + j   for i, j in izip(l1, l2)]) ==  "".join(["".join(item) for item in izip(l1, l2)])
Out[42]: True

但是合并起来izipchain.from_iterable更快了

In [2]: from itertools import  chain, izip

In [3]: timeit "".join(chain.from_iterable(izip(l1, l2)))
10 loops, best of 3: 98.7 ms per loop

chain(*和之间也存在实质性差异 chain.from_iterable(...

In [5]: timeit "".join(chain(*izip(l1, l2)))
1 loops, best of 3: 212 ms per loop

没有像join那样的生成器,传递一个总是慢一些,因为python首先会使用内容来建立一个列表,因为它会对数据进行两次传递,一次传递所需的大小,一次传递实际的大小使用生成器无法实现的联接:

join.h

 /* Here is the general case.  Do a pre-pass to figure out the total
  * amount of space we'll need (sz), and see whether all arguments are
  * bytes-like.
   */

另外,如果您使用不同长度的字符串,并且不想丢失数据,则可以使用izip_longest

In [22]: from itertools import izip_longest    
In [23]: a,b = "hlo","elworld"

In [24]:  "".join(chain.from_iterable(izip_longest(a, b,fillvalue="")))
Out[24]: 'helloworld'

对于python 3,它称为 zip_longest

但是对于python2来说,veedrac的建议是迄今为止最快的:

In [18]: %%timeit
res = bytearray(len(u) * 2)
res[::2] = u
res[1::2] = l
str(res)
   ....: 
100 loops, best of 3: 2.68 ms per loop

If you want the fastest way, you can combine itertools with operator.add:

In [36]: from operator import add

In [37]: from itertools import  starmap, izip

In [38]: timeit "".join([i + j for i, j in uzip(l1, l2)])
1 loops, best of 3: 142 ms per loop

In [39]: timeit "".join(starmap(add, izip(l1,l2)))
1 loops, best of 3: 117 ms per loop

In [40]: timeit "".join(["".join(item) for item in zip(l1, l2)])
1 loops, best of 3: 196 ms per loop

In [41]:  "".join(starmap(add, izip(l1,l2))) ==  "".join([i + j   for i, j in izip(l1, l2)]) ==  "".join(["".join(item) for item in izip(l1, l2)])
Out[42]: True

But combining izip and chain.from_iterable is faster again

In [2]: from itertools import  chain, izip

In [3]: timeit "".join(chain.from_iterable(izip(l1, l2)))
10 loops, best of 3: 98.7 ms per loop

There is also a substantial difference between chain(* and chain.from_iterable(....

In [5]: timeit "".join(chain(*izip(l1, l2)))
1 loops, best of 3: 212 ms per loop

There is no such thing as a generator with join, passing one is always going to be slower as python will first build a list using the content because it does two passes over the data, one to figure out the size needed and one to actually do the join which would not be possible using a generator:

join.h:

 /* Here is the general case.  Do a pre-pass to figure out the total
  * amount of space we'll need (sz), and see whether all arguments are
  * bytes-like.
   */

Also if you have different length strings and you don’t want to lose data you can use izip_longest :

In [22]: from itertools import izip_longest    
In [23]: a,b = "hlo","elworld"

In [24]:  "".join(chain.from_iterable(izip_longest(a, b,fillvalue="")))
Out[24]: 'helloworld'

For python 3 it is called zip_longest

But for python2, veedrac’s suggestion is by far the fastest:

In [18]: %%timeit
res = bytearray(len(u) * 2)
res[::2] = u
res[1::2] = l
str(res)
   ....: 
100 loops, best of 3: 2.68 ms per loop

回答 5

您也可以使用map和执行此操作operator.add

from operator import add

u = 'AAAAA'
l = 'aaaaa'

s = "".join(map(add, u, l))

输出

'AaAaAaAaAa'

map的作用是,它从第一个可迭代对象获取每个元素,u并从第二个可迭代对象获取第一个元素,l并应用作为第一个参数提供的函数add。然后加入只是加入他们。

You could also do this using map and operator.add:

from operator import add

u = 'AAAAA'
l = 'aaaaa'

s = "".join(map(add, u, l))

Output:

'AaAaAaAaAa'

What map does is it takes every element from the first iterable u and the first elements from the second iterable l and applies the function supplied as the first argument add. Then join just joins them.


回答 6

吉姆的答案很好,但是,如果您不介意几次导入,这是我最喜欢的选择:

from functools import reduce
from operator import add

reduce(add, map(add, u, l))

Jim’s answer is great, but here’s my favorite option, if you don’t mind a couple of imports:

from functools import reduce
from operator import add

reduce(add, map(add, u, l))

回答 7

这些建议很多都假设字符串长度相等。也许涵盖了所有合理的用例,但至少对我来说,您似乎也想适应长度不同的字符串。还是我是唯一认为网格应该像这样工作的人:

u = "foobar"
l = "baz"
mesh(u,l) = "fboaozbar"

一种方法是:

def mesh(a,b):
    minlen = min(len(a),len(b))
    return "".join(["".join(x+y for x,y in zip(a,b)),a[minlen:],b[minlen:]])

A lot of these suggestions assume the strings are of equal length. Maybe that covers all reasonable use cases, but at least to me it seems that you might want to accomodate strings of differing lengths too. Or am I the only one thinking the mesh should work a bit like this:

u = "foobar"
l = "baz"
mesh(u,l) = "fboaozbar"

One way to do this would be the following:

def mesh(a,b):
    minlen = min(len(a),len(b))
    return "".join(["".join(x+y for x,y in zip(a,b)),a[minlen:],b[minlen:]])

回答 8

我喜欢使用两个fors,变量名可以提示/提醒正在发生的事情:

"".join(char for pair in zip(u,l) for char in pair)

I like using two fors, the variable names can give a hint/reminder to what is going on:

"".join(char for pair in zip(u,l) for char in pair)

回答 9

只是添加另一种更基本的方法:

st = ""
for char in u:
    st = "{0}{1}{2}".format( st, char, l[ u.index( char ) ] )

Just to add another, more basic approach:

st = ""
for char in u:
    st = "{0}{1}{2}".format( st, char, l[ u.index( char ) ] )

回答 10

有点不讲究Python而不考虑这里的double-list-comprehension答案,用O(1)来处理n个字符串:

"".join(c for cs in itertools.zip_longest(*all_strings) for c in cs)

all_strings您要插入的字符串的列表在哪里。就您而言,all_strings = [u, l]。完整的使用示例如下所示:

import itertools
a = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
b = 'abcdefghijklmnopqrstuvwxyz'
all_strings = [a,b]
interleaved = "".join(c for cs in itertools.zip_longest(*all_strings) for c in cs)
print(interleaved)
# 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz'

喜欢许多答案,最快吗?可能不是,但是简单而灵活。另外,在没有增加太多复杂性的情况下,这比公认的答案要快一些(通常,在python中字符串添加有点慢):

In [7]: l1 = 'A' * 1000000; l2 = 'a' * 1000000;

In [8]: %timeit "".join(a + b for i, j in zip(l1, l2))
1 loops, best of 3: 227 ms per loop

In [9]: %timeit "".join(c for cs in zip(*(l1, l2)) for c in cs)
1 loops, best of 3: 198 ms per loop

Feels a bit un-pythonic not to consider the double-list-comprehension answer here, to handle n string with O(1) effort:

"".join(c for cs in itertools.zip_longest(*all_strings) for c in cs)

where all_strings is a list of the strings you want to interleave. In your case, all_strings = [u, l]. A full use example would look like this:

import itertools
a = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
b = 'abcdefghijklmnopqrstuvwxyz'
all_strings = [a,b]
interleaved = "".join(c for cs in itertools.zip_longest(*all_strings) for c in cs)
print(interleaved)
# 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz'

Like many answers, fastest? Probably not, but simple and flexible. Also, without too much added complexity, this is slightly faster than the accepted answer (in general, string addition is a bit slow in python):

In [7]: l1 = 'A' * 1000000; l2 = 'a' * 1000000;

In [8]: %timeit "".join(a + b for i, j in zip(l1, l2))
1 loops, best of 3: 227 ms per loop

In [9]: %timeit "".join(c for cs in zip(*(l1, l2)) for c in cs)
1 loops, best of 3: 198 ms per loop

回答 11

可能比当前领先的解决方案更快,更短:

from itertools import chain

u = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
l = 'abcdefghijklmnopqrstuvwxyz'

res = "".join(chain(*zip(u, l)))

快速策略是在C级别上尽可能多地做。相同的zip_longest()修复了不均匀的字符串,它会与chain()来自同一个模块,所以在这里不能给我太多点!

我提出的其他解决方案:

res = "".join(u[x] + l[x] for x in range(len(u)))

res = "".join(k + l[i] for i, k in enumerate(u))

Potentially faster and shorter than the current leading solution:

from itertools import chain

u = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
l = 'abcdefghijklmnopqrstuvwxyz'

res = "".join(chain(*zip(u, l)))

Strategy speed-wise is to do as much at the C-level as possible. Same zip_longest() fix for uneven strings and it would be coming out of the same module as chain() so can’t ding me too many points there!

Other solutions I came up with along the way:

res = "".join(u[x] + l[x] for x in range(len(u)))

res = "".join(k + l[i] for i, k in enumerate(u))

回答 12

你可以用1iteration_utilities.roundrobin

u = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
l = 'abcdefghijklmnopqrstuvwxyz'

from iteration_utilities import roundrobin
''.join(roundrobin(u, l))
# returns 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz'

ManyIterables同一包中的类:

from iteration_utilities import ManyIterables
ManyIterables(u, l).roundrobin().as_string()
# returns 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz'

1这来自我编写的第三方库iteration_utilities

You could use iteration_utilities.roundrobin1

u = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
l = 'abcdefghijklmnopqrstuvwxyz'

from iteration_utilities import roundrobin
''.join(roundrobin(u, l))
# returns 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz'

or the ManyIterables class from the same package:

from iteration_utilities import ManyIterables
ManyIterables(u, l).roundrobin().as_string()
# returns 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz'

1 This is from a third-party library I have written: iteration_utilities.


回答 13

我将使用zip()来获得一种可读且简单的方法:

result = ''
for cha, chb in zip(u, l):
    result += '%s%s' % (cha, chb)

print result
# 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz'

I would use zip() to get a readable and easy way:

result = ''
for cha, chb in zip(u, l):
    result += '%s%s' % (cha, chb)

print result
# 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz'

Python 3中的字符串格式

问题:Python 3中的字符串格式

我在Python 2中执行此操作:

"(%d goals, $%d)" % (self.goals, self.penalties)

这是什么Python 3版本?

我尝试在线搜索示例,但一直在获取Python 2版本。

I do this in Python 2:

"(%d goals, $%d)" % (self.goals, self.penalties)

What is the Python 3 version of this?

I tried searching for examples online but I kept getting Python 2 versions.


回答 0

这是有关“新”格式语法的文档。一个例子是:

"({:d} goals, ${:d})".format(self.goals, self.penalties)

如果goalspenalties均为整数(即​​默认格式为ok),则可以将其缩短为:

"({} goals, ${})".format(self.goals, self.penalties)

而且由于参数是的字段self,所以还有一种使用单个参数两次的方法(如@Burhan Khalid在评论中指出的那样):

"({0.goals} goals, ${0.penalties})".format(self)

说明:

  • {} 表示仅下一个位置参数,采用默认格式;
  • {0}表示带有index的参数0,默认格式;
  • {:d} 是下一个位置参数,采用十进制整数格式;
  • {0:d}是带有index的参数0,十进制整数格式。

选择参数时,您可以执行许多其他操作(使用命名参数而不是位置参数,访问字段等),还有许多格式选项(填充数字,使用千位分隔符,显示或不显示符号等)。其他一些例子:

"({goals} goals, ${penalties})".format(goals=2, penalties=4)
"({goals} goals, ${penalties})".format(**self.__dict__)

"first goal: {0.goal_list[0]}".format(self)
"second goal: {.goal_list[1]}".format(self)

"conversion rate: {:.2f}".format(self.goals / self.shots) # '0.20'
"conversion rate: {:.2%}".format(self.goals / self.shots) # '20.45%'
"conversion rate: {:.0%}".format(self.goals / self.shots) # '20%'

"self: {!s}".format(self) # 'Player: Bob'
"self: {!r}".format(self) # '<__main__.Player instance at 0x00BF7260>'

"games: {:>3}".format(player1.games)  # 'games: 123'
"games: {:>3}".format(player2.games)  # 'games:   4'
"games: {:0>3}".format(player2.games) # 'games: 004'

注意:正如其他人指出的那样,新格式并不能取代前一种格式,这两种格式都可以在Python 3和更高版本的Python 2中使用。有人可能会说这是优先考虑的问题,但是恕我直言,较新的版本比旧的版本更具表现力,并且在编写新代码时应使用(当然,除非它针对较旧的环境)。

Here are the docs about the “new” format syntax. An example would be:

"({:d} goals, ${:d})".format(self.goals, self.penalties)

If both goals and penalties are integers (i.e. their default format is ok), it could be shortened to:

"({} goals, ${})".format(self.goals, self.penalties)

And since the parameters are fields of self, there’s also a way of doing it using a single argument twice (as @Burhan Khalid noted in the comments):

"({0.goals} goals, ${0.penalties})".format(self)

Explaining:

  • {} means just the next positional argument, with default format;
  • {0} means the argument with index 0, with default format;
  • {:d} is the next positional argument, with decimal integer format;
  • {0:d} is the argument with index 0, with decimal integer format.

There are many others things you can do when selecting an argument (using named arguments instead of positional ones, accessing fields, etc) and many format options as well (padding the number, using thousands separators, showing sign or not, etc). Some other examples:

"({goals} goals, ${penalties})".format(goals=2, penalties=4)
"({goals} goals, ${penalties})".format(**self.__dict__)

"first goal: {0.goal_list[0]}".format(self)
"second goal: {.goal_list[1]}".format(self)

"conversion rate: {:.2f}".format(self.goals / self.shots) # '0.20'
"conversion rate: {:.2%}".format(self.goals / self.shots) # '20.45%'
"conversion rate: {:.0%}".format(self.goals / self.shots) # '20%'

"self: {!s}".format(self) # 'Player: Bob'
"self: {!r}".format(self) # '<__main__.Player instance at 0x00BF7260>'

"games: {:>3}".format(player1.games)  # 'games: 123'
"games: {:>3}".format(player2.games)  # 'games:   4'
"games: {:0>3}".format(player2.games) # 'games: 004'

Note: As others pointed out, the new format does not supersede the former, both are available both in Python 3 and the newer versions of Python 2 as well. Some may say it’s a matter of preference, but IMHO the newer is much more expressive than the older, and should be used whenever writing new code (unless it’s targeting older environments, of course).


回答 1

Python 3.6现在支持PEP 498的简写文字字符串插值。对于您的用例,新语法很简单:

f"({self.goals} goals, ${self.penalties})"

这与以前的.format标准,但让一个容易做的事情一样

>>> width = 10
>>> precision = 4
>>> value = decimal.Decimal('12.34567')
>>> f'result: {value:{width}.{precision}}'
'result:      12.35'

Python 3.6 now supports shorthand literal string interpolation with PEP 498. For your use case, the new syntax is simply:

f"({self.goals} goals, ${self.penalties})"

This is similar to the previous .format standard, but lets one easily do things like:

>>> width = 10
>>> precision = 4
>>> value = decimal.Decimal('12.34567')
>>> f'result: {value:{width}.{precision}}'
'result:      12.35'

回答 2

该行在Python 3中保持原样。

>>> sys.version
'3.2 (r32:88445, Oct 20 2012, 14:09:29) \n[GCC 4.5.2]'
>>> "(%d goals, $%d)" % (self.goals, self.penalties)
'(1 goals, $2)'

That line works as-is in Python 3.

>>> sys.version
'3.2 (r32:88445, Oct 20 2012, 14:09:29) \n[GCC 4.5.2]'
>>> "(%d goals, $%d)" % (self.goals, self.penalties)
'(1 goals, $2)'

回答 3

我喜欢这种方法

my_hash = {}
my_hash["goals"] = 3 #to show number
my_hash["penalties"] = "5" #to show string
print("I scored %(goals)d goals and took %(penalties)s penalties" % my_hash)

请分别注意括号中的d和s。

输出将是:

I scored 3 goals and took 5 penalties

I like this approach

my_hash = {}
my_hash["goals"] = 3 #to show number
my_hash["penalties"] = "5" #to show string
print("I scored %(goals)d goals and took %(penalties)s penalties" % my_hash)

Note the appended d and s to the brackets respectively.

output will be:

I scored 3 goals and took 5 penalties