标签归档:python-3.x

对python 2.7的支持终止了吗?

问题:对python 2.7的支持终止了吗?

当不再支持python 2.7而不再支持python 2.7时,是否存在已知的日期/时间框架?

Is there a known date/timeframe when python 2.7 will not be supported any more in favor of python 3?


回答 0

自2014年4月13日起,来自http://hg.python.org/peps/rev/76d43e52d978(PEP 373,Python 2.7发布时间表):

Python 2.7的终止生命日期(停产日期,终止日期)已移至未来五年,即2020年。此决定旨在阐明Python 2.7的状态,并减轻那些尚无法迁移到Python 3的用户的后顾之忧。另请参阅PEP 466

As of 13 Apr 2014, from http://hg.python.org/peps/rev/76d43e52d978 (PEP 373, Python 2.7 Release Schedule):

The End Of Life date (EOL, sunset date) for Python 2.7 has been moved five years into the future, to 2020. This decision was made to clarify the status of Python 2.7 and relieve worries for those users who cannot yet migrate to Python 3. See also PEP 466.


回答 1

2010年5月,神的话语为Python 2.7 PATCHLEVEL版本将可能至少6年内作出

因此,也许是2016年,也许是以后。

编辑:推回2020年。请参阅PEP 373的修订版,并在其他答案中链接。

In May 2010, Word of God was that patchlevel releases for Python 2.7 will probably be made for at least 6 years.

So, maybe 2016, probably later.

Edit: Pushed back to 2020. See the revision to PEP 373, linked to in other answers.


回答 2

最近,该日期已更新为2020年1月1日。

参见https://pythonclock.org/

Recently, that date has been updated to January 1, 2020.

see https://pythonclock.org/


回答 3

您应该仔细阅读以下内容(参考:https : //news.ycombinator.com/item ? id =7582300):

这里没有来自python-dev列表的人有很多评论,他们并不真正理解这种差异的实际含义。核心开发人员无需维持2015年后的2.7,并且大多数人不会参与其中。那部分没有改变。发生的事情是Red Hat准备削减RHEL 7发行版,AFAIK取决于您为他们支付13年支持的费用。因此,他们将需要弄清楚如何至少在2027年之前自己获得2.7的支持。RH完全有权利分叉Python,并为自己和客户保留维护补丁(Python不是copyleft)。但,他们是好人,因此,如果仍有Python项目愿意接受这些更改,也许他们愿意至少暂时进行更改。再次,这是我基于ML讨论的推测,而不是RH实​​际上说过的。可以比喻Rails LTS,它是patio11参与[0]的Rails 2.x的商业分支。不可避免地会有人介入以支持2.7,所以让我们看看如何避免出现这样的情况,即保持2.7唯一运行的唯一方法是订阅RHEL。同时,有一些大公司在Windows上广泛使用2.7(例如Enthought,Anaconda),并且认为可以找到某个人偶尔制作Windows安装程序,前提是假定Python.org仍将托管下载。因此,实际上发生的事情不是很令人兴奋。核心提交者所做的工作与将项目按原计划进行一样没有什么不同。发生的情况是,它们将使源代码控制存储库和FTP服务器中的指示灯保持打开状态,以便捕获有兴趣继续支持2.7的大公司员工的免费劳动力。另一种选择是,RH和其他供应商创建专有且昂贵的Python 2.7分支。无论如何,这种情况最终可能会发生,但是如果二进制文件仍然出现在python.org上,并且您不必要求IT部门设置SCM和错误跟踪器,那么雇主将需要更长的时间才能注意到您应该停止提供补丁。等等 发生的情况是,它们将使源代码控制存储库和FTP服务器中的指示灯保持打开状态,以便捕获有兴趣继续支持2.7的大公司员工的免费劳动力。另一种选择是,RH和其他供应商创建专有且昂贵的Python 2.7分支。无论如何,这种情况最终可能会发生,但是如果二进制文件仍然出现在python.org上,并且您不必要求IT部门设置SCM和错误跟踪器,那么雇主将需要更长的时间才能注意到您应该停止提供补丁。等等 发生的情况是,它们将使源代码控制存储库和FTP服务器中的指示灯保持打开状态,以便捕获有兴趣继续支持2.7的大公司员工的免费劳动力。另一种选择是,RH和其他供应商创建专有且昂贵的Python 2.7分支。无论如何,这种情况最终可能会发生,但是如果二进制文件仍然出现在python.org上,并且您不必要求IT部门设置SCM和错误跟踪器,那么雇主将需要更长的时间才能注意到您应该停止提供补丁。等等

you should read this carefully (ref : https://news.ycombinator.com/item?id=7582300 ):

There are a lot of comments here from people who aren’t on the python-dev list and don’t really understand what this diff actually means. The core developers are not required to maintain 2.7 post-2015, and most of them won’t be involved in it. That part hasn’t changed. What is happening is that Red Hat is preparing to cut a RHEL 7 release, which AFAIK depending on how much you pay them they support for 13 years. So they will need to figure out how to support 2.7 themselves at least through 2027. Here is where I am reading between the lines. RH are well within their right to fork Python and keep their maintenance patches to themselves and their customers (Python’s not copyleft). But, they are nice guys and so maybe they are willing to upstream their changes at least for awhile if there is still a Python project willing to accept them. Again, this is my speculation based on the ML discussion, not what RH has actually said they will do. An analogy can be made to Rails LTS, a commercial fork of Rails 2.x that patio11 was involved in [0]. Inevitably somebody is going to step in to support 2.7, and so let’s see what we can do to avoid a situation where the only way to keep running 2.7 is to subscribe to RHEL. Meanwhile, there are some large companies that use 2.7 extensively on Windows (e.g. Enthought, Anaconda) and the thinking goes that somebody can probably be found to produce a Windows installer once in awhile, assuming that Python.org will still host a download. So really what is happening here is not very exciting. The core committers aren’t doing anything different than leaving the project as originally planned. What is happening is that they will leave the lights on in the source control repository and on the FTP server, so as to capture the free labor from people at large companies who have an interest in continuing to support 2.7. The alternative is that RH and other vendors create proprietary and expensive forks of Python 2.7. That may end up happening anyway, but it will take longer for your employer to notice you should stop contributing your patches back if binaries still appear on python.org and you don’t have to ask IT to set up SCM and a bug tracker, etc.


回答 4

本文说:“当2.7发布时,2.x系列将进入五年的仅漏洞修复模式。”

因此,据我所知,Python 2.7是最后一个添加2.x功能的版本,尽管发现的错误将被修复(一段时间),但新功能仅适用于3.x版本。

This article says: “When 2.7 is released, the 2.x line will move into five years of a bug fix-only mode.”

So, as far as I see, Python 2.7 was the last 2.x feature-adding release, and though found bugs are going to be fixed (for some time), new features only go to 3.x releases.


回答 5

到2020年EOS 倒计时还不错。

There is also a pretty ominous countdown clock to the EOS at 2020.


回答 6

PEP 373(Python 2.7发布时间表)是您要求的那种信息的正式来源。

当前显示“计划的未来发布日期:”

  • 2014年5月2.7.7
  • 2.7.8 2014年11月
  • 2015年5月2.7.9
  • 在此日期之后,根据需要发布

另外,它说:“ Python 2.7的生命终止日期(停产日期,日落日期)已经移到了五年后的2020年。”

根据http://hg.python.org/peps/rev/76d43e52d978在2014年4月编辑

PEP 373 (Python 2.7 Release Schedule) is the official source for the kind of information you asked for.

It currently says “Planned future release dates:”

  • 2.7.7 May 2014
  • 2.7.8 November 2014
  • 2.7.9 May 2015
  • beyond this date, releases as needed

Also, it says “The End Of Life date (EOL, sunset date) for Python 2.7 has been moved five years into the future, to 2020.”

Edited in April 2014, according to http://hg.python.org/peps/rev/76d43e52d978


回答 7

《 Python开发人员指南》列出了从2.6版到当前版本的“ Python分支的状态 ”,包括其当前支持状态以及生命周期终止日期。

当前受支持(错误+安全修复):

  • Python 3.8(当前的master / develop分支)
  • Python 3.7
  • Python 3.6
  • Python 2.7(直到2020-01-01)

仅安全修复程序:

  • Python 3.5
  • Python 3.4

The Python Developer’s Guide lists the “Status of Python branches” from version 2.6 up to the current version, including their current support status with End-of-life dates.

Currently supported (bug + security fixes):

  • Python 3.8 (current master/development branch)
  • Python 3.7
  • Python 3.6
  • Python 2.7 (until 2020-01-01)

Security fixes only:

  • Python 3.5
  • Python 3.4

回答 8

Python 2.7将会永远存在。有太多使用它的旧代码,没有人愿意重写。已经有一个名为Tauthon的分支,但是如果这个毫无意义的截止日期成为现实,我们可能还会看到其他人。

Python 2.7 wil be around forever. There is too much old code that uses it that no one wants to rewrite. There is already a fork called Tauthon, but we may see others if this pointless deadline gets real.


在Python3中按索引访问dict_keys元素

问题:在Python3中按索引访问dict_keys元素

我正在尝试通过其索引访问dict_key的元素:

test = {'foo': 'bar', 'hello': 'world'}
keys = test.keys()  # dict_keys object

keys.index(0)
AttributeError: 'dict_keys' object has no attribute 'index'

我想得到foo

与:

keys[0]
TypeError: 'dict_keys' object does not support indexing

我怎样才能做到这一点?

I’m trying to access a dict_key’s element by its index:

test = {'foo': 'bar', 'hello': 'world'}
keys = test.keys()  # dict_keys object

keys.index(0)
AttributeError: 'dict_keys' object has no attribute 'index'

I want to get foo.

same with:

keys[0]
TypeError: 'dict_keys' object does not support indexing

How can I do this?


回答 0

list()而是调用字典:

keys = list(test)

在Python 3中,该dict.keys()方法返回一个字典视图对象,它作为一个集合。直接迭代字典也会产生键,因此将字典转换为列表会得到所有键的列表:

>>> test = {'foo': 'bar', 'hello': 'world'}
>>> list(test)
['foo', 'hello']
>>> list(test)[0]
'foo'

Call list() on the dictionary instead:

keys = list(test)

In Python 3, the dict.keys() method returns a dictionary view object, which acts as a set. Iterating over the dictionary directly also yields keys, so turning a dictionary into a list results in a list of all the keys:

>>> test = {'foo': 'bar', 'hello': 'world'}
>>> list(test)
['foo', 'hello']
>>> list(test)[0]
'foo'

回答 1

不是完整的答案,但可能是有用的提示。如果它确实是您想要的第一项*,那么

next(iter(q))

比快得多

list(q)[0]

对于大词典,因为不必将整个内容存储在内存中。

对于10.000.000物品,我发现它快了将近40.000倍。

*如果dict只是Python 3.6之前的伪随机项目,则第一项(此后它在标准实现中已订购,尽管不建议依赖它)。

Not a full answer but perhaps a useful hint. If it is really the first item you want*, then

next(iter(q))

is much faster than

list(q)[0]

for large dicts, since the whole thing doesn’t have to be stored in memory.

For 10.000.000 items I found it to be almost 40.000 times faster.

*The first item in case of a dict being just a pseudo-random item before Python 3.6 (after that it’s ordered in the standard implementation, although it’s not advised to rely on it).


回答 2

我想要第一个字典项的“键”和“值”对。我用下面的代码。

 key, val = next(iter(my_dict.items()))

I wanted “key” & “value” pair of a first dictionary item. I used the following code.

 key, val = next(iter(my_dict.items()))

回答 3

test = {'foo': 'bar', 'hello': 'world'}
ls = []
for key in test.keys():
    ls.append(key)
print(ls[0])

将键附加到静态定义的列表然后对其进行索引的常规方式

test = {'foo': 'bar', 'hello': 'world'}
ls = []
for key in test.keys():
    ls.append(key)
print(ls[0])

Conventional way of appending the keys to a statically defined list and then indexing it for same


回答 4

在许多情况下,这可能是XY问题。为什么要按位置索引字典键?您真的需要吗?直到最近,字典甚至还没有在Python中排序,因此访问第一个元素是任意的。

我刚刚将一些Python 2代码翻译为Python 3:

keys = d.keys()
for (i, res) in enumerate(some_list):
    k = keys[i]
    # ...

这不是很漂亮,但也不是很糟糕。起初,我正要用可怕的东西代替它

    k = next(itertools.islice(iter(keys), i, None))

在我意识到这一切写成更好之前

for (k, res) in zip(d.keys(), some_list):

效果很好。

我相信在许多其他情况下,可以避免按位置索引字典关键字。尽管字典在Python 3.7中是有序的,但是依靠它并不是很漂亮。上面的代码仅起作用,因为的内容some_list是最近从的内容中产生的d

如果您确实需要disk_keys按索引访问元素,请仔细看一下代码。也许您不需要。

In many cases, this may be an XY Problem. Why are you indexing your dictionary keys by position? Do you really need to? Until recently, dictionaries were not even ordered in Python, so accessing the first element was arbitrary.

I just translated some Python 2 code to Python 3:

keys = d.keys()
for (i, res) in enumerate(some_list):
    k = keys[i]
    # ...

which is not pretty, but not very bad either. At first, I was about to replace it by the monstrous

    k = next(itertools.islice(iter(keys), i, None))

before I realised this is all much better written as

for (k, res) in zip(d.keys(), some_list):

which works just fine.

I believe that in many other cases, indexing dictionary keys by position can be avoided. Although dictionaries are ordered in Python 3.7, relying on that is not pretty. The code above only works because the contents of some_list had been recently produced from the contents of d.

Have a hard look at your code if you really need to access a disk_keys element by index. Perhaps you don’t need to.


回答 5

试试这个

keys = [next(iter(x.keys())) for x in test]
print(list(keys))

结果看起来像这样。[‘foo’,’hello’]

您可以在此处找到更多可能的解决方案。

Try this

keys = [next(iter(x.keys())) for x in test]
print(list(keys))

The result looks like this. [‘foo’, ‘hello’]

You can find more possible solutions here.


检查环境变量是否存在的良好实践是什么?

问题:检查环境变量是否存在的良好实践是什么?

我想检查我的环境中是否存在"FOO"Python 中的变量。为此,我正在使用os标准库。阅读图书馆的文档后,我想出了两种实现目标的方法:

方法1:

if "FOO" in os.environ:
    pass

方法2:

if os.getenv("FOO") is not None:
    pass

我想知道哪种方法是好的/首选条件,以及为什么。

I want to check my environment for the existence of a variable, say "FOO", in Python. For this purpose, I am using the os standard library. After reading the library’s documentation, I have figured out 2 ways to achieve my goal:

Method 1:

if "FOO" in os.environ:
    pass

Method 2:

if os.getenv("FOO") is not None:
    pass

I would like to know which method, if either, is a good/preferred conditional and why.


回答 0

使用第一个;它直接尝试检查是否在中定义了某些内容environ。尽管第二种形式同样可以很好地工作,但是它在语义上是不足的,因为如果存在,您会得到一个返回的值,并且将其用于比较。

你想看看是否有存在 environ,为什么你会得到只是为了进行比较,然后折腾它扔掉

那正是这样getenv做的:

获取一个环境变量None如果不存在则返回。可选的第二个参数可以指定备用默认值。

(这也意味着您的支票可能只是if getenv("FOO")

你不想得到它,你想检查它的存在。

无论哪种方式,getenv都只是一个包装,environ.get但是您看不到有人通过以下方式检查映射中的成员身份:

from os import environ
if environ.get('Foo') is not None:

总结一下,使用:

if "FOO" in os.environ:
    pass

如果您只想检查是否存在,请使用,getenv("FOO")如果您确实想用可能获得的价值做某事。

Use the first; it directly tries to check if something is defined in environ. Though the second form works equally well, it’s lacking semantically since you get a value back if it exists and only use it for a comparison.

You’re trying to see if something is present in environ, why would you get just to compare it and then toss it away?

That’s exactly what getenv does:

Get an environment variable, return None if it doesn’t exist. The optional second argument can specify an alternate default.

(this also means your check could just be if getenv("FOO"))

you don’t want to get it, you want to check for it’s existence.

Either way, getenv is just a wrapper around environ.get but you don’t see people checking for membership in mappings with:

from os import environ
if environ.get('Foo') is not None:

To summarize, use:

if "FOO" in os.environ:
    pass

if you just want to check for existence, while, use getenv("FOO") if you actually want to do something with the value you might get.


回答 1

两种解决方案都有一种情况,这取决于您要根据环境变量的存在来执行什么操作。

情况1

如果您想纯粹基于环境变量的存在而采取不同的措施而又不关心其价值,那么第一个解决方案就是最佳实践。它简要描述了您要测试的内容:环境变量列表中的’FOO’。

if 'KITTEN_ALLERGY' in os.environ:
    buy_puppy()
else:
    buy_kitten()

情况二

如果您想在环境变量中未定义该值的情况下设置默认值,则第二个解决方案实际上很有用,尽管它不是您编写的形式:

server = os.getenv('MY_CAT_STREAMS', 'youtube.com')

也许

server = os.environ.get('MY_CAT_STREAMS', 'youtube.com')

请注意,如果您的应用程序有多个选项,则可能需要查看ChainMap,它允许根据键合并多个字典。ChainMap文档中有一个示例:

[...]
combined = ChainMap(command_line_args, os.environ, defaults)

There is a case for either solution, depending on what you want to do conditional on the existence of the environment variable.

Case 1

When you want to take different actions purely based on the existence of the environment variable, without caring for its value, the first solution is the best practice. It succinctly describes what you test for: is ‘FOO’ in the list of environment variables.

if 'KITTEN_ALLERGY' in os.environ:
    buy_puppy()
else:
    buy_kitten()

Case 2

When you want to set a default value if the value is not defined in the environment variables the second solution is actually useful, though not in the form you wrote it:

server = os.getenv('MY_CAT_STREAMS', 'youtube.com')

or perhaps

server = os.environ.get('MY_CAT_STREAMS', 'youtube.com')

Note that if you have several options for your application you might want to look into ChainMap, which allows to merge multiple dicts based on keys. There is an example of this in the ChainMap documentation:

[...]
combined = ChainMap(command_line_args, os.environ, defaults)

回答 2

为了安全起见

os.getenv('FOO') or 'bar'

上述答案的一个极端情况是设置了环境变量但为空

对于这种特殊情况,您会得到

print(os.getenv('FOO', 'bar'))
# prints new line - though you expected `bar`

要么

if "FOO" in os.environ:
    print("FOO is here")
# prints FOO is here - however its not

为了避免这种情况,只需使用 or

os.getenv('FOO') or 'bar'

然后你得到

print(os.getenv('FOO') or 'bar')
# bar

什么时候有空的环境变量?

您忘记在.env文件中设置值

# .env
FOO=

或导出为

$ export FOO=

或忘记设置它 settings.py

# settings.py
os.environ['FOO'] = ''

更新:如果有疑问,请查看这些单线

>>> import os; os.environ['FOO'] = ''; print(os.getenv('FOO', 'bar'))

$ FOO= python -c "import os; print(os.getenv('FOO', 'bar'))"

To be on the safe side use

os.getenv('FOO') or 'bar'

A corner case with the above answers is when the environment variable is set but is empty

For this special case you get

print(os.getenv('FOO', 'bar'))
# prints new line - though you expected `bar`

or

if "FOO" in os.environ:
    print("FOO is here")
# prints FOO is here - however its not

To avoid this just use or

os.getenv('FOO') or 'bar'

Then you get

print(os.getenv('FOO') or 'bar')
# bar

When do we have empty environment variables?

You forgot to set the value in the .env file

# .env
FOO=

or exported as

$ export FOO=

or forgot to set it in settings.py

# settings.py
os.environ['FOO'] = ''

Update: if in doubt, check out these one-liners

>>> import os; os.environ['FOO'] = ''; print(os.getenv('FOO', 'bar'))

$ FOO= python -c "import os; print(os.getenv('FOO', 'bar'))"

回答 3

如果您要检查是否未设置多个环境变量,可以执行以下操作:

import os

MANDATORY_ENV_VARS = ["FOO", "BAR"]

for var in MANDATORY_ENV_VARS:
    if var not in os.environ:
        raise EnvironmentError("Failed because {} is not set.".format(var))

In case you want to check if multiple env variables are not set, you can do the following:

import os

MANDATORY_ENV_VARS = ["FOO", "BAR"]

for var in MANDATORY_ENV_VARS:
    if var not in os.environ:
        raise EnvironmentError("Failed because {} is not set.".format(var))

回答 4

我的评论可能与给定的标签无关。但是,我是从搜索中转到此页面的。我一直在寻找R中的类似支票,并在@hugovdbeg帖子的帮助下提出了以下内容。我希望这对在R中寻求类似解决方案的人有所帮助

'USERNAME' %in% names(Sys.getenv())

My comment might not be relevant to the tags given. However, I was lead to this page from my search. I was looking for similar check in R and I came up the following with the help of @hugovdbeg post. I hope it would be helpful for someone who is looking for similar solution in R

'USERNAME' %in% names(Sys.getenv())

用python 3解开python 2对象

问题:用python 3解开python 2对象

我想知道是否有一种方法可以加载在Python 2.4和Python 3.4中腌制的对象。

我一直在大量公司遗留代码上运行2to3,以使其保持最新状态。

完成此操作后,在运行文件时出现以下错误:

  File "H:\fixers - 3.4\addressfixer - 3.4\trunk\lib\address\address_generic.py"
, line 382, in read_ref_files
    d = pickle.load(open(mshelffile, 'rb'))
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 1: ordinal
not in range(128)

在争用中查看腌制的对象,它dict在中dict,包含键和type值str

所以我的问题是:有没有办法用python 3.4加载最初在python 2.4中腌制的对象?

I’m wondering if there is a way to load an object that was pickled in Python 2.4, with Python 3.4.

I’ve been running 2to3 on a large amount of company legacy code to get it up to date.

Having done this, when running the file I get the following error:

  File "H:\fixers - 3.4\addressfixer - 3.4\trunk\lib\address\address_generic.py"
, line 382, in read_ref_files
    d = pickle.load(open(mshelffile, 'rb'))
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 1: ordinal
not in range(128)

Looking at the pickled object in contention, it’s a dict in a dict, containing keys and values of type str.

So my question is: Is there a way to load an object, originally pickled in python 2.4, with python 3.4?


回答 0

您必须告诉pickle.load()如何将Python字节串数据转换为Python 3字符串,或者可以告诉pickle将它们保留为字节。

默认设置是尝试将所有字符串数据解码为ASCII,并且解码失败。请参阅pickle.load()文档

可选的关键字参数是fix_importsencodingerrors,用于控制对Python 2生成的pickle流的兼容性支持。如果fix_imports为true,pickle将尝试将旧的Python 2名称映射到Python 3中使用的新名称。编码错误告诉pickle如何解码Python 2腌制的8位字符串实例;它们分别默认为“ ASCII”和“ strict”。该编码可以是“字节”来读取这些8位串实例作为字节对象。

将编码设置为latin1可以直接导入数据:

with open(mshelffile, 'rb') as f:
    d = pickle.load(f, encoding='latin1') 

但是您需要确认没有使用错误的编解码器对所有字符串进行解码;Latin-1适用于任何输入,因为它将字节值0-255直接映射到前256个Unicode代码点。

另一种选择是使用加载数据encoding='bytes',然后解码所有bytes键和值。

请注意,直到使用3.6.8、3.7.2和3.8.0之前的Python版本,除非使用,否则对Python 2 datetime对象数据的解泄漏都是无效的encoding='bytes'

You’ll have to tell pickle.load() how to convert Python bytestring data to Python 3 strings, or you can tell pickle to leave them as bytes.

The default is to try and decode all string data as ASCII, and that decoding fails. See the pickle.load() documentation:

Optional keyword arguments are fix_imports, encoding and errors, which are used to control compatibility support for pickle stream generated by Python 2. If fix_imports is true, pickle will try to map the old Python 2 names to the new names used in Python 3. The encoding and errors tell pickle how to decode 8-bit string instances pickled by Python 2; these default to ‘ASCII’ and ‘strict’, respectively. The encoding can be ‘bytes’ to read these 8-bit string instances as bytes objects.

Setting the encoding to latin1 allows you to import the data directly:

with open(mshelffile, 'rb') as f:
    d = pickle.load(f, encoding='latin1') 

but you’ll need to verify that none of your strings are decoded using the wrong codec; Latin-1 works for any input as it maps the byte values 0-255 to the first 256 Unicode codepoints directly.

The alternative would be to load the data with encoding='bytes', and decode all bytes keys and values afterwards.

Note that up to Python versions before 3.6.8, 3.7.2 and 3.8.0, unpickling of Python 2 datetime object data is broken unless you use encoding='bytes'.


回答 1

encoding='latin1'当对象中包含numpy数组时,使用会引起一些问题。

使用encoding='bytes'会更好。

请参阅此答案以获取有关使用的完整说明encoding='bytes'

Using encoding='latin1' causes some issues when your object contains numpy arrays in it.

Using encoding='bytes' will be better.

Please see this answer for complete explanation of using encoding='bytes'


Anaconda导出环境文件

问题:Anaconda导出环境文件

如何制作可以在其他计算机上使用的anaconda环境文件?

我使用将Anaconda python环境导出到YML conda env export > environment.yml。导出的environment.yml内容包含此行prefix: /home/superdev/miniconda3/envs/juicyenv,它映射到我的anaconda的位置,这在其他计算机上将有所不同。

How can I make anaconda environment file which could be use on other computers?

I exported my anaconda python environment to YML using conda env export > environment.yml. The exported environment.yml contains this line prefix: /home/superdev/miniconda3/envs/juicyenv which maps to my anaconda’s location which will be different on other’s pcs.


回答 0

我在conda规范中找不到任何可让您导出环境文件的内容prefix: ...。但是,正如Alex在评论中指出的那样,从文件创建环境时,conda似乎并不关心前缀行。

考虑到这一点,如果您希望其他用户不了解您的默认安装路径,则可以grep在写入之前删除前缀行environment.yml

conda env export | grep -v "^prefix: " > environment.yml

无论哪种方式,另一个用户都可以运行:

conda env create -f environment.yml

并且该环境将安装在其默认的conda环境路径中。

如果您要指定与系统默认设置不同的安装路径(与environment.yml中的’prefix’不相关),只需使用-p标记后跟所需的路径即可。

conda env create -f environment.yml -p /home/user/anaconda3/envs/env_name

请注意,Conda建议environment.yml手动创建,这对于要跨平台(Windows / Linux / Mac)共享环境的用户尤其重要。在这种情况下,您可以省略该prefix行。

I can’t find anything in the conda specs which allow you to export an environment file without the prefix: ... line. However, as Alex pointed out in the comments, conda doesn’t seem to care about the prefix line when creating an environment from file.

With that in mind, if you want the other user to have no knowledge of your default install path, you can remove the prefix line with grep before writing to environment.yml.

conda env export | grep -v "^prefix: " > environment.yml

Either way, the other user then runs:

conda env create -f environment.yml

and the environment will get installed in their default conda environment path.

If you want to specify a different install path than the default for your system (not related to ‘prefix’ in the environment.yml), just use the -p flag followed by the required path.

conda env create -f environment.yml -p /home/user/anaconda3/envs/env_name

Note that Conda recommends creating the environment.yml by hand, which is especially important if you are wanting to share your environment across platforms (Windows/Linux/Mac). In this case, you can just leave out the prefix line.


回答 1

从要安装在另一台计算机上的环境中保存软件包的最简单方法是:

$ conda list -e > req.txt

然后您可以使用安装环境

$ conda create -n new environment --file req.txt

如果使用pip,请使用以下命令:reference https://pip.pypa.io/en/stable/reference/pip_freeze/

$ env1/bin/pip freeze > requirements.txt
$ env2/bin/pip install -r requirements.txt

The easiest way to save the packages from an environment to be installed in another computer is:

$ conda list -e > req.txt

then you can install the environment using

$ conda create -n new environment --file req.txt

if you use pip, please use the following commands: reference https://pip.pypa.io/en/stable/reference/pip_freeze/

$ env1/bin/pip freeze > requirements.txt
$ env2/bin/pip install -r requirements.txt

回答 2

  • 的Linux

    conda env导出-无构建| grep -v“前缀”> environment.yml

  • 视窗

    conda env export –no-builds | findstr -v“前缀”> environment.yml


基本原理:默认情况下,conda env export包括构建信息:

$ conda env export
...
dependencies:
  - backcall=0.1.0=py37_0
  - blas=1.0=mkl
  - boto=2.49.0=py_0
...

您可以转而无需构建信息即可导出环境:

$ conda env export --no-builds
...
dependencies:
  - backcall=0.1.0
  - blas=1.0
  - boto=2.49.0
...

这使环境与Python版本和OS脱钩。

  • Linux

    conda env export –no-builds | grep -v “prefix” > environment.yml

  • Windows

    conda env export –no-builds | findstr -v “prefix” > environment.yml


Rationale: By default, conda env export includes the build information:

$ conda env export
...
dependencies:
  - backcall=0.1.0=py37_0
  - blas=1.0=mkl
  - boto=2.49.0=py_0
...

You can instead export your environment without build info:

$ conda env export --no-builds
...
dependencies:
  - backcall=0.1.0
  - blas=1.0
  - boto=2.49.0
...

Which unties the environment from the Python version and OS.


回答 3

我发现仅以字符串格式导出软件包比导出整个conda环境更方便。正如前面的答案已经建议的那样:

$ conda list -e > requirements.txt

但是,它requirements.txt包含内部版本号,这些版本号在操作系统之间(例如Mac和之间)不可移植Ubuntu。在conda env export我们可以选择--no-builds但没有的情况下conda list -e,因此我们可以通过发出以下命令来删除内部版本号:

$ sed -i -E "s/^(.*\=.*)(\=.*)/\1/" requirements.txt 

并在另一台计算机上重新创建环境:

conda create -n recreated_env --file requirements.txt 

I find exporting the packages in string format only is more portable than exporting the whole conda environment. As the previous answer already suggested:

$ conda list -e > requirements.txt

However, this requirements.txt contains build numbers which are not portable between operating systems, e.g. between Mac and Ubuntu. In conda env export we have the option --no-builds but not with conda list -e, so we can remove the build number by issuing the following command:

$ sed -i -E "s/^(.*\=.*)(\=.*)/\1/" requirements.txt 

And recreate the environment on another computer:

conda create -n recreated_env --file requirements.txt 

回答 4

  1. 首先激活您的conda环境(您要导出/备份的环境)
conda activate myEnv
  1. 将所有包导出到文件(myEnvBkp.txt)
conda list --explicit > myEnvBkp.txt
  1. 恢复/导入环境:
conda create --name myEnvRestored --file myEnvBkp.txt
  1. First activate your conda environment (the one u want to export/backup)
conda activate myEnv
  1. Export all packages to a file (myEnvBkp.txt)
conda list --explicit > myEnvBkp.txt
  1. Restore/import the environment:
conda create --name myEnvRestored --file myEnvBkp.txt

如何在Mac OS X上为Python 3安装pip?

问题:如何在Mac OS X上为Python 3安装pip?

OS X(Mavericks)已安装Python 2.7库存。但是我用3.3来做我自己的所有Python个人资料。我刚刚冲洗了3.3.2安装并安装了新的3.3.3。所以我需要pyserial再次安装。我可以按照以前做过的方式来做,即:

  1. 从pypi下载pyserial
  2. 解压pyserial.tgz
  3. cd pyserial
  4. python3 setup.py install

但是我想像酷孩子一样做,并且做类似的事情pip3 install pyserial。但目前尚不清楚我如何达到目标。就这一点。对virtualenv不感兴趣(除非必须如此)。

OS X (Mavericks) has Python 2.7 stock installed. But I do all my own personal Python stuff with 3.3. I just flushed my 3.3.2 install and installed the new 3.3.3. So I need to install pyserial again. I can do it the way I’ve done it before, which is:

  1. Download pyserial from pypi
  2. untar pyserial.tgz
  3. cd pyserial
  4. python3 setup.py install

But I’d like to do like the cool kids do, and just do something like pip3 install pyserial. But it’s not clear how I get to that point. And just that point. Not interested (unless I have to be) in virtualenv yet.


回答 0

更新:Python3.4不再需要此功能。它会在库存安装中安装pip3。

我最终在python邮件列表上发布了相同的问题,并得到以下答案:

# download and install setuptools
curl -O https://bootstrap.pypa.io/ez_setup.py
python3 ez_setup.py
# download and install pip
curl -O https://bootstrap.pypa.io/get-pip.py
python3 get-pip.py

完美解决了我的问题。在为我自己添加以下内容之后:

cd /usr/local/bin
ln -s ../../../Library/Frameworks/Python.framework/Versions/3.3/bin/pip pip

为了能够直接运行pip,我能够:

# use pip to install
pip install pyserial

要么:

# Don't want it?
pip uninstall pyserial

UPDATE: This is no longer necessary with Python3.4. It installs pip3 as part of the stock install.

I ended up posting this same question on the python mailing list, and got the following answer:

# download and install setuptools
curl -O https://bootstrap.pypa.io/ez_setup.py
python3 ez_setup.py
# download and install pip
curl -O https://bootstrap.pypa.io/get-pip.py
python3 get-pip.py

Which solved my question perfectly. After adding the following for my own:

cd /usr/local/bin
ln -s ../../../Library/Frameworks/Python.framework/Versions/3.3/bin/pip pip

So that I could run pip directly, I was able to:

# use pip to install
pip install pyserial

or:

# Don't want it?
pip uninstall pyserial

回答 1

我必须自己经历这个过程,并选择一种从长远来看更好的方法。

我安装了自制软件

ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

然后:

brew doctor

最后一步为您提供一些必须解决的警告和错误。其中之一将是下载并安装Mac OS X命令行工具

然后:

brew install python3

这给了我,python3并且走pip3了我的路。

pieter$ which pip3 python3
/usr/local/bin/pip3
/usr/local/bin/python3

I had to go through this process myself and chose a different way that I think is better in the long run.

I installed homebrew

ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

then:

brew doctor

The last step gives you some warnings and errors that you have to resolve. One of those will be to download and install the Mac OS X command-line tools.

then:

brew install python3

This gave me python3 and pip3 in my path.

pieter$ which pip3 python3
/usr/local/bin/pip3
/usr/local/bin/python3

回答 2

在Mac上安装Python3

1. brew install python3
2. curl https://bootstrap.pypa.io/get-pip.py | python3
3. python3

使用pip3安装模块

1. pip3 install ipython
2. python3 -m IPython

:)

Install Python3 on mac

1. brew install python3
2. curl https://bootstrap.pypa.io/get-pip.py | python3
3. python3

Use pip3 to install modules

1. pip3 install ipython
2. python3 -m IPython

:)


回答 3

另外:当您使用python3安装请求时,命令为:

pip3 install requests

pip install requests

Plus: when you install requests with python3, the command is:

pip3 install requests

not

pip install requests

回答 4

  1. brew install python3
  2. 在您的外壳配置文件中创建别名

    • 例如。alias pip3="python3 -m pip"在我的.zshrc

➜〜pip3-版本

来自/usr/local/lib/python3.6/site-packages(python 3.6)的pip 9.0.1

  1. brew install python3
  2. create alias in your shell profile

    • eg. alias pip3="python3 -m pip" in my .zshrc

➜ ~ pip3 –version

pip 9.0.1 from /usr/local/lib/python3.6/site-packages (python 3.6)


回答 5

这是我的简单解决方案:

如果您的系统中同时安装了python2和python3,则默认情况下pip升级将指向python2。因此,我们必须指定python(python3)的版本并使用以下命令:

python3 -m pip install --upgrade pip

此命令将卸载以前安装的pip并安装新版本-升级pip。

这将节省内存并使系统混乱。

图像-在MacOS上如何在Python3中升级pip

Here is my simple solution:

If you have python2 and python3 both installed in your system, the pip upgrade will point to python2 by default. Hence, we must specify the version of python(python3) and use the below command:

python3 -m pip install --upgrade pip

This command will uninstall the previously installed pip and install the new version- upgrading your pip.

This will save memory and declutter your system.

Image – How the upgrading of pip in Python3 works on MacOS


回答 6

要使用Python EasyInstall(我想您要使用它)非常简单!

sudo easy_install pip

因此,然后使用pip安装Pyserial,您可以执行以下操作:

pip install pyserial

To use Python EasyInstall (which is what I think you’re wanting to use), is super easy!

sudo easy_install pip

so then with pip to install Pyserial you would do:

pip install pyserial

回答 7

另外,值得一提的是Max OSX / macOS用户可以使用 Homebrew安装pip3。

$> brew update
$> brew install python3
$> pip3 --version
pip 9.0.1 from /usr/local/lib/python3.6/site-packages (python 3.6)

Also, it’s worth to mention that Max OSX/macOS users can just use Homebrew to install pip3.

$> brew update
$> brew install python3
$> pip3 --version
pip 9.0.1 from /usr/local/lib/python3.6/site-packages (python 3.6)

回答 8

Mac OS X Mojave python代表的2.7版本,Python和python3为版本3.同样是Pythonpippip3。所以,要升级pippython 3做到这一点:

~$ sudo pip3 install --upgrade pip

On Mac OS X Mojave python stands for python of version 2.7 and python3 for python of version 3. The same is pip and pip3. So, to upgrade pip for python 3 do this:

~$ sudo pip3 install --upgrade pip

回答 9

在MacOS 10.12上

下载点数:pip asget-pip.py

下载python3:python3

  1. 安装python3
  2. 打开终端: python3 get-pip.py
  3. pip3 可用

On MacOS 10.12

download pip: pip as get-pip.py

download python3: python3

  1. install python3
  2. open terminal: python3 get-pip.py
  3. pip3 is available

回答 10

pip 使用brew通过python2自动安装:

  1. brew install python3
  2. pip3 --version

pip is installed automatically with python2 using brew:

  1. brew install python3
  2. pip3 --version

回答 11

如果您的Mac上未安装pip,则只需在终端上运行以下命令即可。

sudo easy_install pip

在此处下载python 3: python3

完成这两个步骤后,请确保运行以下命令以验证是否已成功安装它们。

python3 --version
pip3 --version

simply run following on terminal if you don’t have pip installed on your mac.

sudo easy_install pip

download python 3 here: python3

once you’re done with these 2 steps, make sure to run the following to verify whether you’ve installed them successfully.

python3 --version
pip3 --version

回答 12

对于全新的Mac,您需要执行以下步骤:-

  1. 确保已安装 Xcode
  2. sudo easy_install pip
  3. /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
  4. brew doctor
  5. brew doctor
  6. brew install python3

完成后,只需python3在终端上键入,就会看到安装了python 3。

For a fresh new Mac, you need to follow below steps:-

  1. Make sure you have installed Xcode
  2. sudo easy_install pip
  3. /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
  4. brew doctor
  5. brew doctor
  6. brew install python3

And you are done, just type python3 on terminal and you will see python 3 installed.


回答 13

我在python3和pip3中遇到了同样的问题。决策:使用链接和其他东西解决所有冲突

brew doctor

之后

brew reinstall python3

I had the same problem with python3 and pip3. Decision: solving all conflicts with links and other stuff when do

brew doctor

After that

brew reinstall python3

在RHEL上安装Python 3

问题:在RHEL上安装Python 3

我正在尝试使用以下步骤在RHEL上安装python3:

yum search python3

哪个回来了 No matches found for: python3

其次是:

yum search python

搜索结果均未包含python3。接下来我应该尝试什么?

I’m trying to install python3 on RHEL using the following steps:

yum search python3

Which returned No matches found for: python3

Followed by:

yum search python

None of the search results contained python3. What should I try next?


回答 0

手动安装很容易:

  1. 下载(Python.org上可能有较新的版本):

    $ wget https://www.python.org/ftp/python/3.4.3/Python-3.4.3.tar.xz
  2. 解压缩

    $ tar xf Python-3.* 
    $ cd Python-3.*
  3. 准备编译

    $ ./configure
  4. 建立

    $ make
  5. 安装

    $ make install

    或者,如果您不想覆盖python可执行文件(更安全,至少在某些发行版中yum需要python为2.x,例如RHEL6)-您可以python3.*使用并发实例安装到系统默认值altinstall

    $ make altinstall

现在,如果要使用备用安装目录,则可以传递--prefixconfigure命令。

示例:要在/ opt / local中“安装” Python,只需添加--prefix=/opt/local

在后make install步:为了使用新的Python安装,它可能是,你还是要在[前缀] / bin加入到$PATH和[前缀] / lib下的$LD_LIBRARY_PATH(根据的--prefix你通过)

It is easy to install it manually:

  1. Download (there may be newer releases on Python.org):

    $ wget https://www.python.org/ftp/python/3.4.3/Python-3.4.3.tar.xz
    
  2. Unzip

    $ tar xf Python-3.* 
    $ cd Python-3.*
    
  3. Prepare compilation

    $ ./configure
    
  4. Build

    $ make
    
  5. Install

    $ make install
    

    OR if you don’t want to overwrite the python executable (safer, at least on some distros yum needs python to be 2.x, such as for RHEL6) – you can install python3.* as a concurrent instance to the system default with an altinstall:

    $ make altinstall
    

Now if you want an alternative installation directory, you can pass --prefix to the configurecommand.

Example: for ‘installing’ Python in /opt/local, just add --prefix=/opt/local.

After the make install step: In order to use your new Python installation, it could be, that you still have to add the [prefix]/bin to the $PATH and [prefix]/lib to the $LD_LIBRARY_PATH (depending of the --prefix you passed)


回答 1

从RPM安装通常更好,因为:

  • 您可以安装和卸载(正确)python3。
  • 安装时间的方式更快。如果您在具有多个VM的云环境中工作,则不能在每个VM上编译python3。

解决方案1:Red Hat和EPEL存储库

红帽通过EPEL存储库添加了:

  • 适用于CentOS 6的Python 3.4
  • 适用于CentOS 7的Python 3.6

[EPEL]如何在CentOS 6上安装Python 3.4

sudo yum install -y epel-release
sudo yum install -y python34

# Install pip3
sudo yum install -y python34-setuptools  # install easy_install-3.4
sudo easy_install-3.4 pip

您可以使用以下命令创建您的virtualenvpyvenv

pyvenv /tmp/foo

[EPEL]如何在CentOS 7上安装Python 3.6

与CentOS7一起pip3.6提供:)

sudo yum install -y epel-release
sudo yum install -y python36 python36-pip

您可以使用以下命令创建您的virtualenvpyvenv

python3.6 -m venv /tmp/foo

如果使用pyvenv脚本,则会收到警告:

$ pyvenv-3.6 /tmp/foo
WARNING: the pyenv script is deprecated in favour of `python3.6 -m venv`

解决方案2:IUS社区存储库

IUS社区提供了一些 有关RHEL和CentOS的最新软件包。后面的人来自Rackspace,所以我认为他们值得信赖…

https://ius.io/

在此处为您检查正确的仓库:

https://ius.io/setup

[IUS]如何在CentOS 6上安装Python 3.6

sudo yum install -y https://repo.ius.io/ius-release-el6.rpm
sudo yum install -y python36u python36u-pip

您可以使用以下命令创建您的virtualenvpyvenv

python3.6 -m venv /tmp/foo

[IUS]如何在CentOS 7上安装Python 3.6

sudo yum install -y https://repo.ius.io/ius-release-el7.rpm
sudo yum install -y python36u python36u-pip

您可以使用以下命令创建您的virtualenvpyvenv

python3.6 -m venv /tmp/foo

Installing from RPM is generally better, because:

  • you can install and uninstall (properly) python3.
  • the installation time is way faster. If you work in a cloud environment with multiple VMs, compiling python3 on each VMs is not acceptable.

Solution 1: Red Hat & EPEL repositories

Red Hat has added through the EPEL repository:

  • Python 3.4 for CentOS 6
  • Python 3.6 for CentOS 7

[EPEL] How to install Python 3.4 on CentOS 6

sudo yum install -y epel-release
sudo yum install -y python34

# Install pip3
sudo yum install -y python34-setuptools  # install easy_install-3.4
sudo easy_install-3.4 pip

You can create your virtualenv using pyvenv:

pyvenv /tmp/foo

[EPEL] How to install Python 3.6 on CentOS 7

With CentOS7, pip3.6 is provided as a package :)

sudo yum install -y epel-release
sudo yum install -y python36 python36-pip

You can create your virtualenv using pyvenv:

python3.6 -m venv /tmp/foo

If you use the pyvenv script, you’ll get a WARNING:

$ pyvenv-3.6 /tmp/foo
WARNING: the pyenv script is deprecated in favour of `python3.6 -m venv`

Solution 2: IUS Community repositories

The IUS Community provides some up-to-date packages for RHEL & CentOS. The guys behind are from Rackspace, so I think that they are quite trustworthy…

https://ius.io/

Check the right repo for you here:

https://ius.io/setup

[IUS] How to install Python 3.6 on CentOS 6

sudo yum install -y https://repo.ius.io/ius-release-el6.rpm
sudo yum install -y python36u python36u-pip

You can create your virtualenv using pyvenv:

python3.6 -m venv /tmp/foo

[IUS] How to install Python 3.6 on CentOS 7

sudo yum install -y https://repo.ius.io/ius-release-el7.rpm
sudo yum install -y python36u python36u-pip

You can create your virtualenv using pyvenv:

python3.6 -m venv /tmp/foo

回答 2

除了gecco的答案外,我还将步骤3更改为:

./configure

至:

./configure --prefix=/opt/python3

然后,在安装后,您还可以:

# ln -s /opt/python3/bin/python3 /usr/bin/python3

这是为了确保安装不会与yum安装的python冲突。

请参阅我在Internet上找到的说明:

http://www.hosting.com/support/linux/installing-python-3-on-centosredhat-5x-from-source

In addition to gecco’s answer I would change step 3 from:

./configure

to:

./configure --prefix=/opt/python3

Then after installation you could also:

# ln -s /opt/python3/bin/python3 /usr/bin/python3

It is to ensure that installation will not conflict with python installed with yum.

See explanation I have found on Internet:

http://www.hosting.com/support/linux/installing-python-3-on-centosredhat-5x-from-source


回答 3

与Python 2.7和3.3一起,Red Hat Software Collections现在包括Python 3.4-均可在RHEL 6和7上运行。

RHSCL 2.0文档位于https://access.redhat.com/documentation/zh-CN/Red_Hat_Software_Collections/

加上developerblog.redhat.com上的许多文章。

编辑

请按照以下说明在RHEL 6/7或CentOS 6/7上安装Python 3.4:

# 1. Install the Software Collections tools:
yum install scl-utils

# 2. Download a package with repository for your system.
#  (See the Yum Repositories on external link. For RHEL/CentOS 6:)
wget https://www.softwarecollections.org/en/scls/rhscl/rh-python34/epel-6-x86_64/download/rhscl-rh-python34-epel-6-x86_64.noarch.rpm
#  or for RHEL/CentOS 7
wget https://www.softwarecollections.org/en/scls/rhscl/rh-python34/epel-7-x86_64/download/rhscl-rh-python34-epel-7-x86_64.noarch.rpm

# 3. Install the repo package (on RHEL you will need to enable optional channel first):
yum install rhscl-rh-python34-*.noarch.rpm

# 4. Install the collection:
yum install rh-python34

# 5. Start using software collections:
scl enable rh-python34 bash

Along with Python 2.7 and 3.3, Red Hat Software Collections now includes Python 3.4 – all work on both RHEL 6 and 7.

RHSCL 2.0 docs are at https://access.redhat.com/documentation/en-US/Red_Hat_Software_Collections/

Plus lot of articles at developerblog.redhat.com.

edit

Follow these instructions to install Python 3.4 on RHEL 6/7 or CentOS 6/7:

# 1. Install the Software Collections tools:
yum install scl-utils

# 2. Download a package with repository for your system.
#  (See the Yum Repositories on external link. For RHEL/CentOS 6:)
wget https://www.softwarecollections.org/en/scls/rhscl/rh-python34/epel-6-x86_64/download/rhscl-rh-python34-epel-6-x86_64.noarch.rpm
#  or for RHEL/CentOS 7
wget https://www.softwarecollections.org/en/scls/rhscl/rh-python34/epel-7-x86_64/download/rhscl-rh-python34-epel-7-x86_64.noarch.rpm

# 3. Install the repo package (on RHEL you will need to enable optional channel first):
yum install rhscl-rh-python34-*.noarch.rpm

# 4. Install the collection:
yum install rh-python34

# 5. Start using software collections:
scl enable rh-python34 bash

回答 4

使用SCL存储库。

sudo sh -c 'wget -qO- http://people.redhat.com/bkabrda/scl_python33.repo >> /etc/yum.repos.d/scl.repo'
sudo yum install python33
scl enable python27

(每当您要使用python27而不是系统默认值时,都必须运行此最后一个命令。)

Use the SCL repos.

sudo sh -c 'wget -qO- http://people.redhat.com/bkabrda/scl_python33.repo >> /etc/yum.repos.d/scl.repo'
sudo yum install python33
scl enable python27

(This last command will have to be run each time you want to use python27 rather than the system default.)


回答 5

Python3最近作为Python34被添加到EPEL7中。

当前(正在进行)正在努力制定有关如何在EPEL7中打包Python3的打包准则。

参见https://bugzilla.redhat.com/show_bug.cgi?id=1219411
https://lists.fedoraproject.org/pipermail/python-devel/2015-July/000721.html

Python3 was recently added to EPEL7 as Python34.

There is ongoing (currently) effort to make packaging guidelines about how to package things for Python3 in EPEL7.

See https://bugzilla.redhat.com/show_bug.cgi?id=1219411
and https://lists.fedoraproject.org/pipermail/python-devel/2015-July/000721.html


回答 6

您可以从此处下载RHEL6 / CentOS6的源RPM和二进制RPM。

这是从最新的Fedora开发源rpm到RHEL6 / CentOS6的反向移植

You can download a source RPMs and binary RPMs for RHEL6 / CentOS6 from here

This is a backport from the newest Fedora development source rpm to RHEL6 / CentOS6


回答 7

我看到的所有答案都是要求从代码中编译python3或安装二进制RPM软件包。这是启用EPEL(企业Linux的额外软件包)然后使用yum安装python的另一个答案。RHEL 7.5(Maipo)的步骤

yum install wget y
wget https://dl.fedoraproject.org/pub/epel/7/x86_64/Packages/e/epel-release-7-11.noarch.rpm
rpm ivh epel-*.rpm
yum install python36

另请参阅链接

I see all the answers as either asking to compile python3 from code or installing the binary RPM package. Here is another answer to enable EPEL (Extra Packages for Enterprise Linux) and then install python using yum. Steps for RHEL 7.5 (Maipo)

yum install wget –y
wget https://dl.fedoraproject.org/pub/epel/7/x86_64/Packages/e/epel-release-7-XX.noarch.rpm # Verify actual RPM name by browsing dir over browser
rpm –ivh epel-*.rpm
yum install python36

Also see link


回答 8

我在使用python 2.7时遇到了同样的问题。请按照以下步骤成功升级到3.6。您也可以尝试以下一种

  1. 升级版本为2.x之前查看

    python --version
    Python 2.7.5
  2. 使用以下命令将python升级到3.x版本-

    百胜安装python3x

    用所需的版本号替换x

    即用于安装python 3.6执行

    yum install python36
  3. 之后,如果您想将此Python设置为默认版本,则在bashrc文件中添加

    vi〜/ .bashrc

    alias python='python3.6'
  4. 执行bash命令以应用设置

    bash 
  5. 现在您可以看到以下版本

    python --version
    Python 3.6.3

I was having the same issue using the python 2.7. Follow the below steps to upgrade successfully to 3.6. You can also try this one-

  1. See before upgrading version is 2.x

    python --version
    Python 2.7.5
    
  2. Use below command to upgrade your python to 3.x version-

    yum install python3x

    replace x with the version number you want.

    i.e. for installing python 3.6 execute

    yum install python36
    
  3. After that if you want to set this python for your default version then in bashrc file add

    vi ~/.bashrc

    alias python='python3.6'
    
  4. execute bash command to apply the settings

    bash 
    
  5. Now you can see the version below

    python --version
    Python 3.6.3
    

回答 9

通过Software Collections使用Python 3.5的三个步骤:

sudo yum install centos-release-scl
sudo yum install rh-python35
scl enable rh-python35 bash

请注意,最后一个命令不需要sudo。现在我们可以看到python 3是当前shell的默认值:

python --version
Python 3.5.1

如果您希望将Python 2作为当前shell的默认设置,则只需跳过最后一个命令。

现在,假设您的Python 3脚本给您一个类似的错误/usr/bin/env: python3: No such file or directory。这是因为安装通常是通过不寻常的路径完成的:

/opt/rh/rh-python35/root/bin/python3

以上通常是符号链接。如果要在启动时python3自动$PATH为所有用户添加到,则一种添加方法是添加以下文件:

sudo vim /etc/profile.d/rh-python35.sh

会有这样的东西:

#!/bin/bash

PATH=$PATH:/opt/rh/rh-python35/root/bin/

现在,重新启动后,如果我们这样做

python3 --version

它应该工作。一个exceptions是自动生成的用户,例如没有外壳的Jenkins服务器中的“ jenkins”。在这种情况下,手动添加路径到$PATH脚本将是一种方法。

最后,如果您正在使用sudo pip3安装软件包,但是它告诉您找不到pip3,则可能是您在/ etc / sudoers中有一个secure_path。检查应确认这一点。要在运行命令时临时使用标准PATH,可以执行以下操作:sudo visudo

sudo env "PATH=$PATH" pip3 --version

有关更多详细信息,请参见此问题。

注意:Software Collections有一个更新的Python 3.6,但是由于我在尝试安装Pycurl时遇到了很多麻烦,因此目前不推荐使用。对于Python 3.5来说,这不是问题,因为我刚sudo yum install sclo-python35-python-pycurl做完了就可以了。

Three steps using Python 3.5 by Software Collections:

sudo yum install centos-release-scl
sudo yum install rh-python35
scl enable rh-python35 bash

Note that sudo is not needed for the last command. Now we can see that python 3 is the default for the current shell:

python --version
Python 3.5.1

Simply skip the last command if you’d rather have Python 2 as the default for the current shell.

Now let’s say that your Python 3 scripts give you an error like /usr/bin/env: python3: No such file or directory. That’s because the installation is usually done to an unusual path:

/opt/rh/rh-python35/root/bin/python3

The above would normally be a symlink. If you want python3 to be automatically added to the $PATH for all users on startup, one way to do this is adding a file like:

sudo vim /etc/profile.d/rh-python35.sh

Which would have something like:

#!/bin/bash

PATH=$PATH:/opt/rh/rh-python35/root/bin/

And now after a reboot, if we do

python3 --version

It should just work. One exception would be an auto-generated user like “jenkins” in a Jenkins server which doesn’t have a shell. In that case, manually adding the path to $PATH in scripts would be one way to go.

Finally, if you’re using sudo pip3 to install packages, but it tells you that pip3 cannot be found, it could be that you have a secure_path in /etc/sudoers. Checking with sudo visudo should confirm that. To temporarily use the standard PATH when running commands you can do, for example:

sudo env "PATH=$PATH" pip3 --version

See this question for more details.

NOTE: There is a newer Python 3.6 by Software Collections, but I wouldn’t recommend it at this time, because I had major headaches trying to install Pycurl. For Python 3.5 that isn’t an issue because I just did sudo yum install sclo-python35-python-pycurl which worked out of the box.


回答 10

如果您使用的是RHEL,并且希望使用Red Hat支持的Python,请使用Red Hat软件集合(RHSCL)。Red Hat不支持EPEL和IUS软件包。上面的许多答案也指向CentOS软件集合。虽然可以安装它们,但它们不是Red Hat支持的RHEL软件包。

另外,票数最高的答案也提供了不好的建议-在RHEL上,您不想更改/usr/bin/python/usr/bin/python2因为您可能会破坏yum和使用其他RHEL管理工具。看一下/bin/yum,它是一个以开头的Python脚本#!/usr/bin/python。如果您从源代码编译Python,请不要make install以root用户身份进行操作。那将覆盖/usr/bin/python。如果中断yum,则很难恢复系统。

欲了解更多信息,请参阅如何安装Python 3,画中画,VENV,virtualenv中,并pipenv在RHELdevelopers.redhat.com。它涵盖了从RHSCL安装和使用Python 3,使用Python虚拟环境以及使用软件集合以及在RHEL上使用Python的许多技巧。

简而言之,要通过Red Hat Software Collections安装Python 3.6:

$ su -
# subscription-manager repos --enable rhel-7-server-optional-rpms \
   --enable rhel-server-rhscl-7-rpms
# yum -y install @development
# yum -y install rh-python36

# yum -y install rh-python36-numpy \
   rh-python36-scipy \ 
   rh-python36-python-tools \
   rh-python36-python-six

要使用软件集合,您必须启用它:

scl enable rh-python36 bash

但是,如果要永久启用Python 3,可以将以下内容添加到〜/ .bashrc中,然后注销并重新登录。现在,Python 3永久存在。

# Add RHSCL Python 3 to my login environment
source scl_source enable rh-python36

注意:执行此操作后,python现在输入即可提供Python 3.6而不是Python 2.7。

有关更多信息,请参见上面的文章。

If you are on RHEL and want a Red Hat supported Python, use Red Hat Software collections (RHSCL). The EPEL and IUS packages are not supported by Red Hat. Also many of the answers above point to the CentOS software collections. While you can install those, they aren’t the Red Hat supported packages for RHEL.

Also, the top voted answer gives bad advice – On RHEL you do not want to change /usr/bin/python, /usr/bin/python2 because you will likely break yum and other RHEL admin tools. Take a look at /bin/yum, it is a Python script that starts with #!/usr/bin/python. If you compile Python from source, do not do a make install as root. That will overwrite /usr/bin/python. If you break yum it can be difficult to restore your system.

For more info, see How to install Python 3, pip, venv, virtualenv, and pipenv on RHEL on developers.redhat.com. It covers installing and using Python 3 from RHSCL, using Python Virtual Environments, and a number of tips for working with software collections and working with Python on RHEL.

In a nutshell, to install Python 3.6 via Red Hat Software Collections:

$ su -
# subscription-manager repos --enable rhel-7-server-optional-rpms \
   --enable rhel-server-rhscl-7-rpms
# yum -y install @development
# yum -y install rh-python36

# yum -y install rh-python36-numpy \
   rh-python36-scipy \ 
   rh-python36-python-tools \
   rh-python36-python-six

To use a software collection you have to enable it:

scl enable rh-python36 bash

However if you want Python 3 permanently enabled, you can add the following to your ~/.bashrc and then log out and back in again. Now Python 3 is permanently in your path.

# Add RHSCL Python 3 to my login environment
source scl_source enable rh-python36

Note: once you do that, typing python now gives you Python 3.6 instead of Python 2.7.

See the above article for all of this and a lot more detail.


回答 11

如果您需要正式的RHEL软件包,可以使用RHSCL(红帽软件集合)

更多细节:

您必须有权访问Red Hat Customer Portal才能阅读全文。

If you want official RHEL packages you can use RHSCL (Red Hat Software Collections)

More details:

You have to have access to Red Hat Customer Portal to read full articles.


回答 12

这是我按照以下步骤安装Python3的步骤:

yum install wget
wget https://www.python.org/ftp/python/3.6.0/Python-3.6.0.tar.xz  
sudo tar xvf Python-3.*   
cd Python-3.* 
sudo ./configure --prefix=/opt/python3    
sudo make   
sudo make install   
sudo ln -s /opt/python3/bin/python3 /usr/bin/python3

$ /usr/bin/python3    
Python 3.6.0

Here are the steps i followed to install Python3:

yum install wget
wget https://www.python.org/ftp/python/3.6.0/Python-3.6.0.tar.xz  
sudo tar xvf Python-3.*   
cd Python-3.* 
sudo ./configure --prefix=/opt/python3    
sudo make   
sudo make install   
sudo ln -s /opt/python3/bin/python3 /usr/bin/python3

$ /usr/bin/python3    
Python 3.6.0

回答 13

yum install python34.x86_64如果您已epel-release安装,则可以正常工作,此答案说明了如何操作,并且我确认它可以正常工作RHEL 7.3

$ cat /etc/*-release
NAME="Red Hat Enterprise Linux Server"
VERSION="7.3 (Maipo)

$ type python3
python3 is hashed (/usr/bin/python3)

yum install python34.x86_64 works if you have epel-release installed, which this answer explains how to, and I confirmed it worked on RHEL 7.3

$ cat /etc/*-release
NAME="Red Hat Enterprise Linux Server"
VERSION="7.3 (Maipo)

$ type python3
python3 is hashed (/usr/bin/python3)

回答 14

对于Amazon Linux上的RHEL,必须使用python3:

须藤百胜安装python34-devel

For RHEL on Amazon Linux, using python3 I had to do :

sudo yum install python34-devel


回答 15

当SCL不可用时,完全工作36(基于Joys输入)

yum install wget y
wget https://dl.fedoraproject.org/pub/epel/7/x86_64/Packages/e/epel-release-7-11.noarch.rpm
rpm ivh epel-*.rpm
yum install python36

sudo yum install python34-setuptools
sudo mkdir /usr/local/lib/python3.6
sudo mkdir /usr/local/lib/python3.6/site-packages

sudo easy_install-3.6 pip

最后激活环境…

pyvenv-3.6 py3
source py3/bin/activate

然后python3

Full working 36 when SCL is not available (based on Joys input)

yum install wget –y
wget https://dl.fedoraproject.org/pub/epel/7/x86_64/Packages/e/epel-release-7-11.noarch.rpm
rpm –ivh epel-*.rpm
yum install python36

sudo yum install python34-setuptools
sudo mkdir /usr/local/lib/python3.6
sudo mkdir /usr/local/lib/python3.6/site-packages

sudo easy_install-3.6 pip

Finally activate the environment…

pyvenv-3.6 py3
source py3/bin/activate

Then python3


回答 16

您可以安装miniconda(https://conda.io/miniconda.html)。这不仅仅是python 3.7,但安装非常简单明了。

curl https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O
sudo yum install bzip2
bash Miniconda3-latest-Linux-x86_64.sh

您必须接受许可协议,并在交互模式下选择一些选项(接受默认值)。我相信它也可以以某种方式静默安装。

You can install miniconda (https://conda.io/miniconda.html). That’s a bit more than just python 3.7 but the installation is very straightforward and simple.

curl https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O
sudo yum install bzip2
bash Miniconda3-latest-Linux-x86_64.sh

You’ll have to accept the license agreement and choose some options in interactive mode (accept the defaults). I believe it can be also installed silently somehow.


回答 17

对于使用AWS EC2 RHEL 7.5的用户,(使用sudo)启用必需的存储库

yum-config-manager --enable rhui-REGION-rhel-server-optional
yum-config-manager --enable rhui-REGION-rhel-server-rhscl

安装Python 3.6

yum install rh-python36

安装其他依赖项

yum install rh-python36-numpy  rh-python36-scipy  rh-python36-python-tools  rh-python36-python-six

For those working on AWS EC2 RHEL 7.5, (use sudo) enable required repos

yum-config-manager --enable rhui-REGION-rhel-server-optional
yum-config-manager --enable rhui-REGION-rhel-server-rhscl

Install Python 3.6

yum install rh-python36

Install other dependencies

yum install rh-python36-numpy  rh-python36-scipy  rh-python36-python-tools  rh-python36-python-six

类型提示指定类型的列表

问题:类型提示指定类型的列表

使用Python 3的功能注释,可以指定包含在同类列表(或其他集合)中的项的类型,以便在PyCharm和其他IDE中进行类型提示。

一个int列表的伪python代码示例:

def my_func(l:list<int>):
    pass

我知道有可能使用Docstring …

def my_func(l):
    """
    :type l: list[int]
    """
    pass

…但是我更喜欢注释样式。

Using Python 3’s function annotations, it is possible to specify the type of items contained within a homogeneous list (or other collection) for the purpose of type hinting in PyCharm and other IDEs?

A pseudo-python code example for a list of int:

def my_func(l:list<int>):
    pass

I know it’s possible using Docstring…

def my_func(l):
    """
    :type l: list[int]
    """
    pass

… but I prefer the annotation style if it’s possible.


回答 0

回答我自己的问题;TLDR的答案是“

更新2

在2015年9月,Python 3.5发行了对Type Hints的支持,并包含一个新的打字模块。这允许指定集合中包含的类型。截至2015年11月,JetBrains PyCharm 5.0完全支持Python 3.5包含类型提示,如下所示。

更新1

截至2015年5月,PEP0484(类型提示)已被正式接受。草案的实现也可以在github的ambv / typehinting下找到

原始答案

自2014年8月起,我已经确认无法使用Python 3类型注释在集合中指定类型(例如:字符串列表)。

诸如reStructuredText或Sphinx之类的格式化文档字符串的使用是可行的替代方法,并且受各种IDE支持。

看来,Guido还本着mypy的精神考虑了扩展类型注释的想法:http ://mail.python.org/pipermail/python-ideas/2014-August/028618.html

Answering my own question; the TLDR answer is No Yes.

Update 2

In September 2015, Python 3.5 was released with support for Type Hints and includes a new typing module. This allows for the specification of types contained within collections. As of November 2015, JetBrains PyCharm 5.0 fully supports Python 3.5 to include Type Hints as illustrated below.

Update 1

As of May 2015, PEP0484 (Type Hints) has been formally accepted. The draft implementation is also available at github under ambv/typehinting.

Original Answer

As of Aug 2014, I have confirmed that it is not possible to use Python 3 type annotations to specify types within collections (ex: a list of strings).

The use of formatted docstrings such as reStructuredText or Sphinx are viable alternatives and supported by various IDEs.

It also appears that Guido is mulling over the idea of extending type annotations in the spirit of mypy: http://mail.python.org/pipermail/python-ideas/2014-August/028618.html


回答 1

现在Python 3.5正式发布了,这里有Type Hints支持模块- typing以及相关的List通用容器 “类型”。

换句话说,现在您可以执行以下操作:

from typing import List

def my_func(l: List[int]):
    pass

Now that Python 3.5 is officially out, there is the Type Hints supporting module – typing and the relevant List “type” for the generic containers.

In other words, now you can do:

from typing import List

def my_func(l: List[int]):
    pass

回答 2

PEP 484起已添加类型注释

from . import Monitor
from typing import List, Set, Tuple, Dict


active_monitors = [] # type: List[Monitor]
# or
active_monitors: List[Monitor] = []

# bonus
active_monitors: Set[Monitor] = set()
monitor_pair: Tuple[Monitor, Monitor] = (Monitor(), Monitor())
monitor_dict: Dict[str, Monitor] = {'codename': Monitor()}

# nested
monitor_pair_list: List[Dict[str, Monitor]] = [{'codename': Monitor()}]

目前,这对于使用Python 3.6.4的PyCharm来说是有用的

Pycharm中的示例图片

Type comments have been added since PEP 484

from . import Monitor
from typing import List, Set, Tuple, Dict


active_monitors = [] # type: List[Monitor]
# or
active_monitors: List[Monitor] = []

# bonus
active_monitors: Set[Monitor] = set()
monitor_pair: Tuple[Monitor, Monitor] = (Monitor(), Monitor())
monitor_dict: Dict[str, Monitor] = {'codename': Monitor()}

# nested
monitor_pair_list: List[Dict[str, Monitor]] = [{'codename': Monitor()}]

This is currently working for me on PyCharm with Python 3.6.4

Example Picture in Pycharm


回答 3

在BDFL的支持下,现在几乎可以确定python(可能是3.5)将通过函数注释为类型提示提供标准化的语法。

https://www.python.org/dev/peps/pep-0484/

正如PEP中所引用的那样,有一个名为mypy的实验型类型检查器(有点像pylint,但对于类型而言)已经使用此标准,并且不需要任何新语法。

http://mypy-lang.org/

With support from the BDFL, it’s almost certain now that python (probably 3.5) will provide a standardized syntax for type hints via function annotations.

https://www.python.org/dev/peps/pep-0484/

As referenced in the PEP, there is an experimental type-checker (kind of like pylint, but for types) called mypy that already uses this standard, and doesn’t require any new syntax.

http://mypy-lang.org/


回答 4

从Python 3.9开始,内置类型在类型注释方面是通用的(请参阅PEP 585)。这允许直接指定元素的类型:

def my_func(l: list[int]):
    pass

各种工具可能早于Python 3.9支持此语法。如果在运行时未检查注释,则使用引号或语法有效__future__.annotations

# quoted
def my_func(l: 'list[int]'):
    pass
# postponed evaluation of annotation
from __future__ import annotations

def my_func(l: list[int]):
    pass

As of Python 3.9, builtin types are generic with respect to type annotations (see PEP 585). This allows to directly specify the type of elements:

def my_func(l: list[int]):
    pass

Various tools may support this syntax earlier than Python 3.9. When annotations are not inspected at runtime, the syntax is valid using quoting or __future__.annotations.

# quoted
def my_func(l: 'list[int]'):
    pass
# postponed evaluation of annotation
from __future__ import annotations

def my_func(l: list[int]):
    pass

__getattr__在模块上

问题:__getattr__在模块上

如何实现等效的 __getattr__在类,模块上于a?

当调用模块的静态定义的属性中不存在的函数时,我希望在该模块中创建一个类的实例,并使用与该模块上的属性查找失败相同的名称调用该方法。

class A(object):
    def salutation(self, accusative):
        print "hello", accusative

# note this function is intentionally on the module, and not the class above
def __getattr__(mod, name):
    return getattr(A(), name)

if __name__ == "__main__":
    # i hope here to have my __getattr__ function above invoked, since
    # salutation does not exist in the current namespace
    salutation("world")

这使:

matt@stanley:~/Desktop$ python getattrmod.py 
Traceback (most recent call last):
  File "getattrmod.py", line 9, in <module>
    salutation("world")
NameError: name 'salutation' is not defined

How can implement the equivalent of a __getattr__ on a class, on a module?

Example

When calling a function that does not exist in a module’s statically defined attributes, I wish to create an instance of a class in that module, and invoke the method on it with the same name as failed in the attribute lookup on the module.

class A(object):
    def salutation(self, accusative):
        print "hello", accusative

# note this function is intentionally on the module, and not the class above
def __getattr__(mod, name):
    return getattr(A(), name)

if __name__ == "__main__":
    # i hope here to have my __getattr__ function above invoked, since
    # salutation does not exist in the current namespace
    salutation("world")

Which gives:

matt@stanley:~/Desktop$ python getattrmod.py 
Traceback (most recent call last):
  File "getattrmod.py", line 9, in <module>
    salutation("world")
NameError: name 'salutation' is not defined

回答 0

不久前,Guido宣布对新型类的所有特殊方法查找都绕过__getattr__and__getattribute__。Dunder方法曾经工作的模块-你可以,例如,使用一个模块作为一个上下文管理器简单地通过定义__enter____exit__,这些技巧之前爆发

最近,一些历史功能已经卷土重来,其中的一个模块已被卷土重来,__getattr__因此,sys.modules不再需要现有的hack(在导入时将一个模块替换为一个类)。

在Python 3.7+中,您仅使用一种显而易见的方法。要自定义模块上的属性访问,请__getattr__在模块级别定义一个函数,该函数应接受一个参数(属性名称),然后返回计算值或引发一个AttributeError

# my_module.py

def __getattr__(name: str) -> Any:
    ...

这也将允许钩子插入“ from”导入,即,您可以为语句(例如)返回动态生成的对象 from my_module import whatever

与此相关的是,您还可以与模块getattr一起__dir__在模块级别定义一个函数以响应dir(my_module)。有关详细信息,请参见PEP 562

A while ago, Guido declared that all special method lookups on new-style classes bypass __getattr__ and __getattribute__. Dunder methods had previously worked on modules – you could, for example, use a module as a context manager simply by defining __enter__ and __exit__, before those tricks broke.

Recently some historical features have made a comeback, the module __getattr__ among them, and so the existing hack (a module replacing itself with a class in sys.modules at import time) should be no longer necessary.

In Python 3.7+, you just use the one obvious way. To customize attribute access on a module, define a __getattr__ function at the module level which should accept one argument (name of attribute), and return the computed value or raise an AttributeError:

# my_module.py

def __getattr__(name: str) -> Any:
    ...

This will also allow hooks into “from” imports, i.e. you can return dynamically generated objects for statements such as from my_module import whatever.

On a related note, along with the module getattr you may also define a __dir__ function at module level to respond to dir(my_module). See PEP 562 for details.


回答 1

您在这里遇到两个基本问题:

  1. __xxx__ 方法只在类上查找
  2. TypeError: can't set attributes of built-in/extension type 'module'

(1)表示任何解决方案还必须跟踪正在检查的模块,否则每个模块将具有实例替换行为;(2)表示(1)甚至是不可能的……至少不是直接的。

幸运的是,sys.modules对那里发生的事情并不挑剔,因此可以使用包装器,但是只能用于模块访问(即import somemodule; somemodule.salutation('world'),对于相同模块的访问,您几乎必须从替换类中提取方法并将其添加到globals()eiher中。类上的自定义方法(我喜欢使用.export())或具有泛型函数(例如已经列出的答案)要记住的一件事:如果包装器每次都创建一个新实例,而全局解决方案不是,最终,您的行为会有所不同。哦,您不能同时使用两者-一种是另一种。


更新资料

Guido van Rossum出发:

实际上,偶尔会使用并推荐一种hack:一个模块可以用所需的功能定义一个类,然后最后,用该类的实例(如果需要,可以用该类)替换sys.modules中的自身。 ,但通常用处不大)。例如:

# module foo.py

import sys

class Foo:
    def funct1(self, <args>): <code>
    def funct2(self, <args>): <code>

sys.modules[__name__] = Foo()

之所以可行,是因为导入机制正在积极地启用此hack,并且在加载的最后一步是将实际模块从sys.modules中拉出。(这绝非偶然。黑客是在很久以前就提出的,我们认为我们很喜欢在进口机器中提供支持。)

因此,完成所需操作的既定方法是在模块中创建一个类,并且作为模块的最后一步,sys.modules[__name__]用您的类的实例替换-现在您可以根据需要使用__getattr__/ __setattr__/ __getattribute__进行操作。


注意1:如果您使用此功能,则在进行sys.modules分配时,模块中的所有其他内容(例如全局变量,其他函数等)都会丢失-因此请确保所需的所有内容都在替换类之内。

注意2:要支持from module import *您必须__all__在类中进行定义;例如:

class Foo:
    def funct1(self, <args>): <code>
    def funct2(self, <args>): <code>
    __all__ = list(set(vars().keys()) - {'__module__', '__qualname__'})

根据您的Python版本,可能会省略其他名称__all__set()如果不需要Python 2兼容性,可以省略。

There are two basic problems you are running into here:

  1. __xxx__ methods are only looked up on the class
  2. TypeError: can't set attributes of built-in/extension type 'module'

(1) means any solution would have to also keep track of which module was being examined, otherwise every module would then have the instance-substitution behavior; and (2) means that (1) isn’t even possible… at least not directly.

Fortunately, sys.modules is not picky about what goes there so a wrapper will work, but only for module access (i.e. import somemodule; somemodule.salutation('world'); for same-module access you pretty much have to yank the methods from the substitution class and add them to globals() eiher with a custom method on the class (I like using .export()) or with a generic function (such as those already listed as answers). One thing to keep in mind: if the wrapper is creating a new instance each time, and the globals solution is not, you end up with subtly different behavior. Oh, and you don’t get to use both at the same time — it’s one or the other.


Update

From Guido van Rossum:

There is actually a hack that is occasionally used and recommended: a module can define a class with the desired functionality, and then at the end, replace itself in sys.modules with an instance of that class (or with the class, if you insist, but that’s generally less useful). E.g.:

# module foo.py

import sys

class Foo:
    def funct1(self, <args>): <code>
    def funct2(self, <args>): <code>

sys.modules[__name__] = Foo()

This works because the import machinery is actively enabling this hack, and as its final step pulls the actual module out of sys.modules, after loading it. (This is no accident. The hack was proposed long ago and we decided we liked enough to support it in the import machinery.)

So the established way to accomplish what you want is to create a single class in your module, and as the last act of the module replace sys.modules[__name__] with an instance of your class — and now you can play with __getattr__/__setattr__/__getattribute__ as needed.


Note 1: If you use this functionality then anything else in the module, such as globals, other functions, etc., will be lost when the sys.modules assignment is made — so make sure everything needed is inside the replacement class.

Note 2: To support from module import * you must have __all__ defined in the class; for example:

class Foo:
    def funct1(self, <args>): <code>
    def funct2(self, <args>): <code>
    __all__ = list(set(vars().keys()) - {'__module__', '__qualname__'})

Depending on your Python version, there may be other names to omit from __all__. The set() can be omitted if Python 2 compatibility is not needed.


回答 2

这是一个技巧,但是您可以使用一个类包装模块:

class Wrapper(object):
  def __init__(self, wrapped):
    self.wrapped = wrapped
  def __getattr__(self, name):
    # Perform custom logic here
    try:
      return getattr(self.wrapped, name)
    except AttributeError:
      return 'default' # Some sensible default

sys.modules[__name__] = Wrapper(sys.modules[__name__])

This is a hack, but you can wrap the module with a class:

class Wrapper(object):
  def __init__(self, wrapped):
    self.wrapped = wrapped
  def __getattr__(self, name):
    # Perform custom logic here
    try:
      return getattr(self.wrapped, name)
    except AttributeError:
      return 'default' # Some sensible default

sys.modules[__name__] = Wrapper(sys.modules[__name__])

回答 3

我们通常不那样做。

我们要做的就是这个。

class A(object):
....

# The implicit global instance
a= A()

def salutation( *arg, **kw ):
    a.salutation( *arg, **kw )

为什么?使隐式全局实例可见。

例如,查看random模块,该模块创建一个隐式全局实例,以稍微简化您需要“简单”随机数生成器的用例。

We don’t usually do it that way.

What we do is this.

class A(object):
....

# The implicit global instance
a= A()

def salutation( *arg, **kw ):
    a.salutation( *arg, **kw )

Why? So that the implicit global instance is visible.

For examples, look at the random module, which creates an implicit global instance to slightly simplify the use cases where you want a “simple” random number generator.


回答 4

与@HåvardS提出的类似,在我需要在模块上实现一些魔术的情况下(例如__getattr__),我将定义一个继承types.ModuleType并放入其中的新类sys.modules(可能替换自定义模块ModuleType定义了定义)。

请参阅Werkzeug的主__init__.py文件,以实现此功能的强大功能。

Similar to what @Håvard S proposed, in a case where I needed to implement some magic on a module (like __getattr__), I would define a new class that inherits from types.ModuleType and put that in sys.modules (probably replacing the module where my custom ModuleType was defined).

See the main __init__.py file of Werkzeug for a fairly robust implementation of this.


回答 5

这有点黑,但是…

import types

class A(object):
    def salutation(self, accusative):
        print "hello", accusative

    def farewell(self, greeting, accusative):
         print greeting, accusative

def AddGlobalAttribute(classname, methodname):
    print "Adding " + classname + "." + methodname + "()"
    def genericFunction(*args):
        return globals()[classname]().__getattribute__(methodname)(*args)
    globals()[methodname] = genericFunction

# set up the global namespace

x = 0   # X and Y are here to add them implicitly to globals, so
y = 0   # globals does not change as we iterate over it.

toAdd = []

def isCallableMethod(classname, methodname):
    someclass = globals()[classname]()
    something = someclass.__getattribute__(methodname)
    return callable(something)


for x in globals():
    print "Looking at", x
    if isinstance(globals()[x], (types.ClassType, type)):
        print "Found Class:", x
        for y in dir(globals()[x]):
            if y.find("__") == -1: # hack to ignore default methods
                if isCallableMethod(x,y):
                    if y not in globals(): # don't override existing global names
                        toAdd.append((x,y))


for x in toAdd:
    AddGlobalAttribute(*x)


if __name__ == "__main__":
    salutation("world")
    farewell("goodbye", "world")

通过遍历全局命名空间中的所有对象来工作。如果该项目是一个类,则在类属性上进行迭代。如果该属性是可调用的,则将其作为函数添加到全局命名空间中。

它忽略所有包含“ __”的属性。

我不会在生产代码中使用它,但是它应该可以帮助您入门。

This is hackish, but…

import types

class A(object):
    def salutation(self, accusative):
        print "hello", accusative

    def farewell(self, greeting, accusative):
         print greeting, accusative

def AddGlobalAttribute(classname, methodname):
    print "Adding " + classname + "." + methodname + "()"
    def genericFunction(*args):
        return globals()[classname]().__getattribute__(methodname)(*args)
    globals()[methodname] = genericFunction

# set up the global namespace

x = 0   # X and Y are here to add them implicitly to globals, so
y = 0   # globals does not change as we iterate over it.

toAdd = []

def isCallableMethod(classname, methodname):
    someclass = globals()[classname]()
    something = someclass.__getattribute__(methodname)
    return callable(something)


for x in globals():
    print "Looking at", x
    if isinstance(globals()[x], (types.ClassType, type)):
        print "Found Class:", x
        for y in dir(globals()[x]):
            if y.find("__") == -1: # hack to ignore default methods
                if isCallableMethod(x,y):
                    if y not in globals(): # don't override existing global names
                        toAdd.append((x,y))


for x in toAdd:
    AddGlobalAttribute(*x)


if __name__ == "__main__":
    salutation("world")
    farewell("goodbye", "world")

This works by iterating over the all the objects in the global namespace. If the item is a class, it iterates over the class attributes. If the attribute is callable it adds it to the global namespace as a function.

It ignore all attributes which contain “__”.

I wouldn’t use this in production code, but it should get you started.


回答 6

这是我自己的不起眼的贡献-@HåvardS的高度评价的答案略有修饰,但略显一点(因此@ S.Lott可以接受,尽管可能对OP不够好):

import sys

class A(object):
    def salutation(self, accusative):
        print "hello", accusative

class Wrapper(object):
    def __init__(self, wrapped):
        self.wrapped = wrapped

    def __getattr__(self, name):
        try:
            return getattr(self.wrapped, name)
        except AttributeError:
            return getattr(A(), name)

_globals = sys.modules[__name__] = Wrapper(sys.modules[__name__])

if __name__ == "__main__":
    _globals.salutation("world")

Here’s my own humble contribution — a slight embellishment of @Håvard S’s highly rated answer, but a bit more explicit (so it might be acceptable to @S.Lott, even though probably not good enough for the OP):

import sys

class A(object):
    def salutation(self, accusative):
        print "hello", accusative

class Wrapper(object):
    def __init__(self, wrapped):
        self.wrapped = wrapped

    def __getattr__(self, name):
        try:
            return getattr(self.wrapped, name)
        except AttributeError:
            return getattr(A(), name)

_globals = sys.modules[__name__] = Wrapper(sys.modules[__name__])

if __name__ == "__main__":
    _globals.salutation("world")

回答 7

创建包含您的类的模块文件。导入模块。getattr在刚导入的模块上运行。您可以使用以下方式进行动态导入__import__ sys.modules中的模块。

这是您的模块some_module.py

class Foo(object):
    pass

class Bar(object):
    pass

在另一个模块中:

import some_module

Foo = getattr(some_module, 'Foo')

动态地执行此操作:

import sys

__import__('some_module')
mod = sys.modules['some_module']
Foo = getattr(mod, 'Foo')

Create your module file that has your classes. Import the module. Run getattr on the module you just imported. You can do a dynamic import using __import__ and pull the module from sys.modules.

Here’s your module some_module.py:

class Foo(object):
    pass

class Bar(object):
    pass

And in another module:

import some_module

Foo = getattr(some_module, 'Foo')

Doing this dynamically:

import sys

__import__('some_module')
mod = sys.modules['some_module']
Foo = getattr(mod, 'Foo')

如何在Python中切换值

问题:如何在Python中切换值

0和之间切换的最有效方法是什么1

What is the most efficient way to toggle between 0 and 1?


回答 0

使用NOT的解决方案

如果值是布尔值,最快的方法是使用not运算符:

>>> x = True
>>> x = not x        # toggle
>>> x
False
>>> x = not x        # toggle
>>> x
True
>>> x = not x        # toggle
>>> x
False

用减法求解

如果值是数字,则从总数中减去是切换值的一种简单快捷的方法:

>>> A = 5
>>> B = 3
>>> total = A + B
>>> x = A
>>> x = total - x    # toggle
>>> x
3
>>> x = total - x    # toggle
>>> x
5
>>> x = total - x    # toggle
>>> x
3

使用XOR的解决方案

如果该值在01之间切换,则可以使用按位异或

>>> x = 1
>>> x ^= 1
>>> x
0
>>> x ^= 1
>>> x
1

该技术可以推广到任意一对整数。异或一步被替换为预异常数:

>>> A = 205
>>> B = -117
>>> t = A ^ B        # precomputed toggle constant
>>> x = A
>>> x ^= t           # toggle
>>> x
-117
>>> x ^= t           # toggle
>>> x
205
>>> x ^= t           # toggle
>>> x
-117

(此想法由Nick Coghlan提交,后来由@zxxc推广。)

使用字典的解决方案

如果值是可哈希的,则可以使用字典:

>>> A = 'xyz'
>>> B = 'pdq'
>>> d = {A:B, B:A}
>>> x = A
>>> x = d[x]         # toggle
>>> x
'pdq'
>>> x = d[x]         # toggle
>>> x
'xyz'
>>> x = d[x]         # toggle
>>> x
'pdq'

使用条件表达式的解决方案

最慢的方法是使用条件表达式

>>> A = [1,2,3]
>>> B = [4,5,6]
>>> x = A
>>> x = B if x == A else A
>>> x
[4, 5, 6]
>>> x = B if x == A else A
>>> x
[1, 2, 3]
>>> x = B if x == A else A
>>> x
[4, 5, 6]

使用itertools的解决方案

如果您有两个以上的值,则itertools.cycle()函数提供了一种通用的快速方法来在连续的值之间进行切换:

>>> import itertools
>>> toggle = itertools.cycle(['red', 'green', 'blue']).next
>>> toggle()
'red'
>>> toggle()
'green'
>>> toggle()
'blue'
>>> toggle()
'red'
>>> toggle()
'green'
>>> toggle()
'blue'

请注意,在Python 3中,next()方法已更改为__next__(),因此第一行现在将写为toggle = itertools.cycle(['red', 'green', 'blue']).__next__

Solution using NOT

If the values are boolean, the fastest approach is to use the not operator:

>>> x = True
>>> x = not x        # toggle
>>> x
False
>>> x = not x        # toggle
>>> x
True
>>> x = not x        # toggle
>>> x
False

Solution using subtraction

If the values are numerical, then subtraction from the total is a simple and fast way to toggle values:

>>> A = 5
>>> B = 3
>>> total = A + B
>>> x = A
>>> x = total - x    # toggle
>>> x
3
>>> x = total - x    # toggle
>>> x
5
>>> x = total - x    # toggle
>>> x
3

Solution using XOR

If the value toggles between 0 and 1, you can use a bitwise exclusive-or:

>>> x = 1
>>> x ^= 1
>>> x
0
>>> x ^= 1
>>> x
1

The technique generalizes to any pair of integers. The xor-by-one step is replaced with a xor-by-precomputed-constant:

>>> A = 205
>>> B = -117
>>> t = A ^ B        # precomputed toggle constant
>>> x = A
>>> x ^= t           # toggle
>>> x
-117
>>> x ^= t           # toggle
>>> x
205
>>> x ^= t           # toggle
>>> x
-117

(This idea was submitted by Nick Coghlan and later generalized by @zxxc.)

Solution using a dictionary

If the values are hashable, you can use a dictionary:

>>> A = 'xyz'
>>> B = 'pdq'
>>> d = {A:B, B:A}
>>> x = A
>>> x = d[x]         # toggle
>>> x
'pdq'
>>> x = d[x]         # toggle
>>> x
'xyz'
>>> x = d[x]         # toggle
>>> x
'pdq'

Solution using a conditional expression

The slowest way is to use a conditional expression:

>>> A = [1,2,3]
>>> B = [4,5,6]
>>> x = A
>>> x = B if x == A else A
>>> x
[4, 5, 6]
>>> x = B if x == A else A
>>> x
[1, 2, 3]
>>> x = B if x == A else A
>>> x
[4, 5, 6]

Solution using itertools

If you have more than two values, the itertools.cycle() function provides a generic fast way to toggle between successive values:

>>> import itertools
>>> toggle = itertools.cycle(['red', 'green', 'blue']).next
>>> toggle()
'red'
>>> toggle()
'green'
>>> toggle()
'blue'
>>> toggle()
'red'
>>> toggle()
'green'
>>> toggle()
'blue'

Note that in Python 3 the next() method was changed to __next__(), so the first line would be now written as toggle = itertools.cycle(['red', 'green', 'blue']).__next__


回答 1

我一直使用:

p^=True

如果p是布尔值,则在true和false之间切换。

I always use:

p^=True

If p is a boolean, this switches between true and false.


回答 2

这是另一种不直观的方法。优点是您可以循环多个值,而不仅仅是两个[0,1]

对于两个值(切换)

>>> x=[1,0]
>>> toggle=x[toggle]

对于多个值(例如4)

>>> x=[1,2,3,0]
>>> toggle=x[toggle]

我没想到这个解决方案也几乎是最快的

>>> stmt1="""
toggle=0
for i in xrange(0,100):
    toggle = 1 if toggle == 0 else 0
"""
>>> stmt2="""
x=[1,0]
toggle=0
for i in xrange(0,100):
    toggle=x[toggle]
"""
>>> t1=timeit.Timer(stmt=stmt1)
>>> t2=timeit.Timer(stmt=stmt2)
>>> print "%.2f usec/pass" % (1000000 * t1.timeit(number=100000)/100000)
7.07 usec/pass
>>> print "%.2f usec/pass" % (1000000 * t2.timeit(number=100000)/100000)
6.19 usec/pass
stmt3="""
toggle = False
for i in xrange(0,100):
    toggle = (not toggle) & 1
"""
>>> t3=timeit.Timer(stmt=stmt3)
>>> print "%.2f usec/pass" % (1000000 * t3.timeit(number=100000)/100000)
9.84 usec/pass
>>> stmt4="""
x=0
for i in xrange(0,100):
    x=x-1
"""
>>> t4=timeit.Timer(stmt=stmt4)
>>> print "%.2f usec/pass" % (1000000 * t4.timeit(number=100000)/100000)
6.32 usec/pass

Here is another non intuitive way. The beauty is you can cycle over multiple values and not just two [0,1]

For Two values (toggling)

>>> x=[1,0]
>>> toggle=x[toggle]

For Multiple Values (say 4)

>>> x=[1,2,3,0]
>>> toggle=x[toggle]

I didn’t expect this solution to be almost the fastest too

>>> stmt1="""
toggle=0
for i in xrange(0,100):
    toggle = 1 if toggle == 0 else 0
"""
>>> stmt2="""
x=[1,0]
toggle=0
for i in xrange(0,100):
    toggle=x[toggle]
"""
>>> t1=timeit.Timer(stmt=stmt1)
>>> t2=timeit.Timer(stmt=stmt2)
>>> print "%.2f usec/pass" % (1000000 * t1.timeit(number=100000)/100000)
7.07 usec/pass
>>> print "%.2f usec/pass" % (1000000 * t2.timeit(number=100000)/100000)
6.19 usec/pass
stmt3="""
toggle = False
for i in xrange(0,100):
    toggle = (not toggle) & 1
"""
>>> t3=timeit.Timer(stmt=stmt3)
>>> print "%.2f usec/pass" % (1000000 * t3.timeit(number=100000)/100000)
9.84 usec/pass
>>> stmt4="""
x=0
for i in xrange(0,100):
    x=x-1
"""
>>> t4=timeit.Timer(stmt=stmt4)
>>> print "%.2f usec/pass" % (1000000 * t4.timeit(number=100000)/100000)
6.32 usec/pass

回答 3

not运营商否定你的变量(将其转换成一个布尔值,如果它是不是已经一个)。您可以或许1,并0与互换TrueFalse,所以就否定它:

toggle = not toggle

但是,如果您使用两个任意值,请使用inline if

toggle = 'a' if toggle == 'b' else 'b'

The not operator negates your variable (converting it into a boolean if it isn’t already one). You can probably use 1 and 0 interchangeably with True and False, so just negate it:

toggle = not toggle

But if you are using two arbitrary values, use an inline if:

toggle = 'a' if toggle == 'b' else 'b'

回答 4

在1到0之间执行此操作

1-x 

x可以取1或0

Just between 1 and 0, do this

1-x 

x can take 1 or 0


回答 5

三角法,仅仅是因为sincos函数很酷。

>>> import math
>>> def generator01():
...     n=0
...     while True:
...         yield abs( int( math.cos( n * 0.5 * math.pi  ) ) )
...         n+=1
... 
>>> g=generator01() 
>>> g.next()
1
>>> g.next()
0
>>> g.next()
1
>>> g.next()
0

Trigonometric approach, just because sin and cos functions are cool.

>>> import math
>>> def generator01():
...     n=0
...     while True:
...         yield abs( int( math.cos( n * 0.5 * math.pi  ) ) )
...         n+=1
... 
>>> g=generator01() 
>>> g.next()
1
>>> g.next()
0
>>> g.next()
1
>>> g.next()
0

回答 6

令人惊讶的是,没有人提到好的旧除法模2:

In : x = (x + 1)  % 2 ; x
Out: 1

In : x = (x + 1)  % 2 ; x
Out: 0

In : x = (x + 1)  % 2 ; x
Out: 1

In : x = (x + 1)  % 2 ; x
Out: 0

请注意,它等效于x = x - 1,但是取模技术的优点是组的大小或间隔的长度可以大于2个元素,从而为循环提供了类似于轮询交错的方案。

现在只需要2,切换就可以短一些(使用按位运算符):

x = x ^ 1

Surprisingly nobody mention good old division modulo 2:

In : x = (x + 1)  % 2 ; x
Out: 1

In : x = (x + 1)  % 2 ; x
Out: 0

In : x = (x + 1)  % 2 ; x
Out: 1

In : x = (x + 1)  % 2 ; x
Out: 0

Note that it is equivalent to x = x - 1, but the advantage of modulo technique is that the size of the group or length of the interval can be bigger then just 2 elements, thus giving you a similar to round-robin interleaving scheme to loop over.

Now just for 2, toggling can be a bit shorter (using bit-wise operator):

x = x ^ 1

回答 7

一种切换方式是使用多重分配

>>> a = 5
>>> b = 3

>>> t = a, b = b, a
>>> t[0]
3

>>> t = a, b = b, a
>>> t[0]
5

使用itertools:

In [12]: foo = itertools.cycle([1, 2, 3])

In [13]: next(foo)
Out[13]: 1

In [14]: next(foo)
Out[14]: 2

In [15]: next(foo)
Out[15]: 3

In [16]: next(foo)
Out[16]: 1

In [17]: next(foo)
Out[17]: 2

one way to toggle is by using Multiple assignment

>>> a = 5
>>> b = 3

>>> t = a, b = b, a
>>> t[0]
3

>>> t = a, b = b, a
>>> t[0]
5

Using itertools:

In [12]: foo = itertools.cycle([1, 2, 3])

In [13]: next(foo)
Out[13]: 1

In [14]: next(foo)
Out[14]: 2

In [15]: next(foo)
Out[15]: 3

In [16]: next(foo)
Out[16]: 1

In [17]: next(foo)
Out[17]: 2

回答 8

在1和0之间切换的最简单方法是从1减去。

def toggle(value):
    return 1 - value

The easiest way to toggle between 1 and 0 is to subtract from 1.

def toggle(value):
    return 1 - value

回答 9

使用异常处理程序

>>> def toogle(x):
...     try:
...         return x/x-x/x
...     except  ZeroDivisionError:
...         return 1
... 
>>> x=0
>>> x=toogle(x)
>>> x
1
>>> x=toogle(x)
>>> x
0
>>> x=toogle(x)
>>> x
1
>>> x=toogle(x)
>>> x
0

好吧,我是最糟糕的:

import math
import sys

d={1:0,0:1}
l=[1,0]

def exception_approach(x):
    try:
        return x/x-x/x
    except  ZeroDivisionError:
        return 1

def cosinus_approach(x):
    return abs( int( math.cos( x * 0.5 * math.pi  ) ) )

def module_approach(x):
    return  (x + 1)  % 2

def subs_approach(x):
    return  x - 1

def if_approach(x):
    return 0 if x == 1 else 1

def list_approach(x):
    global l
    return l[x]

def dict_approach(x):
    global d
    return d[x]

def xor_approach(x):
    return x^1

def not_approach(x):
    b=bool(x)
    p=not b
    return int(p)

funcs=[ exception_approach, cosinus_approach, dict_approach, module_approach, subs_approach, if_approach, list_approach, xor_approach, not_approach ]

f=funcs[int(sys.argv[1])]
print "\n\n\n", f.func_name
x=0
for _ in range(0,100000000):
    x=f(x)

Using exception handler

>>> def toogle(x):
...     try:
...         return x/x-x/x
...     except  ZeroDivisionError:
...         return 1
... 
>>> x=0
>>> x=toogle(x)
>>> x
1
>>> x=toogle(x)
>>> x
0
>>> x=toogle(x)
>>> x
1
>>> x=toogle(x)
>>> x
0

Ok, I’m the worst:

import math
import sys

d={1:0,0:1}
l=[1,0]

def exception_approach(x):
    try:
        return x/x-x/x
    except  ZeroDivisionError:
        return 1

def cosinus_approach(x):
    return abs( int( math.cos( x * 0.5 * math.pi  ) ) )

def module_approach(x):
    return  (x + 1)  % 2

def subs_approach(x):
    return  x - 1

def if_approach(x):
    return 0 if x == 1 else 1

def list_approach(x):
    global l
    return l[x]

def dict_approach(x):
    global d
    return d[x]

def xor_approach(x):
    return x^1

def not_approach(x):
    b=bool(x)
    p=not b
    return int(p)

funcs=[ exception_approach, cosinus_approach, dict_approach, module_approach, subs_approach, if_approach, list_approach, xor_approach, not_approach ]

f=funcs[int(sys.argv[1])]
print "\n\n\n", f.func_name
x=0
for _ in range(0,100000000):
    x=f(x)

回答 10

怎么样一个假想的切换,存储不仅是当前切换,但与之相关的其他几个值?

toggle = complex.conjugate

在左侧存储任何+或-值,在右侧存储任何无符号的值:

>>> x = 2 - 3j
>>> toggle(x)
(2+3j)

零也起作用:

>>> y = -2 - 0j
>>> toggle(y)
(-2+0j)

轻松检索当前的切换值(TrueFalse表示+和-),LHS(实数)值或RHS(虚数)值:

>>> import math
>>> curr = lambda i: math.atan2(i.imag, -abs(i.imag)) > 0
>>> lhs = lambda i: i.real
>>> rhs = lambda i: abs(i.imag)
>>> x = toggle(x)
>>> curr(x)
True
>>> lhs(x)
2.0
>>> rhs(x)
3.0

轻松交换LHS和RHS(但请注意,两个值的符号一定不重要):

>>> swap = lambda i: i/-1j
>>> swap(2+0j)
2j
>>> swap(3+2j)
(2+3j)

轻松交换LHS和RHS 并同时切换:

>>> swaggle = lambda i: i/1j
>>> swaggle(2+0j)
-2j
>>> swaggle(3+2j)
(2-3j)

防止错误:

>>> toggle(1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: descriptor 'conjugate' requires a 'complex' object but received a 'int'

对LHS和RHS进行更改:

>>> x += 1+2j
>>> x
(3+5j)

…但是要小心操作RHS:

>>> z = 1-1j
>>> z += 2j
>>> z
(1+1j) # whoops! toggled it!

How about an imaginary toggle that stores not only the current toggle, but a couple other values associated with it?

toggle = complex.conjugate

Store any + or – value on the left, and any unsigned value on the right:

>>> x = 2 - 3j
>>> toggle(x)
(2+3j)

Zero works, too:

>>> y = -2 - 0j
>>> toggle(y)
(-2+0j)

Easily retrieve the current toggle value (True and False represent + and -), LHS (real) value, or RHS (imaginary) value:

>>> import math
>>> curr = lambda i: math.atan2(i.imag, -abs(i.imag)) > 0
>>> lhs = lambda i: i.real
>>> rhs = lambda i: abs(i.imag)
>>> x = toggle(x)
>>> curr(x)
True
>>> lhs(x)
2.0
>>> rhs(x)
3.0

Easily swap LHS and RHS (but note that the sign of the both values must not be important):

>>> swap = lambda i: i/-1j
>>> swap(2+0j)
2j
>>> swap(3+2j)
(2+3j)

Easily swap LHS and RHS and also toggle at the same time:

>>> swaggle = lambda i: i/1j
>>> swaggle(2+0j)
-2j
>>> swaggle(3+2j)
(2-3j)

Guards against errors:

>>> toggle(1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: descriptor 'conjugate' requires a 'complex' object but received a 'int'

Perform changes to LHS and RHS:

>>> x += 1+2j
>>> x
(3+5j)

…but be careful manipulating the RHS:

>>> z = 1-1j
>>> z += 2j
>>> z
(1+1j) # whoops! toggled it!

回答 11

变量a和b可以是任意两个值,例如0和1,或者117和711,或“ heads”和“ tails”。不使用数学运算,每次需要切换时仅快速交换值。

a = True   
b = False   

a,b = b,a   # a is now False
a,b = b,a   # a is now True

Variables a and b can be ANY two values, like 0 and 1, or 117 and 711, or “heads” and “tails”. No math is used, just a quick swap of the values each time a toggle is desired.

a = True   
b = False   

a,b = b,a   # a is now False
a,b = b,a   # a is now True

回答 12

我使用abs函数,在循环中非常有用

x = 1
for y in range(0, 3):
    x = abs(x - 1)

x将为0。

I use abs function, very useful on loops

x = 1
for y in range(0, 3):
    x = abs(x - 1)

x will be 0.


回答 13

让我们做一些框架黑客。按名称切换变量。注意:这可能不适用于每个Python运行时。

假设您有一个变量“ x”

>>> import inspect
>>> def toggle(var_name):
>>>     frame = inspect.currentframe().f_back
>>>     vars = frame.f_locals
>>>     vars[var_name] = 0 if vars[var_name] == 1 else 1

>>> x = 0
>>> toggle('x')
>>> x
1
>>> toggle('x')
>>> x
0

Let’s do some frame hacking. Toggle a variable by name. Note: This may not work with every Python runtime.

Say you have a variable “x”

>>> import inspect
>>> def toggle(var_name):
>>>     frame = inspect.currentframe().f_back
>>>     vars = frame.f_locals
>>>     vars[var_name] = 0 if vars[var_name] == 1 else 1

>>> x = 0
>>> toggle('x')
>>> x
1
>>> toggle('x')
>>> x
0

回答 14

如果要处理整数变量,则可以递增1并将其限制为0和1(mod)

X = 0  # or X = 1
X = (X + 1)%2

If you are dealing with an integer variable, you can increment 1 and limit your set to 0 and 1 (mod)

X = 0  # or X = 1
X = (X + 1)%2

回答 15

可以通过内联乘法在-1和+1之间切换。用于以“ Leibniz”方式(或类似方式)计算pi:

sign = 1
result = 0
for i in range(100000):
    result += 1 / (2*i + 1) * sign
    sign *= -1
print("pi (estimate): ", result*4)

Switching between -1 and +1 can be obtained by inline multiplication; used for calculation of pi the ‘Leibniz’ way (or similar):

sign = 1
result = 0
for i in range(100000):
    result += 1 / (2*i + 1) * sign
    sign *= -1
print("pi (estimate): ", result*4)

回答 16

您可以使用的indexlist秒。

def toggleValues(values, currentValue):
    return values[(values.index(currentValue) + 1) % len(values)]

> toggleValues( [0,1] , 1 )
> 0
> toggleValues( ["one","two","three"] , "one" )
> "two"
> toggleValues( ["one","two","three"] , "three")
> "one"

优点:无需其他库,自我解释代码并可以处理任意数据类型。

缺点:不重复保存。 toggleValues(["one","two","duped", "three", "duped", "four"], "duped") 永远会回来"three"

You can make use of the index of lists.

def toggleValues(values, currentValue):
    return values[(values.index(currentValue) + 1) % len(values)]

> toggleValues( [0,1] , 1 )
> 0
> toggleValues( ["one","two","three"] , "one" )
> "two"
> toggleValues( ["one","two","three"] , "three")
> "one"

Pros: No additional libraries, self.explanatory code and working with arbitrary data types.

Cons: not duplicate-save. toggleValues(["one","two","duped", "three", "duped", "four"], "duped") will always return "three"