标签归档:python-3.x

2套并集不包含所有项目

问题:2套并集不包含所有项目

在下面的联合中更改两个集合的顺序时,为什么会得到不同的结果?

set1 = {1, 2, 3}
set2 = {True, False}

print(set1 | set2)
# {False, 1, 2, 3}

print(set2 | set1)
#{False, True, 2, 3}

How come when I change the order of the two sets in the unions below, I get different results?

set1 = {1, 2, 3}
set2 = {True, False}

print(set1 | set2)
# {False, 1, 2, 3}

print(set2 | set1)
#{False, True, 2, 3}

回答 0

为什么union()不包含所有项目

1True是等价的,被认为是重复的。同样,0False也等效:

>>> 1 == True
True
>>> 0 == False
True

使用哪个等效值

当遇到多个等效值时,集合将保持第一个可见:

>>> {0, False}
{0}
>>> {False, 0}
{False}

使价值观与众不同的方法

为了使它们与众不同,只需将它们(value, type)成对存储:

>>> set1 = {(1, int), (2, int), (3, int)}
>>> set2 = {(True, bool), (False, bool)}
>>> set1 | set2
{(3, <class 'int'>), (1, <class 'int'>), (2, <class 'int'>),
 (True, <class 'bool'>), (False, <class 'bool'>)}
>>> set1 & set2
set()

区分值的另一种方法是将它们存储为字符串:

>>> set1 = {'1', '2', '3'}
>>> set2 = {'True', 'False'}
>>> set1 | set2
{'2', '3', 'False', 'True', '1'}
>>> set1 & set2
set()

希望这可以消除谜团并显示前进的方向:-)


从评论中救出:

这是为破坏十字型等价(即标准技术0.0 == 0True == 1以及Decimal(8.5) == 8.5)该技术是在Python 2.7的正则表达式模块用于力的unicode正则表达式被从其他等效的STR正则表达式清楚地高速缓存。是在Python也使用的技术类型参数为true时,对于functools.lru_cache()为3。

如果OP需要除默认等效关系以外的其他内容,则需要定义一些新关系。根据使用情况,可能是字符串不区分大小写,Unicode规范化,视觉外观(看起来不同的事物被认为是不同的),身份(没有两个不同的对象被认为是相等的),值/类型对或其他一些定义等价关系的函数。给定OP的特定示例,他/她似乎期望按类型区分或视觉区分。

Why the union() doesn’t contain all items

The 1 and True are equivalent and considered to be duplicates. Likewise the 0 and False are equivalent as well:

>>> 1 == True
True
>>> 0 == False
True

Which equivalent value is used

When multiple equivalent values are encountered, sets keep the first one seen:

>>> {0, False}
{0}
>>> {False, 0}
{False}

Ways to make the values be distinct

To get them to be treated as distinct, just store them in a (value, type) pair:

>>> set1 = {(1, int), (2, int), (3, int)}
>>> set2 = {(True, bool), (False, bool)}
>>> set1 | set2
{(3, <class 'int'>), (1, <class 'int'>), (2, <class 'int'>),
 (True, <class 'bool'>), (False, <class 'bool'>)}
>>> set1 & set2
set()

Another way to make the values distinct is to store them as strings:

>>> set1 = {'1', '2', '3'}
>>> set2 = {'True', 'False'}
>>> set1 | set2
{'2', '3', 'False', 'True', '1'}
>>> set1 & set2
set()

Hope this clears up the mystery and shows the way forward :-)


Rescued from the comments:

This is the standard technique for breaking cross-type equivalence (i.e. 0.0 == 0, True == 1, and Decimal(8.5) == 8.5). The technique is used in Python 2.7’s regular expression module to force unicode regexes to be cached distinctly from otherwise equivalent str regexes. The technique is also used in Python 3 for functools.lru_cache() when the typed parameter is true.

If the OP needs something other than the default equivalence relation, then some new relation needs to be defined. Depending the use case, that could be case-insensitivity for strings, normalization for unicode, visual appearance (things that look different are considered different), identity (no two distinct objects are considered equal), a value/type pair, or some other function that defines an equivalence relation. Given the OPs specific example, it would seem that he/she expected either distinction by type or visual distinction.


回答 1

在Python,False0被认为是等效的,True1。因为True1被视为相同的值,所以它们中的一个只能同时出现在集合中。哪一个取决于它们添加到集合中的顺序。在第一行中,set1将其用作第一集合,因此我们可以得到1结果集合。在第二组中,True在第一组中,因此True包含在结果中。

In Python, False and 0 are considered equivalent, as are True and 1. Because True and 1 are considered the same value, only one of them can be present in a set a the same time. Which one depends on the order they are added to the set in. In the first line, set1 is used as the first set, so we get 1 in the resulting set. In the second set, True is in the first set, so True is included in the result.


回答 2

如果您查看https://docs.python.org/3/library/stdtypes.html#boolean-values部分4.12.10。布尔值:

布尔值是两个常量对象False和True。它们用于表示真值(尽管其他值也可以视为假或真)。在数字上下文中(例如,用作算术运算符的参数时),它们的行为分别类似于整数0和1

If you look at https://docs.python.org/3/library/stdtypes.html#boolean-values section 4.12.10. Boolean Values:

Boolean values are the two constant objects False and True. They are used to represent truth values (although other values can also be considered false or true). In numeric contexts (for example when used as the argument to an arithmetic operator), they behave like the integers 0 and 1, respectively.


回答 3

为布尔定义了比较运算符(==!=),TrueFalse匹配1和0。

这就是为什么在集合联合中,当它检查是否True已经在新集合中时,会得到一个真实的答案:

>>> True in {1}
True
>>> 1 in {True}
True

The comparison operator (==, !=) is defined for boolean True and False to match 1 and 0.

That’s why, in the set union, when it checks whether True is in the new set already, it gets a truthy answer:

>>> True in {1}
True
>>> 1 in {True}
True

从Python迭代器获取最后一项的最干净方法

问题:从Python迭代器获取最后一项的最干净方法

从Python 2.6的迭代器中获取最后一项的最佳方法是什么?例如说

my_iter = iter(range(5))

什么是获得的最短码/干净的方式4my_iter

我可以做到这一点,但效率似乎并不高:

[x for x in my_iter][-1]

What’s the best way of getting the last item from an iterator in Python 2.6? For example, say

my_iter = iter(range(5))

What is the shortest-code / cleanest way of getting 4 from my_iter?

I could do this, but it doesn’t seem very efficient:

[x for x in my_iter][-1]

回答 0

item = defaultvalue
for item in my_iter:
    pass
item = defaultvalue
for item in my_iter:
    pass

回答 1

使用deque大小为1的。

from collections import deque

#aa is an interator
aa = iter('apple')

dd = deque(aa, maxlen=1)
last_element = dd.pop()

Use a deque of size 1.

from collections import deque

#aa is an interator
aa = iter('apple')

dd = deque(aa, maxlen=1)
last_element = dd.pop()

回答 2

如果您使用的是Python 3.x:

*_, last = iterator # for a better understanding check PEP 448
print(last)

如果您使用的是python 2.7:

last = next(iterator)
for last in iterator:
    continue
print last


边注:

通常情况下,上述解决方案介绍的是你需要正规的情况下什么,但如果你正在处理数据的数量较大,这是更有效地使用一个deque大小1(来源

from collections import deque

#aa is an interator
aa = iter('apple')

dd = deque(aa, maxlen=1)
last_element = dd.pop()

If you are using Python 3.x:

*_, last = iterator # for a better understanding check PEP 448
print(last)

if you are using python 2.7:

last = next(iterator)
for last in iterator:
    continue
print last


Side Note:

Usually, the solution presented above is the what you need for regular cases, but if you are dealing with a big amount of data, it’s more efficient to use a deque of size 1. (source)

from collections import deque

#aa is an interator
aa = iter('apple')

dd = deque(aa, maxlen=1)
last_element = dd.pop()

回答 3

__reversed__如果可用,可能值得使用

if hasattr(my_iter,'__reversed__'):
    last = next(reversed(my_iter))
else:
    for last in my_iter:
        pass

Probably worth using __reversed__ if it is available

if hasattr(my_iter,'__reversed__'):
    last = next(reversed(my_iter))
else:
    for last in my_iter:
        pass

回答 4

简单如:

max(enumerate(the_iter))[1]

As simple as:

max(enumerate(the_iter))[1]

回答 5

由于存在lambda,这不太可能比空的for循环快,但也许会给别人一个思路

reduce(lambda x,y:y,my_iter)

如果iter为空,则引发TypeError

This is unlikely to be faster than the empty for loop due to the lambda, but maybe it will give someone else an idea

reduce(lambda x,y:y,my_iter)

If the iter is empty, a TypeError is raised


回答 6

有这个

list( the_iter )[-1]

如果迭代的长度确实是史诗般的-如此之长以至于实现列表将耗尽内存-那么您确实需要重新考虑设计。

There’s this

list( the_iter )[-1]

If the length of the iteration is truly epic — so long that materializing the list will exhaust memory — then you really need to rethink the design.


回答 7

我会用 reversed,只是它只序列而不是迭代器,这似乎相当武断。

无论采用哪种方式,都必须遍历整个迭代器。以最高的效率,如果您不再需要迭代器,则可以废弃所有值:

for last in my_iter:
    pass
# last is now the last item

我认为这是次佳的解决方案。

I would use reversed, except that it only takes sequences instead of iterators, which seems rather arbitrary.

Any way you do it, you’ll have to run through the entire iterator. At maximum efficiency, if you don’t need the iterator ever again, you could just trash all the values:

for last in my_iter:
    pass
# last is now the last item

I think this is a sub-optimal solution, though.


回答 8

图尔茨库提供了一个很好的解决方案:

from toolz.itertoolz import last
last(values)

但是,仅在这种情况下,添加非核心依赖项可能并不值得。

The toolz library provides a nice solution:

from toolz.itertoolz import last
last(values)

But adding a non-core dependency might not be worth it for using it only in this case.


回答 9

参见以下代码以获取类似信息:

http://excamera.com/sphinx/article-islast.html

您可以使用它来拾取最后一个物品:

[(last, e) for (last, e) in islast(the_iter) if last]

See this code for something similar:

http://excamera.com/sphinx/article-islast.html

you might use it to pick up the last item with:

[(last, e) for (last, e) in islast(the_iter) if last]

回答 10

我只会用 next(reversed(myiter))

I would just use next(reversed(myiter))


回答 11

问题是关于获取迭代器的最后一个元素,但是如果您的迭代器是通过将条件应用于序列来创建的,则可以通过应用反向来查找反向序列的“第一个”,而只需查看所需的元素即可。与序列本身相反。

一个人为的例子

>>> seq = list(range(10))
>>> last_even = next(_ for _ in reversed(seq) if _ % 2 == 0)
>>> last_even
8

The question is about getting the last element of an iterator, but if your iterator is created by applying conditions to a sequence, then reversed can be used to find the “first” of a reversed sequence, only looking at the needed elements, by applying reverse to the sequence itself.

A contrived example,

>>> seq = list(range(10))
>>> last_even = next(_ for _ in reversed(seq) if _ % 2 == 0)
>>> last_even
8

回答 12

另外,对于无限迭代器,您可以使用:

from itertools import islice 
last = list(islice(iterator(), 1000))[-1] # where 1000 is number of samples 

我以为那会慢一点,deque但是它和循环方法一样快,而且实际上快得多(某种程度上)

Alternatively for infinite iterators you can use:

from itertools import islice 
last = list(islice(iterator(), 1000))[-1] # where 1000 is number of samples 

I thought it would be slower then deque but it’s as fast and it’s actually faster then for loop method ( somehow )


回答 13

这个问题是错误的,只能导致复杂而低效的答案。要获得迭代器,您当然要从可迭代的事物开始,这在大多数情况下将提供访问最后一个元素的更直接的方法。

从可迭代对象创建迭代器后,您就不得不遍历元素,因为这是可迭代对象唯一提供的内容。

因此,最有效,最清晰的方法不是首先创建迭代器,而是使用迭代器的本机访问方法。

The question is wrong and can only lead to an answer that is complicated and inefficient. To get an iterator, you of course start out from something that is iterable, which will in most cases offer a more direct way of accessing the last element.

Once you create an iterator from an iterable you are stuck in going through the elements, because that is the only thing an iterable provides.

So, the most efficient and clear way is not to create the iterator in the first place but to use the native access methods of the iterable.


点冻结与点列表

问题:点冻结与点列表

比较输出结果可发现差异:

user@user-VirtualBox:~$ pip list
feedparser (5.1.3)
pip (1.4.1)
setuptools (1.1.5)
wsgiref (0.1.2)
user@user-VirtualBox:~$ pip freeze
feedparser==5.1.3
wsgiref==0.1.2

Pip的文档状态

freeze                      Output installed packages in requirements format.
list                        List installed packages.

但是什么是“需求格式”?为什么pip list生成的清单比清单更全面pip freeze

A comparison of outputs reveals differences:

user@user-VirtualBox:~$ pip list
feedparser (5.1.3)
pip (1.4.1)
setuptools (1.1.5)
wsgiref (0.1.2)
user@user-VirtualBox:~$ pip freeze
feedparser==5.1.3
wsgiref==0.1.2

Pip’s documentation states

freeze                      Output installed packages in requirements format.
list                        List installed packages.

but what is “requirements format,” and why does pip list generate a more comprehensive list than pip freeze?


回答 0

使用时virtualenv,可以指定一个requirements.txt文件来安装所有依赖项。

典型用法:

$ pip install -r requirements.txt

软件包需要采用特定的格式pip才能理解,即

feedparser==5.1.3
wsgiref==0.1.2
django==1.4.2
...

那就是“要求格式”。

在这里,django==1.4.2意味着安装django版本1.4.2(即使最新版本是1.6.x)。如果您未指定==1.4.2,则会安装可用的最新版本。

您可以在“ Virtualenv和pip基础知识 ”以及官方的“ Requirements File Format ”文档中阅读更多内容。

When you are using a virtualenv, you can specify a requirements.txt file to install all the dependencies.

A typical usage:

$ pip install -r requirements.txt

The packages need to be in a specific format for pip to understand, which is

feedparser==5.1.3
wsgiref==0.1.2
django==1.4.2
...

That is the “requirements format”.

Here, django==1.4.2 implies install django version 1.4.2 (even though the latest is 1.6.x). If you do not specify ==1.4.2, the latest version available would be installed.

You can read more in “Virtualenv and pip Basics“, and the official “Requirements File Format” documentation.


回答 1

为了回答这个问题的第二部分,显示pip list但没有显示的两个软件包pip freezesetuptools(easy_install)和它们pip本身。

它看起来像pip freeze少了点列表软件包点子本身依赖。您可以使用该--all标志来显示那些软件包。

文档中

--all

不要在输出中跳过以下软件包:pip,setuptools,distribute,wheel

To answer the second part of this question, the two packages shown in pip list but not pip freeze are setuptools (which is easy_install) and pip itself.

It looks like pip freeze just doesn’t list packages that pip itself depends on. You may use the --all flag to show also those packages.

From the documentation:

--all

Do not skip these packages in the output: pip, setuptools, distribute, wheel


回答 2

主要区别在于可以将的输出pip freeze转储到requirements.txt文件中,并在以后用于重建“冻结”环境。

换句话说,您可以运行:pip freeze > frozen-requirements.txt在一台计算机上运行 ,然后再在另一台计算机上或干净的环境中运行: pip install -r frozen-requirements.txt 您将获得与安装原始环境时所安装的依赖项完全相同的相同环境生成了Frozen-requirements.txt。

The main difference is that the output of pip freeze can be dumped into a requirements.txt file and used later to re-construct the “frozen” environment.

In other words you can run: pip freeze > frozen-requirements.txt on one machine and then later on a different machine or on a clean environment you can do: pip install -r frozen-requirements.txt and you’ll get the an identical environment with the exact same dependencies installed as you had in the original environment where you generated the frozen-requirements.txt.


回答 3

查看pip文档,该文档将两者的功能描述为:

点列表

列出已安装的软件包,包括可编辑的软件包。

点冻结

以需求格式输出已安装的软件包。

因此有两个区别:

  1. 输出格式,freeze为我们提供了标准的需求格式,以后可以用来pip install -r安装需求。

  2. 输出内容,pip list包括pip freeze不包含的可编辑内容。

Look at the pip documentation, which describes the functionality of both as:

pip list

List installed packages, including editables.

pip freeze

Output installed packages in requirements format.

So there are two differences:

  1. Output format, freeze gives us the standard requirement format that may be used later with pip install -r to install requirements from.

  2. Output content, pip list include editables which pip freeze does not.


回答 4

pip list显示所有软件包。

pip freeze示出了包YOU经由安装pip(或pipenv如果使用该工具)在要求的格式命令。

在下面说明创建虚拟信封时已安装setuptoolspipwheelpipenv shell。这些软件包不是我使用pip以下软件安装的:

test1 % pipenv shell
Creating a virtualenv for this project
Pipfile: /Users/terrence/Development/Python/Projects/test1/Pipfile
Using /usr/local/Cellar/pipenv/2018.11.26_3/libexec/bin/python3.8 (3.8.1) to create virtualenv
 Creating virtual environment...
<SNIP>
Installing setuptools, pip, wheel...
done.
 Successfully created virtual environment! 
<SNIP>

现在回顾与比较,我已经只安装了相应的命令的输出冷LIBsampleproject(其中胡椒是一个依赖):

test1 % pip freeze       <== Packages I'VE installed w/ pip

-e git+https://github.com/gdamjan/hello-world-python-package.git@10<snip>71#egg=cool_lib
peppercorn==0.6
sampleproject==1.3.1


test1 % pip list         <== All packages, incl. ones I've NOT installed w/ pip

Package       Version Location                                                                    
------------- ------- --------------------------------------------------------------------------
cool-lib      0.1  /Users/terrence/.local/share/virtualenvs/test1-y2Zgz1D2/src/cool-lib           <== Installed w/ `pip` command
peppercorn    0.6       <== Dependency of "sampleproject"
pip           20.0.2  
sampleproject 1.3.1     <== Installed w/ `pip` command
setuptools    45.1.0  
wheel         0.34.2

pip list shows ALL installed packages.

pip freeze shows packages YOU installed via pip (or pipenv if using that tool) command in a requirements format.

Remark below that setuptools, pip, wheel are installed when pipenv shell creates my virtual envelope. These packages were NOT installed by me using pip:

test1 % pipenv shell
Creating a virtualenv for this project…
Pipfile: /Users/terrence/Development/Python/Projects/test1/Pipfile
Using /usr/local/Cellar/pipenv/2018.11.26_3/libexec/bin/python3.8 (3.8.1) to create virtualenv…
⠹ Creating virtual environment...
<SNIP>
Installing setuptools, pip, wheel...
done.
✔ Successfully created virtual environment! 
<SNIP>

Now review & compare the output of the respective commands where I’ve only installed cool-lib and sampleproject (of which peppercorn is a dependency):

test1 % pip freeze       <== Packages I'VE installed w/ pip

-e git+https://github.com/gdamjan/hello-world-python-package.git@10<snip>71#egg=cool_lib
peppercorn==0.6
sampleproject==1.3.1


test1 % pip list         <== All packages, incl. ones I've NOT installed w/ pip

Package       Version Location                                                                    
------------- ------- --------------------------------------------------------------------------
cool-lib      0.1  /Users/terrence/.local/share/virtualenvs/test1-y2Zgz1D2/src/cool-lib           <== Installed w/ `pip` command
peppercorn    0.6       <== Dependency of "sampleproject"
pip           20.0.2  
sampleproject 1.3.1     <== Installed w/ `pip` command
setuptools    45.1.0  
wheel         0.34.2

如何检查** kwargs键是否存在?

问题:如何检查** kwargs键是否存在?

Python 3.2.3。这里列出了一些想法,这些想法可以在常规var上使用,但是** kwargs似乎遵循不同的规则…所以,为什么这行不通?我如何检查** kwargs中的键是否存在?

if kwargs['errormessage']:
    print("It exists")

我也认为这应该可行,但是不-

if errormessage in kwargs:
    print("yeah it's here")

我猜是因为kwargs是可迭代的?我是否必须遍历它只是为了检查是否存在特定的密钥?

Python 3.2.3. There were some ideas listed here, which work on regular var’s, but it seems **kwargs play by different rules… so why doesn’t this work and how can I check to see if a key in **kwargs exists?

if kwargs['errormessage']:
    print("It exists")

I also think this should work, but it doesn’t —

if errormessage in kwargs:
    print("yeah it's here")

I’m guessing because kwargs is iterable? Do I have to iterate through it just to check if a particular key is there?


回答 0

你要

if 'errormessage' in kwargs:
    print("found it")

获得价值 errormessage

if 'errormessage' in kwargs:
    print("errormessage equals " + kwargs.get("errormessage"))

这样,kwargs只是另一个dict。您的第一个示例,if kwargs['errormessage']意思是“获取与kwargs中的键“ errormessage”关联的值,然后检查其bool值”。因此,如果没有这样的密钥,您将得到一个KeyError

您的第二个示例if errormessage in kwargs:表示“如果kwargs包含以”命名的元素errormessage,并且除非“ errormessage”是变量的名称,否则您将获得NameError

我应该提到的是,字典也有一个.get()接受默认参数的方法(本身默认为None),以便kwargs.get("errormessage")在该键存在时返回值,None否则返回值(类似地kwargs.get("errormessage", 17),您可能会认为这样做)。当您不关心键的存在与拥有None值或键不存在之间的区别时,这会很方便。

You want

if 'errormessage' in kwargs:
    print("found it")

To get the value of errormessage

if 'errormessage' in kwargs:
    print("errormessage equals " + kwargs.get("errormessage"))

In this way, kwargs is just another dict. Your first example, if kwargs['errormessage'], means “get the value associated with the key “errormessage” in kwargs, and then check its bool value”. So if there’s no such key, you’ll get a KeyError.

Your second example, if errormessage in kwargs:, means “if kwargs contains the element named by “errormessage“, and unless “errormessage” is the name of a variable, you’ll get a NameError.

I should mention that dictionaries also have a method .get() which accepts a default parameter (itself defaulting to None), so that kwargs.get("errormessage") returns the value if that key exists and None otherwise (similarly kwargs.get("errormessage", 17) does what you might think it does). When you don’t care about the difference between the key existing and having None as a value or the key not existing, this can be handy.


回答 1

DSM和Tadeck的答案将直接回答您的问题。

在我的脚本中,我经常使用便捷dict.pop()来处理可选参数和其他参数。这是一个简单print()包装器的示例:

def my_print(*args, **kwargs):
    prefix = kwargs.pop('prefix', '')
    print(prefix, *args, **kwargs)

然后:

>>> my_print('eggs')
 eggs
>>> my_print('eggs', prefix='spam')
spam eggs

如您所见,如果prefix中未包含kwargs,则默认值''(空字符串)存储在本地prefix变量中。如果给出,则使用其值。

对于编写任何类型的函数的包装程序,通常这是一个紧凑且易读的方法:始终只是传递您不了解的传递参数,甚至不知道它们是否存在。如果您总是通过,*args并且**kwargs使代码变慢,并且需要更多键入,但是如果被调用函数的接口(在这种情况下print)发生了变化,则无需更改代码。这种方法减少了开发时间,同时支持所有接口更改。

DSM’s and Tadeck’s answers answer your question directly.

In my scripts I often use the convenient dict.pop() to deal with optional, and additional arguments. Here’s an example of a simple print() wrapper:

def my_print(*args, **kwargs):
    prefix = kwargs.pop('prefix', '')
    print(prefix, *args, **kwargs)

Then:

>>> my_print('eggs')
 eggs
>>> my_print('eggs', prefix='spam')
spam eggs

As you can see, if prefix is not contained in kwargs, then the default '' (empty string) is being stored in the local prefix variable. If it is given, then its value is being used.

This is generally a compact and readable recipe for writing wrappers for any kind of function: Always just pass-through arguments you don’t understand, and don’t even know if they exist. If you always pass through *args and **kwargs you make your code slower, and requires a bit more typing, but if interfaces of the called function (in this case print) changes, you don’t need to change your code. This approach reduces development time while supporting all interface changes.


回答 2

就是这样:

if 'errormessage' in kwargs:
    print("yeah it's here")

您需要检查密钥是否在字典中。这样做的语法是some_key in some_dict(这里some_key是可哈希的,不一定是字符串)。

您链接的想法(这些想法)包含用于检查locals()and所返回的字典中是否存在特定键的示例globals()。您的示例与此类似,因为您正在检查kwargs字典(包含关键字参数的字典)中是否存在特定键。

It is just this:

if 'errormessage' in kwargs:
    print("yeah it's here")

You need to check, if the key is in the dictionary. The syntax for that is some_key in some_dict (where some_key is something hashable, not necessarily a string).

The ideas you have linked (these ideas) contained examples for checking if specific key existed in dictionaries returned by locals() and globals(). Your example is similar, because you are checking existence of specific key in kwargs dictionary (the dictionary containing keyword arguments).


回答 3

一种方法是自己添加!怎么样?通过合并kwargs一堆默认值。例如,如果您事先不知道密钥,则此方法不适用于所有情况。但是,如果有,这是一个简单的示例:

import sys

def myfunc(**kwargs):
    args = {'country':'England','town':'London',
            'currency':'Pound', 'language':'English'}

    diff = set(kwargs.keys()) - set(args.keys())
    if diff:
        print("Invalid args:",tuple(diff),file=sys.stderr)
        return

    args.update(kwargs)            
    print(args)

默认值在字典中设置,该字典args包括我们期望的所有键。我们首先检查kwarg中是否有任何意外的键。然后我们更新argskwargs,这将覆盖任何新的价值用户已设置。我们不需要测试键是否存在,我们现在将其args用作参数字典,并且不再需要kwargs

One way is to add it by yourself! How? By merging kwargs with a bunch of defaults. This won’t be appropriate on all occasions, for example, if the keys are not known to you in advance. However, if they are, here is a simple example:

import sys

def myfunc(**kwargs):
    args = {'country':'England','town':'London',
            'currency':'Pound', 'language':'English'}

    diff = set(kwargs.keys()) - set(args.keys())
    if diff:
        print("Invalid args:",tuple(diff),file=sys.stderr)
        return

    args.update(kwargs)            
    print(args)

The defaults are set in the dictionary args, which includes all the keys we are expecting. We first check to see if there are any unexpected keys in kwargs. Then we update args with kwargs which will overwrite any new values that the user has set. We don’t need to test if a key exists, we now use args as our argument dictionary and have no further need of kwargs.


回答 4

您可以自己轻松发现这些东西:

def hello(*args, **kwargs):
    print kwargs
    print type(kwargs)
    print dir(kwargs)

hello(what="world")

You can discover those things easily by yourself:

def hello(*args, **kwargs):
    print kwargs
    print type(kwargs)
    print dir(kwargs)

hello(what="world")

回答 5

if kwarg.__len__() != 0:
    print(kwarg)
if kwarg.__len__() != 0:
    print(kwarg)

如何注释多个返回值的类型?

问题:如何注释多个返回值的类型?

我如何使用类型提示来注释一个返回Iterable总是返回两个值的函数:abool和a str?提示Tuple[bool, str]很接近,除了将返回值类型限制为元组,而不是生成器或其他可迭代类型。

我主要是好奇的,因为我想注释一个foo()用于返回多个值的函数,如下所示:

always_a_bool, always_a_str = foo()

通常函数喜欢foo()做这样的事情return a, b(它返回一个元组),但我喜欢的类型暗示要足够灵活,以取代生成器或列表或别的东西返回的元组。

How do I use type hints to annotate a function that returns an Iterable that always yields two values: a bool and a str? The hint Tuple[bool, str] is close, except that it limits the return value type to a tuple, not a generator or other type of iterable.

I’m mostly curious because I would like to annotate a function foo() that is used to return multiple values like this:

always_a_bool, always_a_str = foo()

Usually functions like foo() do something like return a, b (which returns a tuple), but I would like the type hint to be flexible enough to replace the returned tuple with a generator or list or something else.


回答 0

您总是返回一个对象;使用return one, two只需返回一个元组。

是的,-> Tuple[bool, str]完全正确。

只有Tuple类型可以指定一个固定数量的元素,每一个不同的类型。如果您的函数产生固定数量的返回值,尤其是当这些值是特定的,不同的类型时,确实应该总是返回一个元组。

期望其他序列类型具有可变数量元素的一种类型规范,因此typing.Sequence此处不适用。另请参阅列表和元组之间有什么区别?

元组是异构数据结构(即,它们的条目具有不同的含义),而列表是同类序列。元组具有结构,列表具有顺序。

Python的类型提示系统遵循这一理念,目前尚无语法来指定固定长度的可迭代对象,并在特定位置包含特定类型。

如果必须指定任何可迭代的对象,那么最好的方法是:

-> Iterable[Union[bool, str]]

在这一点上,调用者可以期望布尔值和字符串以任意顺序,并且长度未知(0到无穷大之间)。

You are always returning one object; using return one, two simply returns a tuple.

So yes, -> Tuple[bool, str] is entirely correct.

Only the Tuple type lets you specify a fixed number of elements, each with a distinct type. You really should be returning a tuple, always, if your function produces a fixed number of return values, especially when those values are specific, distinct types.

Other sequence types are expected to have one type specification for a variable number of elements, so typing.Sequence is not suitable here. Also see What’s the difference between lists and tuples?

Tuples are heterogeneous data structures (i.e., their entries have different meanings), while lists are homogeneous sequences. Tuples have structure, lists have order.

Python’s type hint system adheres to that philosophy, there is currently no syntax to specify an iterable of fixed length and containing specific types at specific positions.

If you must specify that any iterable will do, then the best you can do is:

-> Iterable[Union[bool, str]]

at which point the caller can expect booleans and strings in any order, and of unknown length (anywhere between 0 and infinity).


为什么带有f字符串的f'{{{74}}}’与f'{{74}}’相同?

问题:为什么带有f字符串的f'{{{74}}}’与f'{{74}}’相同?

f字符串可从Python 3.6中获得,对于格式化字符串非常有用:

>>> n='you'
>>> f'hello {n}, how are you?'
'hello you, how are you?'

Python 3的f字符串中阅读有关它们的更多信息:改进的字符串格式语法(指南)。我发现了一个有趣的模式:

请注意,使用三重花括号将导致字符串中只有一个大括号:

>>> f"{{{74}}}"
'{74}'

但是,如果使用的括号多于三个,则可以显示更多的括号:

>>> f"{{{{74}}}}"
'{{74}}'

确实是这样:

>>> f'{74}'
'74'

>>> f'{{74}}'
'{74}'

现在,如果我们从两个传递{到三个,结果将是相同的:

>>> f'{{{74}}}'
'{74}'           # same as f'{{74}}' !

因此,我们最多需要4个!({{{{)获得两个大括号作为输出:

>>> f'{{{{74}}}}'
'{{74}}'

为什么是这样?从那时起,用两个花括号使Python需要一个额外的花括号会发生什么?

f-Strings are available from Python 3.6 and are very useful for formatting strings:

>>> n='you'
>>> f'hello {n}, how are you?'
'hello you, how are you?'

Reading more about them in Python 3’s f-Strings: An Improved String Formatting Syntax (Guide). I found an interesting pattern:

Note that using triple braces will result in there being only single braces in your string:

>>> f"{{{74}}}"
'{74}'

However, you can get more braces to show if you use more than triple braces:

>>> f"{{{{74}}}}"
'{{74}}'

And this is exactly the case:

>>> f'{74}'
'74'

>>> f'{{74}}'
'{74}'

Now if we pass from two { to three, the result is the same:

>>> f'{{{74}}}'
'{74}'           # same as f'{{74}}' !

So we need up to 4! ({{{{) to get two braces as an output:

>>> f'{{{{74}}}}'
'{{74}}'

Why is this? What happens with two braces to have Python require an extra one from that moment on?


回答 0

双括号逃脱牙套,所以没有发生插值:{{{}}}。并74保持不变的字符串,'74'

与三括号相同,外部的双括号被转义。另一方面,内部括号导致值的常规字符串插值74

也就是说,该字符串f'{{{74}}}'等效于f'{{ {74} }}',但没有空格(或等效于'{' + f'{74}' + '}')。

在用变量替换数字常量时,您可以看到区别:

In [1]: x = 74

In [2]: f'{{x}}'
Out[2]: '{x}'

In [3]: f'{{{x}}}'
Out[3]: '{74}'

Double braces escape the braces, so that no interpolation happens: {{{, and }}}. And 74 remains an unchanged string, '74'.

With triple braces, the outer double braces are escaped, same as above. The inner braces, on the other hand, lead to regular string interpolation of the value 74.

That is, the string f'{{{74}}}' is equivalent to f'{{ {74} }}', but without spaces (or, equivalently, to '{' + f'{74}' + '}').

You can see the difference when replacing the numeric constant by a variable:

In [1]: x = 74

In [2]: f'{{x}}'
Out[2]: '{x}'

In [3]: f'{{{x}}}'
Out[3]: '{74}'

Python:导入urllib.quote

问题:Python:导入urllib.quote

我想用urllib.quote()。但是python(python3)找不到模块。假设我有以下代码行:

print(urllib.quote("châteu", safe=''))

如何导入urllib.quote?

import urllibimport urllib.quote两者都给

AttributeError: 'module' object has no attribute 'quote'

令我困惑的urllib.request是可以通过以下方式访问import urllib.request

I would like to use urllib.quote(). But python (python3) is not finding the module. Suppose, I have this line of code:

print(urllib.quote("châteu", safe=''))

How do I import urllib.quote?

import urllib or import urllib.quote both give

AttributeError: 'module' object has no attribute 'quote'

What confuses me is that urllib.request is accessible via import urllib.request


回答 0

在Python 3.x中,您需要导入urllib.parse.quote

>>> import urllib.parse
>>> urllib.parse.quote("châteu", safe='')
'ch%C3%A2teu'

根据Python 2.x urllib模块文档

注意

urllib模块已经被分成部分和更名在Python 3 urllib.requesturllib.parse,和urllib.error

In Python 3.x, you need to import urllib.parse.quote:

>>> import urllib.parse
>>> urllib.parse.quote("châteu", safe='')
'ch%C3%A2teu'

According to Python 2.x urllib module documentation:

NOTE

The urllib module has been split into parts and renamed in Python 3 to urllib.request, urllib.parse, and urllib.error.


回答 1

如果您需要同时处理Python 2.x和3.x,则可以捕获异常并加载替代项。

try:
    from urllib import quote  # Python 2.X
except ImportError:
    from urllib.parse import quote  # Python 3+

您还可以使用python兼容性包装器6来处理此问题。

from six.moves.urllib.parse import quote

If you need to handle both Python 2.x and 3.x you can catch the exception and load the alternative.

try:
    from urllib import quote  # Python 2.X
except ImportError:
    from urllib.parse import quote  # Python 3+

You could also use the python compatibility wrapper six to handle this.

from six.moves.urllib.parse import quote

回答 2

urllib在Python3中进行了一些更改,现在可以从parse子模块中导入

>>> from urllib.parse import quote  
>>> quote('"')                      
'%22'                               

urllib went through some changes in Python3 and can now be imported from the parse submodule

>>> from urllib.parse import quote  
>>> quote('"')                      
'%22'                               

回答 3

这就是我在不使用异常的情况下的处理方式。

import sys
if sys.version_info.major > 2:  # Python 3 or later
    from urllib.parse import quote
else:  # Python 2
    from urllib import quote

This is how I handle this, without using exceptions.

import sys
if sys.version_info.major > 2:  # Python 3 or later
    from urllib.parse import quote
else:  # Python 2
    from urllib import quote

如何在f字符串中使用换行符’\ n’格式化Python 3.6中的输出?

问题:如何在f字符串中使用换行符’\ n’格式化Python 3.6中的输出?

我想知道如何用f字符串以Pythonic方式格式化这种情况:

names = ['Adam', 'Bob', 'Cyril']
text = f"Winners are:\n{'\n'.join(names)}"
print(text)

问题是'\'无法在{...}f字符串的表达式部分内使用。预期Yield:

Winners are:
Adam
Bob
Cyril

I would like to know how to format this case in a Pythonic way with f-strings:

names = ['Adam', 'Bob', 'Cyril']
text = f"Winners are:\n{'\n'.join(names)}"
print(text)

The problem is that '\' cannot be used inside the {...} expression portions of an f-string. Expected output:

Winners are:
Adam
Bob
Cyril

回答 0

你不能 反斜杠不能出现在花括号内{};这样做会导致SyntaxError

>>> f'{\}'
SyntaxError: f-string expression part cannot include a backslash

这是在PEP中为f字符串指定的:

反斜杠可能不会出现在f字符串的表达式部分内,[…]

一种选择是先'\n'命名,然后再.joinf-string 内进行命名;也就是说,不使用文字:

names = ['Adam', 'Bob', 'Cyril']
nl = '\n'
text = f"Winners are:{nl}{nl.join(names)}"
print(text)

结果是:

Winners are:
Adam
Bob
Cyril

@wim指定的另一个选项是chr(10)用来获取\n返回值,然后在该处加入。f"Winners are:\n{chr(10).join(names)}"

当然,还有另一种方法是'\n'.join预先添加相应的名称:

n = "\n".join(names)
text = f"Winners are:\n{n}"

结果相同。

注意:

这是f-string和之间的细微差别之一str.format。在后者中,您可以始终使用标点符号,只要打开包含这些键的相应古怪字典即可:

>>> "{\\} {*}".format(**{"\\": 'Hello', "*": 'World!'})
"Hello World!"

(请不要这样做。)

在前一种情况下,标点符号是不允许的,因为您不能使用它们的标识符。


撇开:我肯定会选择printformat,因为其他答案也可以替代。我给出的选项仅在由于某些原因必须使用f字符串的情况下适用。

仅仅因为有些新事物,并不意味着您应该尝试用它做一切;-)

You can’t. Backslashes cannot appear inside the curly braces {}; doing so results in a SyntaxError:

>>> f'{\}'
SyntaxError: f-string expression part cannot include a backslash

This is specified in the PEP for f-strings:

Backslashes may not appear inside the expression portions of f-strings, […]

One option is assinging '\n' to a name and then .join on that inside the f-string; that is, without using a literal:

names = ['Adam', 'Bob', 'Cyril']
nl = '\n'
text = f"Winners are:{nl}{nl.join(names)}"
print(text)

Results in:

Winners are:
Adam
Bob
Cyril

Another option, as specified by @wim, is to use chr(10) to get \n returned and then join there. f"Winners are:\n{chr(10).join(names)}"

Yet another, of course, is to '\n'.join beforehand and then add the name accordingly:

n = "\n".join(names)
text = f"Winners are:\n{n}"

which results in the same output.

Note:

This is one of the small differences between f-strings and str.format. In the latter, you can always use punctuation granted that a corresponding wacky dict is unpacked that contains those keys:

>>> "{\\} {*}".format(**{"\\": 'Hello', "*": 'World!'})
"Hello World!"

(Please don’t do this.)

In the former, punctuation isn’t allowed because you can’t have identifiers that use them.


Aside: I would definitely opt for print or format, as the other answers suggest as an alternative. The options I’ve given only apply if you must for some reason use f-strings.

Just because something is new, doesn’t mean you should try and do everything with it ;-)


回答 1

您不需要f字符串或其他格式化程序即可使用分隔符打印字符串列表。只需使用sep关键字参数即可print()

names = ['Adam', 'Bob', 'Cyril']
print('Winners are:', *names, sep='\n')

输出:

Winners are:
Adam
Bob
Cyril

就是说,使用str.join()/str.format()这里比任何f字符串解决方法更容易理解。

print('\n'.join(['Winners are:', *names]))
print('Winners are:\n{}'.format('\n'.join(names)))

You don’t need f-strings or other formatters to print a list of strings with a separator. Just use the sep keyword argument to print():

names = ['Adam', 'Bob', 'Cyril']
print('Winners are:', *names, sep='\n')

Output:

Winners are:
Adam
Bob
Cyril

That said, using str.join()/str.format() here would arguably be simpler and more readable than any f-string workaround:

print('\n'.join(['Winners are:', *names]))
print('Winners are:\n{}'.format('\n'.join(names)))

回答 2

您不能像其他人所说的那样在f字符串中使用反斜杠,但是您可以使用来解决这个问题os.linesep(尽管请注意,并非\n在所有平台上都使用反斜杠,除非读/写二进制文件,否则不建议这样做;请参阅Rick的评论):

>>> import os
>>> names = ['Adam', 'Bob', 'Cyril']
>>> print(f"Winners are:\n{os.linesep.join(names)}")
Winners are:
Adam
Bob
Cyril 

或以一种不太易读的方式,但保证是\n,方法是chr()

>>> print(f"Winners are:\n{chr(10).join(names)}")
Winners are:
Adam
Bob
Cyril

You can’t use backslashes in f-strings as others have said, but you could step around this using os.linesep (although note this won’t be \n on all platforms, and is not recommended unless reading/writing binary files; see Rick’s comments):

>>> import os
>>> names = ['Adam', 'Bob', 'Cyril']
>>> print(f"Winners are:\n{os.linesep.join(names)}")
Winners are:
Adam
Bob
Cyril 

Or perhaps in a less readable way, but guaranteed to be \n, with chr():

>>> print(f"Winners are:\n{chr(10).join(names)}")
Winners are:
Adam
Bob
Cyril

回答 3

其他答案给出了有关如何将换行符放入f字符串字段的想法。但是,我认为对于OP给出的示例(可能指示OP的实际用例),实际上不应该使用这些想法。

使用f字符串的全部目的是提高代码的可读性。f字符串是您无法使用的format。请仔细考虑是否对此有更多可读性(如果可以的话):

f"Winners are:\n{'\n'.join(names)}"

…或这个:

newline = '\n'
f"Winners are:\n{newline.join(names)}"

…或这个:

"Winners are:\n{chr(10).join(names)}"

与这个:

"Winners are:\n{}".format('\n'.join(names))

最后一种方法至少具有可读性,如果不是更多的话。

简而言之:当您需要螺丝起子时,不要只用锤子,因为那是新的有光泽的工具。读取代码的频率远高于写入代码。

对于其他用例,是的,这个chr(10)想法或newline想法可能是适当的。但不是给定的。

The other answers give ideas for how to put the newline character into a f-string field. However, I would argue that for the example the OP gave (which may or may not be indicative of OP’s actual use case), none of these ideas should actually be used.

The entire point of using f-strings is increasing code readability. There is nothing you can do with f-strings that you cannot do with format. Consider carefully whether there is anything more readable about this (if you could do it):

f"Winners are:\n{'\n'.join(names)}"

…or this:

newline = '\n'
f"Winners are:\n{newline.join(names)}"

…or this:

"Winners are:\n{chr(10).join(names)}"

vs. this:

"Winners are:\n{}".format('\n'.join(names))

The last way is at least as readable, if not more so.

In short: don’t use a hammer when you need a screwdriver just because you have a shiny new one. Code is read much more often than it is written.

For other use cases, yes, it’s possible the chr(10) idea or newline idea may be appropriate. But not for the one given.


Python 3在线解释器/ Shell

问题:Python 3在线解释器/ Shell

是否有使用Python 3 的在线解释器,例如http://codepad.org/http://www.trypython.org/

回答

由于问题已经结束,因此我在这里给出另一个答案。

Wandbox提供了多种语言的在线REPL,包括Python 2.x和3.x,C ++和Java。

Is there an online interpreter like http://codepad.org/ or http://www.trypython.org/ which uses Python 3?

Answer

Since the question is closed, I give another answer here.

Wandbox offers online REPLs for many languages, including Python 2.x and 3.x, C++ and Java.


回答 0

Ideone支持Python 2.6和Python 3

Ideone supports Python 2.6 and Python 3


回答 1

我最近在CompileOnline遇到了Python 3解释器。

I recently came across Python 3 interpreter at CompileOnline.


“模块”没有属性“ urlencode”

问题:“模块”没有属性“ urlencode”

当我尝试遵循与URL编码相关的Python Wiki的示例时

>>> import urllib
>>> params = urllib.urlencode({'spam': 1, 'eggs': 2, 'bacon': 0})
>>> f = urllib.urlopen("http://www.musi-cal.com/cgi-bin/query", params)
>>> print f.read()

在第二行引发错误:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute 'urlencode'

我想念什么?

When I try to follow the Python Wiki’s example related to URL encoding:

>>> import urllib
>>> params = urllib.urlencode({'spam': 1, 'eggs': 2, 'bacon': 0})
>>> f = urllib.urlopen("http://www.musi-cal.com/cgi-bin/query", params)
>>> print f.read()

An error is raised on the second line:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute 'urlencode'

What am I missing?


回答 0

urllib已在拆分Python 3

urllib.urlencode()功能是现在urllib.parse.urlencode()

urllib.urlopen()现在的功能urllib.request.urlopen()

urllib has been split up in Python 3.

The urllib.urlencode() function is now urllib.parse.urlencode(),

the urllib.urlopen() function is now urllib.request.urlopen().


回答 1

import urllib.parse
urllib.parse.urlencode({'spam': 1, 'eggs': 2, 'bacon': 0})
import urllib.parse
urllib.parse.urlencode({'spam': 1, 'eggs': 2, 'bacon': 0})

回答 2

您使用Python 2文档,但使用Python 3编写程序。

You use the Python 2 docs but write your program in Python 3.