标签归档:Python

如何将字符串中每个单词的首字母大写?

问题:如何将字符串中每个单词的首字母大写?

s = 'the brown fox'

…在这里做某事…

s 应该 :

'The Brown Fox'

最简单的方法是什么?

s = 'the brown fox'

…do something here…

s should be :

'The Brown Fox'

What’s the easiest way to do this?


回答 0

.title()一个字符串(ASCII或Unicode是细)的方法做到这一点:

>>> "hello world".title()
'Hello World'
>>> u"hello world".title()
u'Hello World'

但是,请注意文档中提到的带有嵌入式撇号的字符串。

该算法使用单词的简单语言独立定义作为连续字母的组。该定义在许多情况下都适用,但是它意味着缩略语和所有格中的撇号形成单词边界,这可能不是期望的结果:

>>> "they're bill's friends from the UK".title()
"They'Re Bill'S Friends From The Uk"

The .title() method of a string (either ASCII or Unicode is fine) does this:

>>> "hello world".title()
'Hello World'
>>> u"hello world".title()
u'Hello World'

However, look out for strings with embedded apostrophes, as noted in the docs.

The algorithm uses a simple language-independent definition of a word as groups of consecutive letters. The definition works in many contexts but it means that apostrophes in contractions and possessives form word boundaries, which may not be the desired result:

>>> "they're bill's friends from the UK".title()
"They'Re Bill'S Friends From The Uk"

回答 1

.title()方法效果不佳,

>>> "they're bill's friends from the UK".title()
"They'Re Bill'S Friends From The Uk"

试试string.capwords()方法,

import string
string.capwords("they're bill's friends from the UK")
>>>"They're Bill's Friends From The Uk"

capwordspython文档中

使用str.split()将参数分解为单词,使用str.capitalize()将每个单词大写,然后使用str.join()将大写的单词连接起来。如果不存在可选的第二个参数sep或“无”,则将空白字符替换为一个空格,并删除前导和尾随空白,否则将使用sep拆分和合并单词。

The .title() method can’t work well,

>>> "they're bill's friends from the UK".title()
"They'Re Bill'S Friends From The Uk"

Try string.capwords() method,

import string
string.capwords("they're bill's friends from the UK")
>>>"They're Bill's Friends From The Uk"

From the python docs on capwords:

Split the argument into words using str.split(), capitalize each word using str.capitalize(), and join the capitalized words using str.join(). If the optional second argument sep is absent or None, runs of whitespace characters are replaced by a single space and leading and trailing whitespace are removed, otherwise sep is used to split and join the words.


回答 2

仅仅因为这种事情对我来说很有趣,所以这里有另外两个解决方案。

拆分为单词,对拆分组中的每个单词进行大写,然后重新加入。不管是什么,这都会将将单词分隔的空白变为单个空白。

s = 'the brown fox'
lst = [word[0].upper() + word[1:] for word in s.split()]
s = " ".join(lst)

编辑:我不记得我在写上面的代码时在想什么,但是没有必要建立一个明确的列表。我们可以使用生成器表达式以懒惰的方式进行操作。因此,这是一个更好的解决方案:

s = 'the brown fox'
s = ' '.join(word[0].upper() + word[1:] for word in s.split())

使用正则表达式匹配字符串的开头,或使用空格分隔单词,再加上一个非空格字符;用括号标记“匹配组”。编写一个函数,该函数接受一个match对象,并以大写形式返回空白的空白匹配组和非空白的字符匹配组。然后使用re.sub()替换图案。这个没有第一个解决方案的标点符号问题,也没有像我的第一个解决方案那样重做空白。这产生最好的结果。

import re
s = 'the brown fox'

def repl_func(m):
    """process regular expression match groups for word upper-casing problem"""
    return m.group(1) + m.group(2).upper()

s = re.sub("(^|\s)(\S)", repl_func, s)


>>> re.sub("(^|\s)(\S)", repl_func, s)
"They're Bill's Friends From The UK"

我很高兴研究了这个答案。我不知道re.sub()可以发挥作用!您可以在内部re.sub()进行非平凡的处理以产生最终结果!

Just because this sort of thing is fun for me, here are two more solutions.

Split into words, initial-cap each word from the split groups, and rejoin. This will change the white space separating the words into a single white space, no matter what it was.

s = 'the brown fox'
lst = [word[0].upper() + word[1:] for word in s.split()]
s = " ".join(lst)

EDIT: I don’t remember what I was thinking back when I wrote the above code, but there is no need to build an explicit list; we can use a generator expression to do it in lazy fashion. So here is a better solution:

s = 'the brown fox'
s = ' '.join(word[0].upper() + word[1:] for word in s.split())

Use a regular expression to match the beginning of the string, or white space separating words, plus a single non-whitespace character; use parentheses to mark “match groups”. Write a function that takes a match object, and returns the white space match group unchanged and the non-whitespace character match group in upper case. Then use re.sub() to replace the patterns. This one does not have the punctuation problems of the first solution, nor does it redo the white space like my first solution. This one produces the best result.

import re
s = 'the brown fox'

def repl_func(m):
    """process regular expression match groups for word upper-casing problem"""
    return m.group(1) + m.group(2).upper()

s = re.sub("(^|\s)(\S)", repl_func, s)


>>> re.sub("(^|\s)(\S)", repl_func, s)
"They're Bill's Friends From The UK"

I’m glad I researched this answer. I had no idea that re.sub() could take a function! You can do nontrivial processing inside re.sub() to produce the final result!


回答 3

以下是执行此操作的不同方法的摘要,它们将适用于所有这些输入:

""           => ""       
"a b c"      => "A B C"             
"foO baR"    => "FoO BaR"      
"foo    bar" => "Foo    Bar"   
"foo's bar"  => "Foo's Bar"    
"foo's1bar"  => "Foo's1bar"    
"foo 1bar"   => "Foo 1bar"     

-最简单的解决方案是将句子拆分成单词并大写第一个字母,然后将其重新组合在一起:

# Be careful with multiple spaces, and empty strings
# for empty words w[0] would cause an index error, 
# but with w[:1] we get an empty string as desired
def cap_sentence(s):
  return ' '.join(w[:1].upper() + w[1:] for w in s.split(' ')) 

-如果您不想先使用花哨的生成器将输入字符串拆分成单词,请执行以下操作:

# Iterate through each of the characters in the string and capitalize 
# the first char and any char after a blank space
from itertools import chain 
def cap_sentence(s):
  return ''.join( (c.upper() if prev == ' ' else c) for c, prev in zip(s, chain(' ', s)) )

-或不导入itertools:

def cap_sentence(s):
  return ''.join( (c.upper() if i == 0 or s[i-1] == ' ' else c) for i, c in enumerate(s) )

-或者您可以使用正则表达式,来自steveha的答案

# match the beginning of the string or a space, followed by a non-space
import re
def cap_sentence(s):
  return re.sub("(^|\s)(\S)", lambda m: m.group(1) + m.group(2).upper(), s)

现在,这些是其他一些已发布的答案,如果我们使用的单词定义是句子的开头或空格后的任何内容,则这些输入将无法按预期运行:

  return s.title()

# Undesired outputs: 
"foO baR"    => "Foo Bar"       
"foo's bar"  => "Foo'S Bar" 
"foo's1bar"  => "Foo'S1Bar"     
"foo 1bar"   => "Foo 1Bar"      

  return ' '.join(w.capitalize() for w in s.split())    
  # or
  import string
  return string.capwords(s)

# Undesired outputs:
"foO baR"    => "Foo Bar"      
"foo    bar" => "Foo Bar"      

使用”进行拆分将修复第二个输出,但是capwords()仍不适用于第一个输出

  return ' '.join(w.capitalize() for w in s.split(' '))    
  # or
  import string
  return string.capwords(s, ' ')

# Undesired outputs:
"foO baR"    => "Foo Bar"      

注意多个空格

  return ' '.join(w[0].upper() + w[1:] for w in s.split())
# Undesired outputs:
"foo    bar" => "Foo Bar"                 

Here’s a summary of different ways to do it, they will work for all these inputs:

""           => ""       
"a b c"      => "A B C"             
"foO baR"    => "FoO BaR"      
"foo    bar" => "Foo    Bar"   
"foo's bar"  => "Foo's Bar"    
"foo's1bar"  => "Foo's1bar"    
"foo 1bar"   => "Foo 1bar"     

– The simplest solution is to split the sentence into words and capitalize the first letter then join it back together:

# Be careful with multiple spaces, and empty strings
# for empty words w[0] would cause an index error, 
# but with w[:1] we get an empty string as desired
def cap_sentence(s):
  return ' '.join(w[:1].upper() + w[1:] for w in s.split(' ')) 

– If you don’t want to split the input string into words first, and using fancy generators:

# Iterate through each of the characters in the string and capitalize 
# the first char and any char after a blank space
from itertools import chain 
def cap_sentence(s):
  return ''.join( (c.upper() if prev == ' ' else c) for c, prev in zip(s, chain(' ', s)) )

– Or without importing itertools:

def cap_sentence(s):
  return ''.join( (c.upper() if i == 0 or s[i-1] == ' ' else c) for i, c in enumerate(s) )

– Or you can use regular expressions, from steveha’s answer:

# match the beginning of the string or a space, followed by a non-space
import re
def cap_sentence(s):
  return re.sub("(^|\s)(\S)", lambda m: m.group(1) + m.group(2).upper(), s)

Now, these are some other answers that were posted, and inputs for which they don’t work as expected if we are using the definition of a word being the start of the sentence or anything after a blank space:

  return s.title()

# Undesired outputs: 
"foO baR"    => "Foo Bar"       
"foo's bar"  => "Foo'S Bar" 
"foo's1bar"  => "Foo'S1Bar"     
"foo 1bar"   => "Foo 1Bar"      

  return ' '.join(w.capitalize() for w in s.split())    
  # or
  import string
  return string.capwords(s)

# Undesired outputs:
"foO baR"    => "Foo Bar"      
"foo    bar" => "Foo Bar"      

using ‘ ‘ for the split will fix the second output, but capwords() still won’t work for the first

  return ' '.join(w.capitalize() for w in s.split(' '))    
  # or
  import string
  return string.capwords(s, ' ')

# Undesired outputs:
"foO baR"    => "Foo Bar"      

Be careful with multiple blank spaces

  return ' '.join(w[0].upper() + w[1:] for w in s.split())
# Undesired outputs:
"foo    bar" => "Foo Bar"                 

回答 4

@jibberia anwser的复制粘贴就绪版本:

def capitalize(line):
    return ' '.join(s[:1].upper() + s[1:] for s in line.split(' '))

Copy-paste-ready version of @jibberia anwser:

def capitalize(line):
    return ' '.join(s[:1].upper() + s[1:] for s in line.split(' '))

回答 5

当解决方案既简单又安全时,为什么要使join和for循环使您的生活复杂化?

只是这样做:

string = "the brown fox"
string[0].upper()+string[1:]

Why do you complicate your life with joins and for loops when the solution is simple and safe??

Just do this:

string = "the brown fox"
string[0].upper()+string[1:]

回答 6

如果str.title()对您不起作用,请自己大写。

  1. 将字符串分成单词列表
  2. 每个单词的首字母大写
  3. 将单词连接成一个字符串

单线:

>>> ' '.join([s[0].upper() + s[1:] for s in "they're bill's friends from the UK".split(' ')])
"They're Bill's Friends From The UK"

清晰的例子:

input = "they're bill's friends from the UK"
words = input.split(' ')
capitalized_words = []
for word in words:
    title_case_word = word[0].upper() + word[1:]
    capitalized_words.append(title_case_word)
output = ' '.join(capitalized_words)

If str.title() doesn’t work for you, do the capitalization yourself.

  1. Split the string into a list of words
  2. Capitalize the first letter of each word
  3. Join the words into a single string

One-liner:

>>> ' '.join([s[0].upper() + s[1:] for s in "they're bill's friends from the UK".split(' ')])
"They're Bill's Friends From The UK"

Clear example:

input = "they're bill's friends from the UK"
words = input.split(' ')
capitalized_words = []
for word in words:
    title_case_word = word[0].upper() + word[1:]
    capitalized_words.append(title_case_word)
output = ' '.join(capitalized_words)

回答 7

如果只想要第一个字母:

>>> 'hello world'.capitalize()
'Hello world'

但是要大写每个单词:

>>> 'hello world'.title()
'Hello World'

If only you want the first letter:

>>> 'hello world'.capitalize()
'Hello world'

But to capitalize each word:

>>> 'hello world'.title()
'Hello World'

回答 8

如果您访问[1:],则空字符串将引发错误,因此我将使用:

def my_uppercase(title):
    if not title:
       return ''
    return title[0].upper() + title[1:]

仅将首字母大写。

An empty string will raise an Error if you access [1:], therefore I would use:

def my_uppercase(title):
    if not title:
       return ''
    return title[0].upper() + title[1:]

to uppercase the first letter only.


回答 9

正如Mark所指出的,您应该使用.title()

"MyAwesomeString".title()

但是,如果要在django模板中将第一个字母大写,则可以使用以下命令:

{{ "MyAwesomeString"|title }}

或使用变量:

{{ myvar|title }}

As Mark pointed out you should use .title():

"MyAwesomeString".title()

However, if would like to make the first letter uppercase inside a django template, you could use this:

{{ "MyAwesomeString"|title }}

or using a variable:

{{ myvar|title }}

回答 10

建议的方法str.title()并非在所有情况下都有效。例如:

string = "a b 3c"
string.title()
> "A B 3C"

代替"A B 3c"

我认为,最好执行以下操作:

def capitalize_words(string):
    words = string.split(" ") # just change the split(" ") method
    return ' '.join([word.capitalize() for word in words])

capitalize_words(string)
>'A B 3c'

The suggested method str.title() does not work in all cases. For example:

string = "a b 3c"
string.title()
> "A B 3C"

instead of "A B 3c".

I think, it is better to do something like this:

def capitalize_words(string):
    words = string.split(" ") # just change the split(" ") method
    return ' '.join([word.capitalize() for word in words])

capitalize_words(string)
>'A B 3c'

回答 11

尽管所有答案都已经令人满意,但是我将尝试覆盖所有2个额外的情况以及以前的所有情况。

如果空间不均匀并且您想要保持相同

string = hello    world i  am    here.

如果所有字符串都不以字母开头

string = 1 w 2 r 3g

在这里你可以使用

def solve(s):
    a = s.split(' ')
    for i in range(len(a)):
        a[i]= a[i].capitalize()
    return ' '.join(a)

这会给你

output = Hello    World I  Am    Here
output = 1 W 2 R 3g

我希望这不是多余的。

Although all the answer are already satisfactory but I’ll try to cover the 2 extra cases along with the all the previous case.

if the spaces are not uniform and you want to maintain the same

string = hello    world i  am    here.

if all the string are not starting from alphabets

string = 1 w 2 r 3g

Here you can use this

def solve(s):
    a = s.split(' ')
    for i in range(len(a)):
        a[i]= a[i].capitalize()
    return ' '.join(a)

this will give you

output = Hello    World I  Am    Here
output = 1 W 2 R 3g

I hope this is not redundant.


回答 12

大写单词…

str = "this is string example....  wow!!!";
print "str.title() : ", str.title();

@ Gary02127注释,在解决方案工作标题下带有撇号

import re

def titlecase(s):
    return re.sub(r"[A-Za-z]+('[A-Za-z]+)?", lambda mo: mo.group(0)[0].upper() + mo.group(0)[1:].lower(), s)

text = "He's an engineer, isn't he? SnippetBucket.com "
print(titlecase(text))

To capitalize words…

str = "this is string example....  wow!!!";
print "str.title() : ", str.title();

@Gary02127 comment, below solution work title with apostrophe

import re

def titlecase(s):
    return re.sub(r"[A-Za-z]+('[A-Za-z]+)?", lambda mo: mo.group(0)[0].upper() + mo.group(0)[1:].lower(), s)

text = "He's an engineer, isn't he? SnippetBucket.com "
print(titlecase(text))

回答 13

不要忽视空白的保留。如果您要处理'fred flinstone'而得到'Fred Flinstone'而不是'Fred Flinstone',则说明您的空白空间已损坏。上述某些解决方案将失去空白。这是一个适用于Python 2和3并保留空白的解决方案。

def propercase(s):
    return ''.join(map(''.capitalize, re.split(r'(\s+)', s)))

Don’t overlook the preservation of white space. If you want to process 'fred flinstone' and you get 'Fred Flinstone' instead of 'Fred Flinstone', you’ve corrupted your white space. Some of the above solutions will lose white space. Here’s a solution that’s good for Python 2 and 3 and preserves white space.

def propercase(s):
    return ''.join(map(''.capitalize, re.split(r'(\s+)', s)))

回答 14

快速功能适用于Python 3

Python 3.6.9 (default, Nov  7 2019, 10:44:02) 
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> capitalizeFirtChar = lambda s: s[:1].upper() + s[1:]
>>> print(capitalizeFirtChar('помните своих Предковъ. Сражайся за Правду и Справедливость!'))
Помните своих Предковъ. Сражайся за Правду и Справедливость!
>>> print(capitalizeFirtChar('хай живе вільна Україна! Хай живе Любовь поміж нас.'))
Хай живе вільна Україна! Хай живе Любовь поміж нас.
>>> print(capitalizeFirtChar('faith and Labour make Dreams come true.'))
Faith and Labour make Dreams come true.

A quick function worked for Python 3

Python 3.6.9 (default, Nov  7 2019, 10:44:02) 
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> capitalizeFirtChar = lambda s: s[:1].upper() + s[1:]
>>> print(capitalizeFirtChar('помните своих Предковъ. Сражайся за Правду и Справедливость!'))
Помните своих Предковъ. Сражайся за Правду и Справедливость!
>>> print(capitalizeFirtChar('хай живе вільна Україна! Хай живе Любовь поміж нас.'))
Хай живе вільна Україна! Хай живе Любовь поміж нас.
>>> print(capitalizeFirtChar('faith and Labour make Dreams come true.'))
Faith and Labour make Dreams come true.

回答 15

用不均匀的空格大写字符串

好吧,我知道这是一个古老的问题,可能答案几乎已经用尽,但我想补充一下@Amit Gupta的非均匀空间。从最初的问题开始,我们想将字符串中的每个单词都大写s = 'the brown fox'。如果字符串的s = 'the brown fox'空格不均匀怎么办。

def solve(s):
    # if you want to maintain the spaces in the string, s = 'the brown      fox'
    # use s.split(' ') instead of s.split(). 
    # s.split() returns ['the', 'brown', 'fox']
    # while s.split(' ') returns ['the', 'brown', '', '', '', '', '', 'fox']
    capitalized_word_list = [word.capitalize() for word in s.split(' ')]
    return ' '.join(capitalized_word_list)

Capitalize string with non-uniform spaces

Well, I understand this is an old question and probably answers may have nearly been exhausited, but I would like to add to @Amit Gupta’s point of non-uniform spaces. From the original question, we would like to capitalize every word in the string s = 'the brown fox'. What if the string was s = 'the brown fox' with non-uniform spaces.

def solve(s):
    # if you want to maintain the spaces in the string, s = 'the brown      fox'
    # use s.split(' ') instead of s.split(). 
    # s.split() returns ['the', 'brown', 'fox']
    # while s.split(' ') returns ['the', 'brown', '', '', '', '', '', 'fox']
    capitalized_word_list = [word.capitalize() for word in s.split(' ')]
    return ' '.join(capitalized_word_list)

回答 16

**如果您想缩小尺寸**

 #Assuming you are opening a new file   
 with open(input_file) as file:
     lines = [x for x in reader(file) if x]
 #for loop to parse the file by line
 for line in lines:
           name = [x.strip().lower() for x in line if x]
           print(name) #check the result

**In case you want to downsize **

 #Assuming you are opening a new file   
 with open(input_file) as file:
     lines = [x for x in reader(file) if x]
 #for loop to parse the file by line
 for line in lines:
           name = [x.strip().lower() for x in line if x]
           print(name) #check the result

回答 17

我真的很喜欢这个答案:

@jibberia anwser的复制粘贴就绪版本:

def capitalize(line):
    return ' '.join([s[0].upper() + s[1:] for s in line.split(' ')])

但是,我发送的某些行拆分了一些空白的”字符,这些字符在尝试执行s [1:]时会导致错误。可能有更好的方法来执行此操作,但是我必须添加if len(s)> 0,例如

return ' '.join([s[0].upper() + s[1:] for s in line.split(' ') if len(s)>0])

I really like this answer:

Copy-paste-ready version of @jibberia anwser:

def capitalize(line):
    return ' '.join([s[0].upper() + s[1:] for s in line.split(' ')])

But some of the lines that I was sending split off some blank ” characters that caused errors when trying to do s[1:]. There is probably a better way to do this, but I had to add in a if len(s)>0, as in

return ' '.join([s[0].upper() + s[1:] for s in line.split(' ') if len(s)>0])

检查Python列表项是否在另一个字符串中包含一个字符串

问题:检查Python列表项是否在另一个字符串中包含一个字符串

我有一个清单:

my_list = ['abc-123', 'def-456', 'ghi-789', 'abc-456']

并要搜索包含字符串的项目'abc'。我怎样才能做到这一点?

if 'abc' in my_list:

会检查是否'abc'存在在列表中,但它的一部分'abc-123''abc-456''abc'对自己不存在。那么,如何获得包含的所有物品'abc'

I have a list:

my_list = ['abc-123', 'def-456', 'ghi-789', 'abc-456']

and want to search for items that contain the string 'abc'. How can I do that?

if 'abc' in my_list:

would check if 'abc' exists in the list but it is a part of 'abc-123' and 'abc-456', 'abc' does not exist on its own. So how can I get all items that contain 'abc' ?


回答 0

如果您只想检查abc列表中是否存在任何字符串,则可以尝试

some_list = ['abc-123', 'def-456', 'ghi-789', 'abc-456']
if any("abc" in s for s in some_list):
    # whatever

如果您确实要获取包含的所有项目abc,请使用

matching = [s for s in some_list if "abc" in s]

If you only want to check for the presence of abc in any string in the list, you could try

some_list = ['abc-123', 'def-456', 'ghi-789', 'abc-456']
if any("abc" in s for s in some_list):
    # whatever

If you really want to get all the items containing abc, use

matching = [s for s in some_list if "abc" in s]

回答 1

只是丢掉它:如果您碰巧需要与多个字符串匹配,例如abcdef,则可以按如下方式组合两种理解:

matchers = ['abc','def']
matching = [s for s in my_list if any(xs in s for xs in matchers)]

输出:

['abc-123', 'def-456', 'abc-456']

Just throwing this out there: if you happen to need to match against more than one string, for example abc and def, you can combine two comprehensions as follows:

matchers = ['abc','def']
matching = [s for s in my_list if any(xs in s for xs in matchers)]

Output:

['abc-123', 'def-456', 'abc-456']

回答 2

使用filter以获取该具备的要素abc

>>> lst = ['abc-123', 'def-456', 'ghi-789', 'abc-456']
>>> print filter(lambda x: 'abc' in x, lst)
['abc-123', 'abc-456']

您还可以使用列表推导。

>>> [x for x in lst if 'abc' in x]

顺便说一句,不要将单词list用作变量名,因为它已经用于list类型。

Use filter to get at the elements that have abc.

>>> lst = ['abc-123', 'def-456', 'ghi-789', 'abc-456']
>>> print filter(lambda x: 'abc' in x, lst)
['abc-123', 'abc-456']

You can also use a list comprehension.

>>> [x for x in lst if 'abc' in x]

By the way, don’t use the word list as a variable name since it is already used for the list type.


回答 3

如果您只想知道’abc’是否在其中一项中,这是最短的方法:

if 'abc' in str(my_list):

If you just need to know if ‘abc’ is in one of the items, this is the shortest way:

if 'abc' in str(my_list):

回答 4

这是一个很老的问题,但是我提供这个答案,因为先前的答案不能解决列表中不是字符串(或某种可迭代对象)的项。这些项目将导致整个列表理解失败,并发生异常。

要通过跳过不可迭代的项目来优雅地处理列表中的此类项目,请使用以下命令:

[el for el in lst if isinstance(el, collections.Iterable) and (st in el)]

然后,带有这样的列表:

lst = [None, 'abc-123', 'def-456', 'ghi-789', 'abc-456', 123]
st = 'abc'

您仍然会得到匹配的项目(['abc-123', 'abc-456']

可迭代的测试可能不是最好的。从这里得到它:在Python中,如何确定对象是否可迭代?

This is quite an old question, but I offer this answer because the previous answers do not cope with items in the list that are not strings (or some kind of iterable object). Such items would cause the entire list comprehension to fail with an exception.

To gracefully deal with such items in the list by skipping the non-iterable items, use the following:

[el for el in lst if isinstance(el, collections.Iterable) and (st in el)]

then, with such a list:

lst = [None, 'abc-123', 'def-456', 'ghi-789', 'abc-456', 123]
st = 'abc'

you will still get the matching items (['abc-123', 'abc-456'])

The test for iterable may not be the best. Got it from here: In Python, how do I determine if an object is iterable?


回答 5

x = 'aaa'
L = ['aaa-12', 'bbbaaa', 'cccaa']
res = [y for y in L if x in y]
x = 'aaa'
L = ['aaa-12', 'bbbaaa', 'cccaa']
res = [y for y in L if x in y]

回答 6

for item in my_list:
    if item.find("abc") != -1:
        print item
for item in my_list:
    if item.find("abc") != -1:
        print item

回答 7

any('abc' in item for item in mylist)
any('abc' in item for item in mylist)

回答 8

使用__contains__()Pythons字符串类的方法:

a = ['abc-123', 'def-456', 'ghi-789', 'abc-456']
for i in a:
    if i.__contains__("abc") :
        print(i, " is containing")

Use the __contains__() method of Pythons string class.:

a = ['abc-123', 'def-456', 'ghi-789', 'abc-456']
for i in a:
    if i.__contains__("abc") :
        print(i, " is containing")

回答 9

我是Python的新手。我得到了下面的代码,使其易于理解:

my_list = ['abc-123', 'def-456', 'ghi-789', 'abc-456']
for str in my_list:
    if 'abc' in str:
       print(str)

I am new to Python. I got the code below working and made it easy to understand:

my_list = ['abc-123', 'def-456', 'ghi-789', 'abc-456']
for str in my_list:
    if 'abc' in str:
       print(str)

回答 10

my_list = ['abc-123', 'def-456', 'ghi-789', 'abc-456']

for item in my_list:
    if (item.find('abc')) != -1:
        print ('Found at ', item)
my_list = ['abc-123', 'def-456', 'ghi-789', 'abc-456']

for item in my_list:
    if (item.find('abc')) != -1:
        print ('Found at ', item)

回答 11

mylist=['abc','def','ghi','abc']

pattern=re.compile(r'abc') 

pattern.findall(mylist)
mylist=['abc','def','ghi','abc']

pattern=re.compile(r'abc') 

pattern.findall(mylist)

回答 12

我进行了搜索,要求您输入某个值,然后它将从包含您的输入的列表中查找一个值:

my_list = ['abc-123',
        'def-456',
        'ghi-789',
        'abc-456'
        ]

imp = raw_input('Search item: ')

for items in my_list:
    val = items
    if any(imp in val for items in my_list):
        print(items)

尝试搜索“ abc”。

I did a search, which requires you to input a certain value, then it will look for a value from the list which contains your input:

my_list = ['abc-123',
        'def-456',
        'ghi-789',
        'abc-456'
        ]

imp = raw_input('Search item: ')

for items in my_list:
    val = items
    if any(imp in val for items in my_list):
        print(items)

Try searching for ‘abc’.


回答 13

def find_dog(new_ls):
    splt = new_ls.split()
    if 'dog' in splt:
        print("True")
    else:
        print('False')


find_dog("Is there a dog here?")
def find_dog(new_ls):
    splt = new_ls.split()
    if 'dog' in splt:
        print("True")
    else:
        print('False')


find_dog("Is there a dog here?")

回答 14

我需要与匹配相对应的列表索引,如下所示:

lst=['abc-123', 'def-456', 'ghi-789', 'abc-456']

[n for n, x in enumerate(lst) if 'abc' in x]

输出

[0, 3]

I needed the list indices that correspond to a match as follows:

lst=['abc-123', 'def-456', 'ghi-789', 'abc-456']

[n for n, x in enumerate(lst) if 'abc' in x]

output

[0, 3]

回答 15

问题:提供abc的信息

    a = ['abc-123', 'def-456', 'ghi-789', 'abc-456']


    aa = [ string for string in a if  "abc" in string]
    print(aa)

Output =>  ['abc-123', 'abc-456']

Question : Give the informations of abc

    a = ['abc-123', 'def-456', 'ghi-789', 'abc-456']


    aa = [ string for string in a if  "abc" in string]
    print(aa)

Output =>  ['abc-123', 'abc-456']

回答 16

据我所知,“ for”陈述总是会浪费时间。

当列表长度增加时,执行时间也会增加。

我认为,使用“ is”语句在字符串中搜索子字符串会更快一些。

In [1]: t = ["abc_%s" % number for number in range(10000)]

In [2]: %timeit any("9999" in string for string in t)
1000 loops, best of 3: 420 µs per loop

In [3]: %timeit "9999" in ",".join(t)
10000 loops, best of 3: 103 µs per loop

但是,我同意该any声明更具可读性。

From my knowledge, a ‘for’ statement will always consume time.

When the list length is growing up, the execution time will also grow.

I think that, searching a substring in a string with ‘is’ statement is a bit faster.

In [1]: t = ["abc_%s" % number for number in range(10000)]

In [2]: %timeit any("9999" in string for string in t)
1000 loops, best of 3: 420 µs per loop

In [3]: %timeit "9999" in ",".join(t)
10000 loops, best of 3: 103 µs per loop

But, I agree that the any statement is more readable.


IndentationError:unindent与任何外部缩进级别都不匹配

问题:IndentationError:unindent与任何外部缩进级别都不匹配

当我编译下面的Python代码时,我得到

IndentationError:unindent与任何外部缩进级别都不匹配


import sys

def Factorial(n): # Return factorial
    result = 1
    for i in range (1,n):
        result = result * i
    print "factorial is ",result
    return result

为什么?

When I compile the Python code below, I get

IndentationError: unindent does not match any outer indentation level


import sys

def Factorial(n): # Return factorial
    result = 1
    for i in range (1,n):
        result = result * i
    print "factorial is ",result
    return result

Why?


回答 0

其他海报可能是正确的…选项卡中可能混有空格。尝试执行搜索和替换操作,以将所有标签替换为几个空格。

尝试这个:

import sys

def Factorial(n): # return factorial
    result = 1
    for i in range (1,n):
        result = result * i
    print "factorial is ",result
    return result

print Factorial(10)

Other posters are probably correct…there might be spaces mixed in with your tabs. Try doing a search & replace to replace all tabs with a few spaces.

Try this:

import sys

def Factorial(n): # return factorial
    result = 1
    for i in range (1,n):
        result = result * i
    print "factorial is ",result
    return result

print Factorial(10)

回答 1

重要说明空格是首选方法 -请参阅PEP008 缩进制表符或空格?。(感谢@Siha。)

对于Sublime Text用户:

设置Sublime Text为使用制表符进行缩进: View-> Indentation->Convert Indentation to Tabs

Indent Using Spaces还要取消选中上面相同子菜单中的选项。这将立即解决此问题。

IMPORTANT: Spaces are the preferred method – see PEP008 Indentation and Tabs or Spaces?. (Thanks to @Siha for this.)

For Sublime Text users:

Set Sublime Text to use tabs for indentation: View –> Indentation –> Convert Indentation to Tabs

Uncheck the Indent Using Spaces option as well in the same sub-menu above. This will immediately resolve this issue.


回答 2

要轻松检查制表符/空格的问题,您可以执行以下操作:

python -m tabnanny yourfile.py

或者您当然可以正确设置编辑器:-)

To easily check for problems with tabs/spaces you can actually do this:

python -m tabnanny yourfile.py

or you can just set up your editor correctly of course :-)


回答 3

您确定不在缩进空格中混用制表符和空格吗?(这将导致该错误。)

请注意,建议您不要在Python代码中使用制表符。请参阅样式指南。您应该配置Notepad ++以便为选项卡插入空格。

Are you sure you are not mixing tabs and spaces in your indentation white space? (That will cause that error.)

Note, it is recommended that you don’t use tabs in Python code. See the style guide. You should configure Notepad++ to insert spaces for tabs.


回答 4

每当遇到此错误时,都是因为我以某种方式混淆了编辑器中的制表符和空格。

Whenever I’ve encountered this error, it’s because I’ve somehow mixed up tabs and spaces in my editor.


回答 5

如果使用Python的IDLE编辑器,则可以按照类似的错误消息之一进行操作:

1)全选,例如Ctrl+A

2)转到格式->取消制表区域

3)仔细检查您的缩进是否仍然正确,保存并重新运行您的程序。

我正在使用Python 2.5.4

If you use Python’s IDLE editor you can do as it suggests in one of similar error messages:

1) select all, e.g. Ctrl + A

2) Go to Format -> Untabify Region

3) Double check your indenting is still correct, save and rerun your program.

I’m using Python 2.5.4


回答 6

如果您使用的是Vim,请按Escape键,然后输入

gg = G

这会自动缩进所有内容,并清除您抛出的所有空格。

If you are using Vim, hit escape and then type

gg=G

This auto indents everything and will clear up any spaces you have thrown in.


回答 7

这行:result = result * i应该缩进(这是for循环的主体)。

或者-您混合使用空格和制表符

The line: result = result * i should be indented (it is the body of the for-loop).

Or – you have mixed space and tab characters


回答 8

原子上

Packages > Whitespace > Convert Spaces to Tabs

然后再次检查您的文件缩进:

python -m tabnanny yourFile.py

要么

>python
>>> help("yourFile.py")

On Atom

go to

Packages > Whitespace > Convert Spaces to Tabs

Then check again your file indentation:

python -m tabnanny yourFile.py

or

>python
>>> help("yourFile.py")

回答 9

看起来是一个缩进问题。你不必匹配在Python大括号,但你必须匹配缩进层次。

防止空格/制表符问题的最佳方法是在文本编辑器中显示不可见的字符。这将为您提供预防和/或解决与缩进相关的错误的快速方法。

同样,注入复制粘贴的代码是此类问题的常见来源。

Looks to be an indentation problem. You don’t have to match curly brackets in Python but you do have to match indentation levels.

The best way to prevent space/tab problems is to display invisible characters within your text editor. This will give you a quick way to prevent and/or resolve indentation-related errors.

Also, injecting copy-pasted code is a common source for this type of problem.


回答 10

如果使用notepad ++,请使用扩展搜索模式“替换”以找到\ t并用四个空格替换。

If you use notepad++, do a “replace” with extended search mode to find \t and replace with four spaces.


回答 11

对于Atom用户,Packages ->whitspace -> remove trailing whitespaces 这对我有用

for Atom Users, Packages ->whitspace -> remove trailing whitespaces this worked for me


回答 12

只是一个补充。我在Notepad ++中的两个缩进都有类似的问题。

  1. 无exceptions的缩进
  2. 外压痕等级

    转到—->搜索选项卡—->点击替换 —->选中单选按钮扩展到下面—>现在用四个空格替换\ t

    转到—->搜索选项卡—->点击替换 —->按下单选按钮扩展到下面—>现在将\ n替换为空

Just a addition. I had a similar problem with the both indentations in Notepad++.

  1. Unexcepted indentation
  2. Outer Indentation Level

    Go to —-> Search tab —-> tap on replace —-> hit the radio button Extended below —> Now replace \t with four spaces

    Go to —-> Search tab —-> tap on replace —-> hit the radio button Extended below —> Now replace \n with nothing


回答 13

我使用的是Jupyter笔记本,尝试了几乎所有上述解决方案(以适应我的情况)为无效。然后,我一行一行地删除了每一行的所有空格,并用tab代替了。那解决了问题。

I was using Jupyter notebook and tried almost all of the above solutions (adapting to my scenario) to no use. I then went line by line, deleted all spaces for each line and replaced with tab. That solved the issue.


回答 14

对于Spyder用户,请 转至源>修复缩进以立即解决问题

For Spyder users goto Source > Fix Indentation to fix the issue immediately


回答 15

可能是因为其上方的函数缩进方式不同。即

class a:
    def blah:
      print("Hello world")
    def blah1:
      print("Hello world")

It could be because the function above it is not indented the same way. i.e.

class a:
    def blah:
      print("Hello world")
    def blah1:
      print("Hello world")

回答 16

昨天我遇到了同样的问题,这是缩进错误,正在使用崇高的文本编辑器。花了我几个小时的时间来修复它,最后我最终将代码复制到VI文本编辑器中,并且运行良好。ps python对空格太敏感,请确保不要混合使用空格和制表符。

I had the same issue yesterday, it was indentation error, was using sublime text editor. took my hours trying to fix it and at the end I ended up copying the code into VI text editor and it just worked fine. ps python is too whitespace sensitive, make sure not to mix space and tab.


回答 17

因为我意识到没有特定的答案spyder,所以我将添加一个答案:基本上,仔细查看您的if声明并确保全部ifelifelse具有相同的间距,即它们在开始时位于同一行,如下所示:

def your_choice(answer):
    if answer>5:
        print("You're overaged")
    elif answer<=5 and answer>1: 
            print("Welcome to the toddler's club!")
    else:
            print("No worries mate!")

Since I realize there’s no answer specific to spyder,I’ll add one: Basically, carefully look at your if statement and make sure all if, elif and else have the same spacing that is they’re in the same line at the start like so:

def your_choice(answer):
    if answer>5:
        print("You're overaged")
    elif answer<=5 and answer>1: 
            print("Welcome to the toddler's club!")
    else:
            print("No worries mate!")

回答 18

我定义了一个函数,但除了函数注释外,它没有任何内容

def foo(bar):
    # Some awesome temporary comment.
    # But there is actually nothing in the function!
    # D'Oh!

大喊:

  File "foobar.py", line 69

                                ^
IndentationError: expected an indented block

(请注意,^标记指向的行为空)

多种解决方案:

1:仅将功能注释掉

2:添加功能注释

def foo(bar):
    '' Some awesome comment. This comment could be just one space.''

3:添加不执行任何操作的行

def foo(bar):
    0

在任何情况下,请务必使其明显的 ,为什么它是一个空的功能-为自己,或您的同事将使用代码

I had a function defined, but it did not had any content apart from its function comments…

def foo(bar):
    # Some awesome temporary comment.
    # But there is actually nothing in the function!
    # D'Oh!

It yelled :

  File "foobar.py", line 69

                                ^
IndentationError: expected an indented block

(note that the line the ^ mark points to is empty)

Multiple solutions:

1: Just comment out the function

2: Add function comment

def foo(bar):
    '' Some awesome comment. This comment could be just one space.''

3: Add line that does nothing

def foo(bar):
    0

In any case, make sure to make it obvious why it is an empty function – for yourself, or for your peers that will use your code


回答 19

首先,只是提醒您有一个逻辑错误,您最好保持result = 1,否则即使在循环运行后,您的输出也将为result = 0。

其次,您可以这样编写:

import sys

def Factorial(n): # Return factorial
  result = 0
  for i in range (1,n):
     result = result * i

  print "factorial is ",result
  return result

留下一行将告诉python shell FOR语句已经结束。如果您有使用python shell的经验,那么您可以理解为什么我们必须行。

Firstly, just to remind you there is a logical error you better keep result=1 or else your output will be result=0 even after the loop runs.

Secondly you can write it like this:

import sys

def Factorial(n): # Return factorial
  result = 0
  for i in range (1,n):
     result = result * i

  print "factorial is ",result
  return result

Leaving a line will tell the python shell that the FOR statements have ended. If you have experience using the python shell then you can understand why we have to leave a line.


回答 20

对于它的价值,我的文档字符串缩进太多,这也引发了相同的错误

class junk: 
     """docstring is indented too much""" 
    def fun(): return   

IndentationError: unindent does not match any outer indentation level

For what its worth, my docstring was indented too much and this also throws the same error

class junk: 
     """docstring is indented too much""" 
    def fun(): return   

IndentationError: unindent does not match any outer indentation level


回答 21

这是因为制表符和空格混在一起。您可以删除所有空格,然后将其替换为制表符。

或者,尝试编写以下代码:

#!/usr/bin/python -tt

在代码的开头。此行解决了制表符和空格之间的所有差异。

This is because there is a mix-up of both tabs and spaces. You can either remove all the spaces and replace them with tabs.

Or, Try writing this:

#!/usr/bin/python -tt

at the beginning of the code. This line resolves any differences between tabs and spaces.


回答 22

就我而言,问题是在Eclipse上配置pydev

in my case, the problem was the configuration of pydev on Eclipse


回答 23

如果使用Komodo编辑器,则可以按照以下类似错误消息之一的建议进行操作:

1)全选,例如Ctrl + A

2)转到代码->取消制表区域

3)仔细检查您的缩进是否仍然正确,保存并重新运行您的程序。

我正在使用Python 3.4.2

If you use Komodo editor you can do as it suggests in one of similar error messages:

1) select all, e.g. Ctrl + A

2) Go to Code -> Untabify Region

3) Double check your indenting is still correct, save and rerun your program.

I’m using Python 3.4.2


回答 24

如果您将Sublime文本用于python开发,则可以使用Anaconda软件包来避免该错误。安装Anaconda后,

  1. 崇高地打开文件
  2. 右键单击开放空间
  3. 选择水蟒
  4. 点击自动格式化
  5. 完成或按CTRL + ALT + R。

If you are using Sublime text for python development,you can avoid the error by using the package Anaconda.After installing Anaconda,

  1. open your file in sublime
  2. right click on the open spaces
  3. choose anaconda
  4. click on autoformat
  5. DONE Or Press CTRL+ALT+R.

回答 25

在具有python插件的intellij中,按Ctrl + Shift + Alt重新格式化文档可解决缩进/制表符/空格问题

In intellij with python plugin, Ctrl + Shift + Alt to reformat the document fixed the indent/tab/spaces problem


回答 26

对于SPYDER用户:我将spyder 3.3.2与python 3.7.1结合使用,并解决了此问题,将缩进设置为使用选项卡,并通过以下步骤单击:

  • 工具。
  • 偏好。
  • 编辑。
  • 高级设置。
  • 缩进字符->制表符。

然后,使用Tab键重置“ unidented”行。

由于某种原因,如果没有此设置,有时会出现幽灵 IndentationError。

For SPYDER users: I’m using spyder 3.3.2 with python 3.7.1 and I solved this, setting indentation to use tabs, with the following steps, click on:

  • Tools.
  • Preferences.
  • Editor.
  • Advanced settings.
  • Indentation characters -> Tabs.

Then I reset the “unidented” line using tab key.

For some reason, without this setting, I got the ghost IndentationError sometimes.


回答 27

例如:

1. def convert_distance(miles):
2.   km = miles * 1.6
3.   return km

在这段代码中,我也遇到了同样的情况。只需删除第2行和第3行的先前缩进空格,然后使用tab或空格即可。切勿同时使用两者。在用python编写代码时,给出适当的缩进。对于Spyder,请转至源>修复缩进。VC代码和崇高文本或任何其他编辑器也是如此。修复缩进。

For example:

1. def convert_distance(miles):
2.   km = miles * 1.6
3.   return km

In this code same situation occurred for me. Just delete the previous indent spaces of line 2 and 3, and then either use tab or space. Never use both. Give proper indentation while writing code in python. For Spyder goto Source > Fix Indentation. Same goes to VC Code and sublime text or any other editor. Fix the indentation.


回答 28

发生这种情况的主要原因是编辑器。尝试将选项卡更改为spaces(4)。最佳的Python友好IDE或编辑器是pycharm,sublime,vim(对于Linux)。
即使我也遇到过同样的问题,后来我发现还有一个编码问题。我建议您也更改您的编辑器。

This happens mainly because of editor .Try changing tabs to spaces(4).the best python friendly IDE or Editors are pycharm ,sublime ,vim for linux.
even i too had encountered the same issue , later i found that there is a encoding issue .i suggest u too change ur editor.


Python:在列表中查找

问题:Python:在列表中查找

我遇到了这个:

item = someSortOfSelection()
if item in myList:
    doMySpecialFunction(item)

但有时它不适用于我的所有物品,好像它们在列表中没有被识别(当它是字符串列表时)。

这是在列表中查找项目的最“ pythonic”方式if x in l:吗?

I have come across this:

item = someSortOfSelection()
if item in myList:
    doMySpecialFunction(item)

but sometimes it does not work with all my items, as if they weren’t recognized in the list (when it’s a list of string).

Is this the most ‘pythonic’ way of finding an item in a list: if x in l:?


回答 0

关于您的第一个问题:该代码非常好,并且如果与item其中的一个元素相等就应该可以工作myList。也许您尝试找到与其中一项不完全匹配的字符串,或者您使用的浮点值会导致不正确。

至于第二个问题:如果“查找”列表中的内容,实际上有几种可能的方法。

检查里面是否有东西

这是您描述的用例:检查列表中是否包含某些内容。如您所知,您可以使用in运算符:

3 in [1, 2, 3] # => True

过滤集合

即,找到满足特定条件的序列中的所有元素。您可以为此使用列表推导或生成器表达式:

matches = [x for x in lst if fulfills_some_condition(x)]
matches = (x for x in lst if x > 6)

后者将返回一个生成器,您可以将其想象为一种懒惰列表,该列表只有在您对其进行迭代时才会被构建。顺便说一句,第一个完全等于

matches = filter(fulfills_some_condition, lst)

在Python 2中。在这里您可以看到工作中的高阶函数。在Python 3中,filter不返回列表,而是返回类似生成器的对象。

寻找第一次出现

如果您只想匹配条件的第一件事(但是您还不知道它是什么),那么可以使用for循环(可能也使用该else子句,这并不是很知名)。您也可以使用

next(x for x in lst if ...)

StopIteration如果没有找到任何匹配项,则将返回第一个匹配项或引发a 。或者,您可以使用

next((x for x in lst if ...), [default value])

查找物品的位置

对于列表,index如果您想知道某个元素在列表中的何处,还有一种方法有时会很有用:

[1,2,3].index(2) # => 1
[1,2,3].index(4) # => ValueError

但是,请注意,如果有重复项,则.index始终返回最低索引:……

[1,2,3,2].index(2) # => 1

如果有重复项,并且想要所有索引,则可以enumerate()改用:

[i for i,x in enumerate([1,2,3,2]) if x==2] # => [1, 3]

As for your first question: that code is perfectly fine and should work if item equals one of the elements inside myList. Maybe you try to find a string that does not exactly match one of the items or maybe you are using a float value which suffers from inaccuracy.

As for your second question: There’s actually several possible ways if “finding” things in lists.

Checking if something is inside

This is the use case you describe: Checking whether something is inside a list or not. As you know, you can use the in operator for that:

3 in [1, 2, 3] # => True

Filtering a collection

That is, finding all elements in a sequence that meet a certain condition. You can use list comprehension or generator expressions for that:

matches = [x for x in lst if fulfills_some_condition(x)]
matches = (x for x in lst if x > 6)

The latter will return a generator which you can imagine as a sort of lazy list that will only be built as soon as you iterate through it. By the way, the first one is exactly equivalent to

matches = filter(fulfills_some_condition, lst)

in Python 2. Here you can see higher-order functions at work. In Python 3, filter doesn’t return a list, but a generator-like object.

Finding the first occurrence

If you only want the first thing that matches a condition (but you don’t know what it is yet), it’s fine to use a for loop (possibly using the else clause as well, which is not really well-known). You can also use

next(x for x in lst if ...)

which will return the first match or raise a StopIteration if none is found. Alternatively, you can use

next((x for x in lst if ...), [default value])

Finding the location of an item

For lists, there’s also the index method that can sometimes be useful if you want to know where a certain element is in the list:

[1,2,3].index(2) # => 1
[1,2,3].index(4) # => ValueError

However, note that if you have duplicates, .index always returns the lowest index:……

[1,2,3,2].index(2) # => 1

If there are duplicates and you want all the indexes then you can use enumerate() instead:

[i for i,x in enumerate([1,2,3,2]) if x==2] # => [1, 3]

回答 1

如果要查找一个元素或在中None使用default next,则StopIteration在列表中未找到该元素时不会提高:

first_or_default = next((x for x in lst if ...), None)

If you want to find one element or None use default in next, it won’t raise StopIteration if the item was not found in the list:

first_or_default = next((x for x in lst if ...), None)

回答 2

虽然Niklas B.的答案非常全面,但是当我们想在列表中查找某项时,有时获得其索引很有用:

next((i for i, x in enumerate(lst) if [condition on x]), [default value])

While the answer from Niklas B. is pretty comprehensive, when we want to find an item in a list it is sometimes useful to get its index:

next((i for i, x in enumerate(lst) if [condition on x]), [default value])

回答 3

寻找第一次出现

在其中有一个配方itertools

def first_true(iterable, default=False, pred=None):
    """Returns the first true value in the iterable.

    If no true value is found, returns *default*

    If *pred* is not None, returns the first item
    for which pred(item) is true.

    """
    # first_true([a,b,c], x) --> a or b or c or x
    # first_true([a,b], x, f) --> a if f(a) else b if f(b) else x
    return next(filter(pred, iterable), default)

例如,以下代码查找列表中的第一个奇数:

>>> first_true([2,3,4,5], None, lambda x: x%2==1)
3  

Finding the first occurrence

There’s a recipe for that in itertools:

def first_true(iterable, default=False, pred=None):
    """Returns the first true value in the iterable.

    If no true value is found, returns *default*

    If *pred* is not None, returns the first item
    for which pred(item) is true.

    """
    # first_true([a,b,c], x) --> a or b or c or x
    # first_true([a,b], x, f) --> a if f(a) else b if f(b) else x
    return next(filter(pred, iterable), default)

For example, the following code finds the first odd number in a list:

>>> first_true([2,3,4,5], None, lambda x: x%2==1)
3  

回答 4

另一种选择:您可以使用来检查项目是否在列表中if item in list:,但这是订单O(n)。如果您要处理大量项目,而您只需要知道某项是否是列表的成员,则可以先将列表转换为集合,然后利用恒定时间集查找

my_set = set(my_list)
if item in my_set:  # much faster on average than using a list
    # do something

并非在每种情况下都是正确的解决方案,但是在某些情况下,这可能会为您带来更好的性能。

请注意,使用来创建集合set(my_list)也是O(n),因此,如果您只需要执行一次此操作,则以这种方式进行操作不会更快。但是,如果您需要反复检查成员资格,则在初始集创建之后,每次查找将为O(1)。

Another alternative: you can check if an item is in a list with if item in list:, but this is order O(n). If you are dealing with big lists of items and all you need to know is whether something is a member of your list, you can convert the list to a set first and take advantage of constant time set lookup:

my_set = set(my_list)
if item in my_set:  # much faster on average than using a list
    # do something

Not going to be the correct solution in every case, but for some cases this might give you better performance.

Note that creating the set with set(my_list) is also O(n), so if you only need to do this once then it isn’t any faster to do it this way. If you need to repeatedly check membership though, then this will be O(1) for every lookup after that initial set creation.


回答 5

在处理字符串列表时,您可能想使用两种可能的搜索之一:

  1. 如果list元素等于一个项目(’example’在[‘one’,’example’,’two’]中):

    if item in your_list: some_function_on_true()

    [‘one’,’ex’,’two’]中的’ex’=>真

    [‘one’,’ex’,’two’]中的’ex_1’=>否

  2. 如果list元素就像一个项目(“ ex”在[‘one,’example’,’two’]中,或者’example_1’在[‘one’,’example’,’two’]中):

    matches = [el for el in your_list if item in el]

    要么

    matches = [el for el in your_list if el in item]

    然后只需要检查len(matches)或阅读即可。

You may want to use one of two possible searches while working with list of strings:

  1. if list element is equal to an item (‘example’ is in [‘one’,’example’,’two’]):

    if item in your_list: some_function_on_true()

    ‘ex’ in [‘one’,’ex’,’two’] => True

    ‘ex_1’ in [‘one’,’ex’,’two’] => False

  2. if list element is like an item (‘ex’ is in [‘one,’example’,’two’] or ‘example_1’ is in [‘one’,’example’,’two’]):

    matches = [el for el in your_list if item in el]

    or

    matches = [el for el in your_list if el in item]

    then just check len(matches) or read them if needed.


回答 6

定义和用法

count()方法返回具有指定值的元素数。

句法

list.count(value)

例:

fruits = ['apple', 'banana', 'cherry']

x = fruits.count("cherry")

问题的例子:

item = someSortOfSelection()

if myList.count(item) >= 1 :

    doMySpecialFunction(item)

Definition and Usage

the count() method returns the number of elements with the specified value.

Syntax

list.count(value)

example:

fruits = ['apple', 'banana', 'cherry']

x = fruits.count("cherry")

Question’s example:

item = someSortOfSelection()

if myList.count(item) >= 1 :

    doMySpecialFunction(item)

回答 7

而不是使用的list.index(x)如果在列表中找到返回x的指数或返回#ValueError,如果没有找到X,你可以使用邮件list.count(x)返回列表x的发生次数(验证x是确实在列表中),或者它否则返回0(在没有x的情况下)。有趣的count()是,它不会破坏您的代码,也不会要求您在找不到x时抛出异常

Instead of using list.index(x) which returns the index of x if it is found in list or returns a #ValueError message if x is not found, you could use list.count(x) which returns the number of occurrences of x in list (validation that x is indeed in the list) or it returns 0 otherwise (in the absence of x). The cool thing about count() is that it doesn’t break your code or require you to throw an exception for when x is not found


回答 8

如果您要检查一次收藏品中是否存在值,则可以使用“ in”运算符。但是,如果要检查一次以上,则建议使用bisect模块。请记住,使用bisect模块的数据必须进行排序。因此,您可以对数据进行一次排序,然后可以使用二等分。在我的机器上使用bisect模块比使用“ in”运算符快12倍。

这是使用Python 3.8及更高版本语法的代码示例:

import bisect
from timeit import timeit

def bisect_search(container, value):
    return (
      (index := bisect.bisect_left(container, value)) < len(container) 
      and container[index] == value
    )

data = list(range(1000))
# value to search
true_value = 666
false_value = 66666

# times to test
ttt = 1000

print(f"{bisect_search(data, true_value)=} {bisect_search(data, false_value)=}")

t1 = timeit(lambda: true_value in data, number=ttt)
t2 = timeit(lambda: bisect_search(data, true_value), number=ttt)

print("Performance:", f"{t1=:.4f}, {t2=:.4f}, diffs {t1/t2=:.2f}")

输出:

bisect_search(data, true_value)=True bisect_search(data, false_value)=False
Performance: t1=0.0220, t2=0.0019, diffs t1/t2=11.71

If you are going to check if value exist in the collectible once then using ‘in’ operator is fine. However, if you are going to check for more than once then I recommend using bisect module. Keep in mind that using bisect module data must be sorted. So you sort data once and then you can use bisect. Using bisect module on my machine is about 12 times faster than using ‘in’ operator.

Here is an example of code using Python 3.8 and above syntax:

import bisect
from timeit import timeit

def bisect_search(container, value):
    return (
      (index := bisect.bisect_left(container, value)) < len(container) 
      and container[index] == value
    )

data = list(range(1000))
# value to search
true_value = 666
false_value = 66666

# times to test
ttt = 1000

print(f"{bisect_search(data, true_value)=} {bisect_search(data, false_value)=}")

t1 = timeit(lambda: true_value in data, number=ttt)
t2 = timeit(lambda: bisect_search(data, true_value), number=ttt)

print("Performance:", f"{t1=:.4f}, {t2=:.4f}, diffs {t1/t2=:.2f}")

Output:

bisect_search(data, true_value)=True bisect_search(data, false_value)=False
Performance: t1=0.0220, t2=0.0019, diffs t1/t2=11.71

回答 9

检查字符串列表中的项目是否没有其他多余的空格。这就是可能无法解释项目的原因。

Check there are no additional/unwanted whites space in the items of the list of strings. That’s a reason that can be interfering explaining the items cannot be found.


ImportError:没有名为请求的模块

问题:ImportError:没有名为请求的模块

每当我尝试导入时requests,都会出现错误提示No module Named requests

import requests

我得到的错误:

File "ex2.py", line 1, in <module>
    import requests
ImportError: No module named requests

Whenever I try to import requests, I get an error saying No module Named requests.

import requests

The error I get:

File "ex2.py", line 1, in <module>
    import requests
ImportError: No module named requests

回答 0

Requests不是内置模块(默认的python安装不附带),因此您必须安装它:

OSX / Linux

如果已安装,请使用$ sudo pip install requests(或pip3 install requests用于python3) pip。如果pip已安装但不在您的路径中,则可以使用python -m pip install requests(或python3 -m pip install requests用于python3)

或者,sudo easy_install -U requests如果已easy_install安装,也可以使用。

另外,您可以使用系统软件包管理器:

对于centos:yum install python-requests 对于Ubuntu:apt-get install python-requests

视窗

如果已安装Pip.exe并将其添加到Path Environment Variable中,请使用pip install requests(或pip3 install requests用于python3) pip。如果pip已安装但不在您的路径中,则可以使用python -m pip install requests(或python3 -m pip install requests用于python3)

或者从命令提示符,使用> Path\easy_install.exe requests,这里Path是你的Python*\Scripts文件夹,如果安装它。(例如:C:\Python32\Scripts

如果您要手动将库添加到Windows计算机,则可以下载压缩的库,解压缩它,然后将其放入Lib\site-packagespython路径的文件夹中。(例如:C:\Python27\Lib\site-packages

从来源(通用)

对于任何缺少的库,通常可从https://pypi.python.org/pypi/获得该源。您可以在此处下载请求:https//pypi.python.org/pypi/requests

在Mac OS X和Windows上,下载源zip后,解压缩它,并从未python setup.py install压缩的dir 的termiminal / cmd中运行。

来源

Requests is not a built in module (does not come with the default python installation), so you will have to install it:

OSX/Linux

Use $ sudo pip install requests (or pip3 install requests for python3) if you have pip installed. If pip is installed but not in your path you can use python -m pip install requests (or python3 -m pip install requests for python3)

Alternatively you can also use sudo easy_install -U requests if you have easy_install installed.

Alternatively you can use your systems package manager:

For centos: yum install python-requests For Ubuntu: apt-get install python-requests

Windows

Use pip install requests (or pip3 install requests for python3) if you have pip installed and Pip.exe added to the Path Environment Variable. If pip is installed but not in your path you can use python -m pip install requests (or python3 -m pip install requests for python3)

Alternatively from a cmd prompt, use > Path\easy_install.exe requests, where Path is your Python*\Scripts folder, if it was installed. (For example: C:\Python32\Scripts)

If you manually want to add a library to a windows machine, you can download the compressed library, uncompress it, and then place it into the Lib\site-packages folder of your python path. (For example: C:\Python27\Lib\site-packages)

From Source (Universal)

For any missing library, the source is usually available at https://pypi.python.org/pypi/. You can download requests here: https://pypi.python.org/pypi/requests

On mac osx and windows, after downloading the source zip, uncompress it and from the termiminal/cmd run python setup.py install from the uncompressed dir.

(source)


回答 1

对我而言,您使用的是哪个版本的Python并不明显。

如果是Python 3,一个解决方案是 sudo pip3 install requests

It’s not obvious to me which version of Python you are using.

If it’s Python 3, a solution would be sudo pip3 install requests


回答 2

requests在适用于Python2的Debian / Ubuntu上安装模块:

$ sudo apt-get install python-requests

对于Python3,命令为:

$ sudo apt-get install python3-requests

To install requests module on Debian/Ubuntu for Python2:

$ sudo apt-get install python-requests

And for Python3 the command is:

$ sudo apt-get install python3-requests


回答 3

如果您使用的是Ubuntu,则需要安装 requests

运行以下命令:

pip install requests

如果遇到权限被拒绝的错误,请在命令前使用sudo:

sudo pip install requests

If you are using Ubuntu, there is need to install requests

run this command:

pip install requests

if you face permission denied error, use sudo before command:

sudo pip install requests

回答 4

这可能为时已晚,但是即使未设置pip path,也可以运行此命令。我正在Windows 10上运行Python 3.7,这是命令

py -m pip install requests

并且您还可以将“ requests”替换为任何其他已卸载的库

This may be a liittle bit too late but this command can be run even when pip path is not set. I am using Python 3.7 running on Windows 10 and this is the command

py -m pip install requests

and you can also replace ‘requests’ with any other uninstalled library


回答 5

在OSX上,该命令将取决于您安装的python的风格。

Python 2.x-默认

sudo pip install requests

Python 3.x

sudo pip3 install requests

On OSX, the command will depend on the flavour of python installation you have.

Python 2.x – Default

sudo pip install requests

Python 3.x

sudo pip3 install requests

回答 6

就我而言,请求已经安装,但需要升级。以下命令可以解决问题

$ sudo pip install requests --upgrade

In my case requests was already installed, but needed an upgrade. The following command did the trick

$ sudo pip install requests --upgrade

回答 7

在Windows打开命令行上

pip3 install requests

On Windows Open Command Line

pip3 install requests

回答 8

我遇到了同样的问题,所以我从https://pypi.python.org/pypi/requests#downloads 请求下载文件夹中将名为“ requests”的文件夹复制到“ /Library/Python/2.7/site-packages”。现在,当您使用:导入请求时,它应该可以正常工作。

I had the same issue, so I copied the folder named “requests” from https://pypi.python.org/pypi/requests#downloadsrequests download to “/Library/Python/2.7/site-packages”. Now when you use: import requests, it should work fine.


回答 9

Brew用户可以使用下面的参考,

安装请求的命令:

python3 -m pip install requests

自制软件和Python

pip是Python的软件包安装程序,您需要该软件包requests

Brew users can use reference below,

command to install requests:

python3 -m pip install requests

Homebrew and Python

pip is the package installer for Python and you need the package requests.


回答 10

向应用程序添加第三方程序包

跟随此链接 https://cloud.google.com/appengine/docs/python/tools/libraries27?hl=zh_CN#vendoring

步骤1:在项目的根目录中有一个名为appengine_config.py的文件,然后添加以下行:

从google.appengine.ext导入供应商

添加安装在“ lib”文件夹中的所有库。

vendor.add(’lib’)

步骤2:创建一个目录,并将其命名为project的根目录下的“ lib”。

步骤3:使用pip install -t lib请求

第4步:部署到App Engine。

Adding Third-party Packages to the Application

Follow this link https://cloud.google.com/appengine/docs/python/tools/libraries27?hl=en#vendoring

step1 : Have a file by named a file named appengine_config.py in the root of your project, then add these lines:

from google.appengine.ext import vendor

Add any libraries installed in the “lib” folder.

vendor.add(‘lib’)

Step 2: create a directory and name it “lib” under root directory of project.

step 3: use pip install -t lib requests

step 4 : deploy to app engine.


回答 11

尝试sudo apt-get install python-requests

这对我有用。

Try sudo apt-get install python-requests.

This worked for me.


回答 12

对于Windows,只需将路径指定为cd,然后将路径指定为python的“脚本”,然后执行命令easy_install.exe请求即可。然后尝试导入请求…

For windows just give path as cd and path to the “Scripts” of python and then execute the command easy_install.exe requests.Then try import requests…


回答 13

唯一对我有用的东西:

curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
python get-pip.py
pip install requests

The only thing that worked for me:

curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
python get-pip.py
pip install requests

回答 14

在过去的几个月中,我有几次遇到这个问题。我还没有看到针对fedora系统的好的解决方案,因此这里是另一个解决方案。我正在使用RHEL7,发现了以下内容:

如果您urllib3通过进行了安装pip,并且requests通过进行了安装yum,则即使安装了正确的软件包,也会出现问题。如果您urllib3通过yumrequests安装了,则同样适用pip。这是我为解决此问题所做的工作:

sudo pip uninstall requests
sudo pip uninstall urllib3
sudo yum remove python-urllib3
sudo yum remove python-requests

(确认已删除所有这些库)

sudo yum install python-urllib3
sudo yum install python-requests

请注意,这仅适用于运行Fedora,Redhat或CentOS的系统。

资料来源:
这个问题(在答案的评论中)。
这个 github问题。

I have had this issue a couple times in the past few months. I haven’t seen a good solution for fedora systems posted, so here’s yet another solution. I’m using RHEL7, and I discovered the following:

If you have urllib3 installed via pip, and requests installed via yum you will have issues, even if you have the correct packages installed. The same will apply if you have urllib3 installed via yum, and requests installed via pip. Here’s what I did to fix the issue:

sudo pip uninstall requests
sudo pip uninstall urllib3
sudo yum remove python-urllib3
sudo yum remove python-requests

(confirm that all those libraries have been removed)

sudo yum install python-urllib3
sudo yum install python-requests

Just be aware that this will only work for systems that are running Fedora, Redhat, or CentOS.

Sources:
This very question (in the comments to this answer).
This github issue.


回答 15

我已经安装了python2.7和python3.6

打开〜/ .bash_profile的命令行, 我发现#Setting Python 3.6的PATH,所以我将路径更改为PATH =“ / usr / local / Cellar / python / 2.7.13 / bin:$ {PATH}”,(请确保您的python2.7的路径),然后保存。这个对我有用。

I have installed python2.7 and python3.6

Open Command Line to ~/.bash_profile I find that #Setting PATH for Python 3.6 , So I change the path to PATH=”/usr/local/Cellar/python/2.7.13/bin:${PATH}” , (please make sure your python2.7’s path) ,then save. It works for me.


回答 16

如果要request在Windows上导入:

pip install request

然后beautifulsoup4用于:

pip3 install beautifulsoup4

if you want request import on windows:

pip install request

then beautifulsoup4 for:

pip3 install beautifulsoup4

回答 17

我解决了这个问题。您可以尝试这种方法。在此文件“ .bash_profile”中,添加类似alias python=/Library/Frameworks/Python.framework/Versions/2.7/bin/python2.7

I solved this problem.You can try this method. In this file ‘.bash_profile’, Add codes like alias python=/Library/Frameworks/Python.framework/Versions/2.7/bin/python2.7


回答 18

如果您将anaconda用作Python软件包管理器,请执行以下操作:

conda install -c anaconda requests

通过pip安装请求对我没有帮助。

If you are using anaconda as your python package manager, execute the following:

conda install -c anaconda requests

Installing requests through pip didn’t help me.


回答 19

您必须确保您的请求模块未安装在最新版本的python中。

使用python 3.7时,请像这样运行python文件:

python3 myfile.py

或使用以下命令进入python交互模式:

python3

是的,这对我有用。像这样运行文件:python3 file.py

You must make sure your requests module is not being installed in a more recent version of python.

When using python 3.7, run your python file like:

python3 myfile.py

or enter python interactive mode with:

python3

Yes, this works for me. Run your file like this: python3 file.py


回答 20

Python 常见安装问题

如果Homebrew在macOS上修改了路径,这些命令也很有用。

python -m pip install requests

要么

python3 -m pip install requests

并行安装多个版本的Python?

Python Common installation issues

These commands are also useful if Homebrew screws up your path on macOS.

python -m pip install requests

or

python3 -m pip install requests

Multiple versions of Python installed in parallel?


回答 21

我的答案与@ pi-k基本相同。就我而言,我的程序在本地运行,但无法在质量检查服务器上构建。(我怀疑devops阻止了该软件包的旧版本,而且我的版本肯定已经过时了)我只是决定升级所有内容

$ pip install pip-review
$ pip-review --local --interactive

My answer is basically the same as @pi-k. In my case my program worked locally but failed to build on QA servers. (I suspect devops had older versions of the package blocked and my version must have been too out-of-date) I just decided to upgrade everything

$ pip install pip-review
$ pip-review --local --interactive

回答 22

如果您使用的是anaconda 步骤1:python 步骤2:在管理员模式下打开anaconda提示 步骤3:cd < python path > 步骤4:在此位置安装软件包

If you are using anaconda step 1: where python step 2: open anaconda prompt in administrator mode step 3: cd <python path> step 4: install the package in this location


回答 23

就我而言,这表明请求Requirement已经满足。所以我用。

sudo pip3 install requests

In my case it was showing request Requirement already satisfied . so I use.

sudo pip3 install requests

回答 24

pycharm IDE中

从菜单中的文件一键设置

2-接下来进行Python解释器

3点子

4-搜索请求并安装

在终端pycharm中写入此命令

pip install requests 

并通过以下方式使用:

import requests

in pycharm IDE

1-go to setting from File in menu

2-next go on Python interpreter

3-click on pip

4- search for requests and install it

or write this order in terminal pycharm

pip install requests 

and use it by :

import requests

回答 25

我的问题是我有四个尝试使用的python不同的python库(即使我显式调用了/usr/bin/python)。一旦我从路径中删除了shell别名和另外两个python,/usr/bin/python就可以了import requests

-HTH

My problem was that I had four different python libraries that python was trying to use (even though I was explicitly calling /usr/bin/python). Once I removed a shell alias and two other pythons from my path, /usr/bin/python was able to import requests.

-HTH


回答 26

问题可能是由于一台计算机具有多个版本的Python。确保要安装所有版本的请求模块。

就我而言,我有python版本2.73.7。我通过同时安装两个版本的python解决了此问题

The issue could be because of a machine having multiple versions of Python. Make sure that you are installing Request modules in all the versions.

In my case, I had python version 2.7 and 3.7. I resolved this issue by installing with both versions of python


回答 27

试试这个,我已经安装了anaconda,在阅读了很多文章之后,我发现这是一个解决方法

import sys
print(sys.version)
print("\n \n")
print(sys.path)
sys.path.append('/usr/local/anaconda3/envs/py36/lib/python3.6/site-packages')

在python_version文件夹中提供站点包的路径。

Try this I have anaconda installed and after going through a lot of articles I found this as a fix

import sys
print(sys.version)
print("\n \n")
print(sys.path)
sys.path.append('/usr/local/anaconda3/envs/py36/lib/python3.6/site-packages')

Provide the path of site-packages inside python_version folder.


回答 28

也许您安装了多个版本的python。尝试使用其他版本(例如python3.7 xxx.py)来确定哪个版本正确。

Maybe you have multiple versions of python installed. Try different versions, such as python3.7 xxx.py, to identify which one is the right version.


回答 29

您还可以通过首先在目录中找到pip3.exe文件在Windows上使用pip安装:对我说==> cd c:\ python34 \ scripts然后运行==> pip3安装请求

you can also use pip install on windows by first locating the pip3.exe file in the directory: say for me==> cd c:\python34\scripts then run ==> pip3 install requests


Python try-else

问题:Python try-else

语句的可选else子句的预期用途是try什么?

What is the intended use of the optional else clause of the try statement?


回答 0

else如果执行不符合try-如果没有exceptions,则执行块中的语句。老实说,我从来没有发现需要。

但是,“ 处理异常”指出:

使用else子句比向try子句添加其他代码更好,因为它避免了意外捕获try … except语句保护的代码未引发的异常。

所以,如果你有一个方法可以,例如,抛出IOError了,你想抓住它会引发异常,但有你想,如果第一个操作成功做其它的事情,你不要想抓住从一个IOError该操作,您可能会这样写:

try:
    operation_that_can_throw_ioerror()
except IOError:
    handle_the_exception_somehow()
else:
    # we don't want to catch the IOError if it's raised
    another_operation_that_can_throw_ioerror()
finally:
    something_we_always_need_to_do()

如果仅放在another_operation_that_can_throw_ioerror()之后operation_that_can_throw_ioerrorexcept则将捕获第二个调用的错误。并且,如果将其放在整个代码try块之后,它将始终运行,直到finally。将else让您确保

  1. 只有在没有exceptions的情况下,第二个操作才会运行
  2. 它在代码finally块之前运行,并且
  3. IOError它筹集到的任何钱都没有被抓住

The statements in the else block are executed if execution falls off the bottom of the try – if there was no exception. Honestly, I’ve never found a need.

However, Handling Exceptions notes:

The use of the else clause is better than adding additional code to the try clause because it avoids accidentally catching an exception that wasn’t raised by the code being protected by the try … except statement.

So, if you have a method that could, for example, throw an IOError, and you want to catch exceptions it raises, but there’s something else you want to do if the first operation succeeds, and you don’t want to catch an IOError from that operation, you might write something like this:

try:
    operation_that_can_throw_ioerror()
except IOError:
    handle_the_exception_somehow()
else:
    # we don't want to catch the IOError if it's raised
    another_operation_that_can_throw_ioerror()
finally:
    something_we_always_need_to_do()

If you just put another_operation_that_can_throw_ioerror() after operation_that_can_throw_ioerror, the except would catch the second call’s errors. And if you put it after the whole try block, it’ll always be run, and not until after the finally. The else lets you make sure

  1. the second operation’s only run if there’s no exception,
  2. it’s run before the finally block, and
  3. any IOErrors it raises aren’t caught here

回答 1

有一个重要的用途else-风格和可读性。通常,将可能导致异常的代码保留在处理它们的代码附近是一个好主意。例如,比较这些:

try:
    from EasyDialogs import AskPassword
    # 20 other lines
    getpass = AskPassword
except ImportError:
    getpass = default_getpass

try:
    from EasyDialogs import AskPassword
except ImportError:
    getpass = default_getpass
else:
    # 20 other lines
    getpass = AskPassword

except不能提前返回或重新引发异常时,第二个是好的。如果可能的话,我会写:

try:
    from EasyDialogs import AskPassword
except ImportError:
    getpass = default_getpass
    return False  # or throw Exception('something more descriptive')

# 20 other lines
getpass = AskPassword

注:答案抄自最近发布的重复这里,所以这一切的“AskPassword”的东西。

There is one big reason to use else – style and readability. It’s generally a good idea to keep code that can cause exceptions near the code that deals with them. For example, compare these:

try:
    from EasyDialogs import AskPassword
    # 20 other lines
    getpass = AskPassword
except ImportError:
    getpass = default_getpass

and

try:
    from EasyDialogs import AskPassword
except ImportError:
    getpass = default_getpass
else:
    # 20 other lines
    getpass = AskPassword

The second one is good when the except can’t return early, or re-throw the exception. If possible, I would have written:

try:
    from EasyDialogs import AskPassword
except ImportError:
    getpass = default_getpass
    return False  # or throw Exception('something more descriptive')

# 20 other lines
getpass = AskPassword

Note: Answer copied from recently-posted duplicate here, hence all this “AskPassword” stuff.


回答 2

一种用途:测试一些应引发异常的代码。

try:
    this_should_raise_TypeError()
except TypeError:
    pass
except:
    assert False, "Raised the wrong exception type"
else:
    assert False, "Didn't raise any exception"

(此代码应在实践中抽象为更通用的测试。)

One use: test some code that should raise an exception.

try:
    this_should_raise_TypeError()
except TypeError:
    pass
except:
    assert False, "Raised the wrong exception type"
else:
    assert False, "Didn't raise any exception"

(This code should be abstracted into a more generic test in practice.)


回答 3

Python try-else

elsetry语句的optional 子句的预期用途是什么?

如果没有预期处理异常的情况,则预期的用途是为更多代码运行提供上下文。

此上下文避免了意外处理您未预期到的错误。

但重要的是要了解导致else子句来运行的精确条件,因为returncontinuebreak可中断的控制流else

综上所述

else声明是否有运行没有异常,如果不是被打断returncontinuebreak声明。

其他答案错过了最后一部分。

从文档:

可选的else,如果条款被执行,并且当控制切断端流动的的try条款。*

(加粗体。)脚注如下:

*目前,控制“落端流动”除了在异常或一个的执行的情况下returncontinuebreak语句。

它确实需要至少一个前面的except子句(请参阅语法)。因此,它实际上不是“ try-else”,而是“ try-except-else(-finally)”,else(和finally)是可选的。

Python指南预期的使用详解:

try … except语句具有可选的else子句,该子句在存在时必须遵循所有except子句。这对于try子句未引发异常的必须执行的代码很有用。例如:

for arg in sys.argv[1:]:
    try:
        f = open(arg, 'r')
    except IOError:
        print 'cannot open', arg
    else:
        print arg, 'has', len(f.readlines()), 'lines'
        f.close()

使用else子句比向try子句添加其他代码更好,因为它避免了意外捕获try … except语句保护的代码未引发的异常。

else后面的示例区分代码try

如果处理错误,该else块将不会运行。例如:

def handle_error():
    try:
        raise RuntimeError('oops!')
    except RuntimeError as error:
        print('handled a RuntimeError, no big deal.')
    else:
        print('if this prints, we had no error!') # won't print!
    print('And now we have left the try block!')  # will print!

现在,

>>> handle_error()
handled a RuntimeError, no big deal.
And now we have left the try block!

Python try-else

What is the intended use of the optional else clause of the try statement?

The intended use is to have a context for more code to run if there were no exceptions where it was expected to be handled.

This context avoids accidentally handling errors you did not expect.

But it’s important to understand the precise conditions that cause the else clause to run, because return, continue, and break can interrupt the control flow to else.

In Summary

The else statement runs if there are no exceptions and if not interrupted by a return, continue, or break statement.

The other answers miss that last part.

From the docs:

The optional else clause is executed if and when control flows off the end of the try clause.*

(Bolding added.) And the footnote reads:

*Currently, control “flows off the end” except in the case of an exception or the execution of a return, continue, or break statement.

It does require at least one preceding except clause (see the grammar). So it really isn’t “try-else,” it’s “try-except-else(-finally),” with the else (and finally) being optional.

The Python Tutorial elaborates on the intended usage:

The try … except statement has an optional else clause, which, when present, must follow all except clauses. It is useful for code that must be executed if the try clause does not raise an exception. For example:

for arg in sys.argv[1:]:
    try:
        f = open(arg, 'r')
    except IOError:
        print 'cannot open', arg
    else:
        print arg, 'has', len(f.readlines()), 'lines'
        f.close()

The use of the else clause is better than adding additional code to the try clause because it avoids accidentally catching an exception that wasn’t raised by the code being protected by the try … except statement.

Example differentiating else versus code following the try block

If you handle an error, the else block will not run. For example:

def handle_error():
    try:
        raise RuntimeError('oops!')
    except RuntimeError as error:
        print('handled a RuntimeError, no big deal.')
    else:
        print('if this prints, we had no error!') # won't print!
    print('And now we have left the try block!')  # will print!

And now,

>>> handle_error()
handled a RuntimeError, no big deal.
And now we have left the try block!

回答 4

Try-except-else非常适合将EAFP模式鸭子模式结合使用:

try:
  cs = x.cleanupSet
except AttributeError:
  pass
else:
  for v in cs:
    v.cleanup()

您可能会觉得此朴素的代码很好:

try:
  for v in x.cleanupSet:
    v.clenaup()
except AttributeError:
  pass

这是一种意外隐藏代码中严重错误的好方法。我在这里打错了清理,但是让我知道的AttributeError被吞噬了。更糟糕的是,如果我正确编写了该方法,但是偶尔会向该传递给具有错误名称属性的用户类型的清理方法,导致该方法在中途无声地失败并且未关闭文件?祝您调试好运。

Try-except-else is great for combining the EAFP pattern with duck-typing:

try:
  cs = x.cleanupSet
except AttributeError:
  pass
else:
  for v in cs:
    v.cleanup()

You might thing this naïve code is fine:

try:
  for v in x.cleanupSet:
    v.clenaup()
except AttributeError:
  pass

This is a great way of accidentally hiding severe bugs in your code. I typo-ed cleanup there, but the AttributeError that would let me know is being swallowed. Worse, what if I’d written it correctly, but the cleanup method was occasionally being passed a user type that had a misnamed attribute, causing it to silently fail half-way through and leave a file unclosed? Good luck debugging that one.


回答 5

我发现当您必须执行清理操作时,即使有exceptions,它也确实很有用:

try:
    data = something_that_can_go_wrong()
except Exception as e: # yes, I know that's a bad way to do it...
    handle_exception(e)
else:
    do_stuff(data)
finally:
    clean_up()

I find it really useful when you’ve got cleanup to do that has to be done even if there’s an exception:

try:
    data = something_that_can_go_wrong()
except Exception as e: # yes, I know that's a bad way to do it...
    handle_exception(e)
else:
    do_stuff(data)
finally:
    clean_up()

回答 6

即使您现在无法想到它的用途,您也可以打赌一定有它的用途。这是一个难以想象的示例:

else

a = [1,2,3]
try:
    something = a[2]
except:
    print "out of bounds"
else:
    print something

没有else

try:
    something = a[2]
except:
    print "out of bounds"

if "something" in locals():
    print something

something如果没有错误抛出,则在此处定义了变量。您可以在try块外将其删除,但是如果定义了变量,则需要进行一些混乱的检测。

Even though you can’t think of a use of it right now, you can bet there has to be a use for it. Here is an unimaginative sample:

With else:

a = [1,2,3]
try:
    something = a[2]
except:
    print "out of bounds"
else:
    print something

Without else:

try:
    something = a[2]
except:
    print "out of bounds"

if "something" in locals():
    print something

Here you have the variable something defined if no error is thrown. You can remove this outside the try block, but then it requires some messy detection if a variable is defined.


回答 7

有一个很好的例子try-elsePEP 380。基本上,归结为在算法的不同部分进行不同的异常处理。

就像这样:

try:
    do_init_stuff()
except:
    handle_init_suff_execption()
else:
    try:
        do_middle_stuff()
    except:
        handle_middle_stuff_exception()

这使您可以在发生异常的地方编写异常处理代码。

There’s a nice example of try-else in PEP 380. Basically, it comes down to doing different exception handling in different parts of the algorithm.

It’s something like this:

try:
    do_init_stuff()
except:
    handle_init_suff_execption()
else:
    try:
        do_middle_stuff()
    except:
        handle_middle_stuff_exception()

This allows you to write the exception handling code nearer to where the exception occurs.


回答 8

来自错误和异常#处理异常-docs.python.org

try ... except语句有一个可选else子句,当存在时,该子句必须遵循所有除子句之外的子句。这对于try子句未引发异常的必须执行的代码很有用。例如:

for arg in sys.argv[1:]:
    try:
        f = open(arg, 'r')
    except IOError:
        print 'cannot open', arg
    else:
        print arg, 'has', len(f.readlines()), 'lines'
        f.close()

使用else子句比向try子句添加其他代码更好,因为它避免了意外捕获try … except语句保护的代码未引发的异常。

From Errors and Exceptions # Handling exceptions – docs.python.org

The try ... except statement has an optional else clause, which, when present, must follow all except clauses. It is useful for code that must be executed if the try clause does not raise an exception. For example:

for arg in sys.argv[1:]:
    try:
        f = open(arg, 'r')
    except IOError:
        print 'cannot open', arg
    else:
        print arg, 'has', len(f.readlines()), 'lines'
        f.close()

The use of the else clause is better than adding additional code to the try clause because it avoids accidentally catching an exception that wasn’t raised by the code being protected by the try … except statement.


回答 9

查看Python参考,似乎else是在try没有异常的情况下执行的。当控制从try子句的末尾流出时,将执行可选的else子句。2 else子句中的异常不由前面的except子句处理。

深入研究python有一个例子,如果我理解正确,try他们会在块中尝试导入模块,当该模块失败时,您将获得异常并绑定默认值,但是当它起作用时,您可以选择进入else块并绑定所需的内容(请参阅示例和说明的链接)。

如果您尝试在代码catch块中进行工作,则可能会引发另一个异常-我想这就是代码else块派上用场的地方。

Looking at Python reference it seems that else is executed after try when there’s no exception. The optional else clause is executed if and when control flows off the end of the try clause. 2 Exceptions in the else clause are not handled by the preceding except clauses.

Dive into python has an example where, if I understand correctly, in try block they try to import a module, when that fails you get exception and bind default but when it works you have an option to go into else block and bind what is required (see link for the example and explanation).

If you tried to do work in catch block it might throw another exception – I guess that’s where the else block comes handy.


回答 10

而已。try-except子句的’else’块存在于(仅当)tryed操作成功时运行的代码。它可以被使用,也可以被滥用。

try:
    fp= open("configuration_file", "rb")
except EnvironmentError:
    confdata= '' # it's ok if the file can't be opened
else:
    confdata= fp.read()
    fp.close()

# your code continues here
# working with (possibly empty) confdata

我个人喜欢它,并在适当的时候使用它。它在语义上对语句进行分组。

That’s it. The ‘else’ block of a try-except clause exists for code that runs when (and only when) the tried operation succeeds. It can be used, and it can be abused.

try:
    fp= open("configuration_file", "rb")
except EnvironmentError:
    confdata= '' # it's ok if the file can't be opened
else:
    confdata= fp.read()
    fp.close()

# your code continues here
# working with (possibly empty) confdata

Personally, I like it and use it when appropriate. It semantically groups statements.


回答 11

可能的用途可能是:

#debug = []

def debuglog(text, obj=None):
    " Simple little logger. "
    try:
        debug   # does global exist?
    except NameError:
        pass    # if not, don't even bother displaying
    except:
        print('Unknown cause. Debug debuglog().')
    else:
        # debug does exist.
        # Now test if you want to log this debug message
        # from caller "obj"
        try:
            if obj in debug:
                print(text)     # stdout
        except TypeError:
            print('The global "debug" flag should be an iterable.')
        except:
            print('Unknown cause. Debug debuglog().')

def myfunc():
    debuglog('Made it to myfunc()', myfunc)

debug = [myfunc,]
myfunc()

也许这会导致您使用过多。

Perhaps a use might be:

#debug = []

def debuglog(text, obj=None):
    " Simple little logger. "
    try:
        debug   # does global exist?
    except NameError:
        pass    # if not, don't even bother displaying
    except:
        print('Unknown cause. Debug debuglog().')
    else:
        # debug does exist.
        # Now test if you want to log this debug message
        # from caller "obj"
        try:
            if obj in debug:
                print(text)     # stdout
        except TypeError:
            print('The global "debug" flag should be an iterable.')
        except:
            print('Unknown cause. Debug debuglog().')

def myfunc():
    debuglog('Made it to myfunc()', myfunc)

debug = [myfunc,]
myfunc()

Maybe this will lead you too a use.


回答 12

我发现该try: ... else:构造在您运行数据库查询并将这些查询的结果记录到具有相同口味/类型的单独数据库中的情况下很有用。假设我有很多工作线程,它们都处理提交给队列的数据库查询

#in a long running loop
try:
    query = queue.get()
    conn = connect_to_db(<main db>)
    curs = conn.cursor()
    try:
        curs.execute("<some query on user input that may fail even if sanitized">)
    except DBError:
        logconn = connect_to_db(<logging db>)
        logcurs = logconn.cursor()
        logcurs.execute("<update in DB log with record of failed query")
        logcurs.close()
        logconn.close()
    else:

        #we can't put this in main try block because an error connecting
        #to the logging DB would be indistinguishable from an error in 
        #the mainquery 

        #We can't put this after the whole try: except: finally: block
        #because then we don't know if the query was successful or not

        logconn = connect_to_db(<logging db>)
        logcurs = logconn.cursor()
        logcurs.execute("<update in DB log with record of successful query")
        logcurs.close()
        logconn.close()
        #do something in response to successful query
except DBError:
    #This DBError is because of a problem with the logging database, but 
    #we can't let that crash the whole thread over what might be a
    #temporary network glitch
finally:
    curs.close()
    conn.close()
    #other cleanup if necessary like telling the queue the task is finished

当然,如果您可以区分可能引发的异常,则不必使用它,但是如果对成功的一段代码做出反应的代码可能会抛出与该成功的段相同的异常,并且您不能仅仅让第二个可能的异常消失,或者在成功后立即返回(在我的情况下这将杀死线程),这确实派上了用场。

I have found the try: ... else: construct useful in the situation where you are running database queries and logging the results of those queries to a separate database of the same flavour/type. Let’s say I have lots of worker threads all handling database queries submitted to a queue

#in a long running loop
try:
    query = queue.get()
    conn = connect_to_db(<main db>)
    curs = conn.cursor()
    try:
        curs.execute("<some query on user input that may fail even if sanitized">)
    except DBError:
        logconn = connect_to_db(<logging db>)
        logcurs = logconn.cursor()
        logcurs.execute("<update in DB log with record of failed query")
        logcurs.close()
        logconn.close()
    else:

        #we can't put this in main try block because an error connecting
        #to the logging DB would be indistinguishable from an error in 
        #the mainquery 

        #We can't put this after the whole try: except: finally: block
        #because then we don't know if the query was successful or not

        logconn = connect_to_db(<logging db>)
        logcurs = logconn.cursor()
        logcurs.execute("<update in DB log with record of successful query")
        logcurs.close()
        logconn.close()
        #do something in response to successful query
except DBError:
    #This DBError is because of a problem with the logging database, but 
    #we can't let that crash the whole thread over what might be a
    #temporary network glitch
finally:
    curs.close()
    conn.close()
    #other cleanup if necessary like telling the queue the task is finished

Of course if you can distinguish between the possible exceptions that might be thrown, you don’t have to use this, but if code reacting to a successful piece of code might throw the same exception as the successful piece, and you can’t just let the second possible exception go, or return immediately on success (which would kill the thread in my case), then this does come in handy.


回答 13

else通常可以使用一个块来补充每个except块中发生的功能。

try:
    test_consistency(valuable_data)
except Except1:
    inconsistency_type = 1
except Except2:
    inconsistency_type = 2
except:
    # Something else is wrong
    raise
else:
    inconsistency_type = 0

"""
Process each individual inconsistency down here instead of
inside the except blocks. Use 0 to mean no inconsistency.
"""

在这种情况下,inconsistency_type在每个except块中都设置,以便在中的无错误情况下补充行为else

当然,我将其描述为一种模式,有一天可能会在您自己的代码中出现。在这种情况下,无论如何您只需将其设置inconsistency_type为0 try

An else block can often exist to complement functionality that occurs in every except block.

try:
    test_consistency(valuable_data)
except Except1:
    inconsistency_type = 1
except Except2:
    inconsistency_type = 2
except:
    # Something else is wrong
    raise
else:
    inconsistency_type = 0

"""
Process each individual inconsistency down here instead of
inside the except blocks. Use 0 to mean no inconsistency.
"""

In this case, inconsistency_type is set in each except block, so that behaviour is complemented in the no-error case in else.

Of course, I’m describing this as a pattern that may turn up in your own code someday. In this specific case, you just set inconsistency_type to 0 before the try block anyway.


回答 14

这是我喜欢使用此模式的另一个地方:

 while data in items:
     try
        data = json.loads(data)
     except ValueError as e:
        log error
     else:
        # work on the `data`

Here is another place where I like to use this pattern:

 while data in items:
     try
        data = json.loads(data)
     except ValueError as e:
        log error
     else:
        # work on the `data`

回答 15

我可以想到的一种使用场景是不可预测的异常,如果再次尝试可以避免这种异常。例如,当try块中的操作涉及随机数时:

while True:
    try:
        r = random.random()
        some_operation_that_fails_for_specific_r(r)
    except Exception:
        continue
    else:
        break

但是,如果可以预测到异常,则应始终在选择异常之前预先选择验证。但是,并非所有事情都可以预测,因此此代码模式应有的地位。

One of the use scenarios I can think of is unpredictable exceptions, which can be circumvented if you try again. For instance, when the operations in try block involves random numbers:

while True:
    try:
        r = random.random()
        some_operation_that_fails_for_specific_r(r)
    except Exception:
        continue
    else:
        break

But if the exception can be predicted, you should always choose validation beforehand over an exception. However, not everything can be predicted, so this code pattern has its place.


回答 16

我发现else对于处理可能不正确的配置文件很有用:

try:
    value, unit = cfg['lock'].split()
except ValueError:
    msg = 'lock monitoring config must consist of two words separated by white space'
    self.log('warn', msg)
else:
     # get on with lock monitoring if config is ok

读取lock配置的异常会禁用锁定监视,并且ValueErrors会记录一条有用的警告消息。

I have found else useful for dealing with a possibly incorrect config file:

try:
    value, unit = cfg['lock'].split()
except ValueError:
    msg = 'lock monitoring config must consist of two words separated by white space'
    self.log('warn', msg)
else:
     # get on with lock monitoring if config is ok

An exception reading the lock config disables lock monitoring and ValueErrors log a helpful warning message.


回答 17

假设您的编程逻辑取决于字典是否具有带有给定键的条目。您可以测试dict.get(key)使用if... else...构造的结果,也可以执行以下操作:

try:
    val = dic[key]
except KeyError:
    do_some_stuff()
else:
    do_some_stuff_with_val(val)

Suppose your programming logic depends on whether a dictionary has an entry with a given key. You can test the result of dict.get(key) using if... else... construct, or you can do:

try:
    val = dic[key]
except KeyError:
    do_some_stuff()
else:
    do_some_stuff_with_val(val)

回答 18

我将添加另一个在处理数据库会话时似乎很简单的用例:

    # getting a DB connection 
    conn = db.engine.connect()

    # and binding to a DB session
    session = db.get_session(bind=conn)

    try:
        # we build the query to DB
        q = session.query(MyTable).filter(MyTable.col1 == 'query_val')

        # i.e retrieve one row
        data_set = q.one_or_none()

        # return results
        return [{'col1': data_set.col1, 'col2': data_set.col2, ...}]

    except:
        # here we make sure to rollback the transaction, 
        # handy when we update stuff into DB
        session.rollback()
        raise

    else:
        # when no errors then we can commit DB changes
        session.commit()

    finally:
        # and finally we can close the session
        session.close()

I would add another use case that seems straight forward when handling DB sessions:

    # getting a DB connection 
    conn = db.engine.connect()

    # and binding to a DB session
    session = db.get_session(bind=conn)

    try:
        # we build the query to DB
        q = session.query(MyTable).filter(MyTable.col1 == 'query_val')

        # i.e retrieve one row
        data_set = q.one_or_none()

        # return results
        return [{'col1': data_set.col1, 'col2': data_set.col2, ...}]

    except:
        # here we make sure to rollback the transaction, 
        # handy when we update stuff into DB
        session.rollback()
        raise

    else:
        # when no errors then we can commit DB changes
        session.commit()

    finally:
        # and finally we can close the session
        session.close()

回答 19

else:块令人困惑,并且(几乎)无用。它也是forand while语句的一部分。

实际上,即使在if声明中,else:也可能以真正可怕的方式滥用它们,从而创建很难发现的错误。

考虑一下。

   if a < 10:
       # condition stated explicitly
   elif a > 10 and b < 10:
       # condition confusing but at least explicit
   else:
       # Exactly what is true here?
       # Can be hard to reason out what condition is true

再三考虑else:。这通常是一个问题。除非在if-statement中,否则应避免使用它,甚至还要考虑记录-condition else以使其明确。

The else: block is confusing and (nearly) useless. It’s also part of the for and while statements.

Actually, even on an if-statement, the else: can be abused in truly terrible ways creating bugs that are very hard to find.

Consider this.

   if a < 10:
       # condition stated explicitly
   elif a > 10 and b < 10:
       # condition confusing but at least explicit
   else:
       # Exactly what is true here?
       # Can be hard to reason out what condition is true

Think twice about else:. It is generally a problem. Avoid it except in an if-statement and even then consider documenting the else– condition to make it explicit.


Python在类中是否具有“私有”变量?

问题:Python在类中是否具有“私有”变量?

我来自Java世界,正在阅读Bruce Eckels的Python 3 Patterns,Recipes和Idioms

在阅读类时,它继续说在Python中不需要声明实例变量。您只需在构造函数中使用它们,然后它们就在那里。

因此,例如:

class Simple:
    def __init__(self, s):
        print("inside the simple constructor")
        self.s = s

    def show(self):
        print(self.s)

    def showMsg(self, msg):
        print(msg + ':', self.show())

如果是这样,那么类的任何对象都Simple可以s在类外部更改变量的值。

例如:

if __name__ == "__main__":
    x = Simple("constructor argument")
    x.s = "test15" # this changes the value
    x.show()
    x.showMsg("A message")

在Java中,我们已经学会了有关公共/私有/保护变量的知识。这些关键字很有意义,因为有时您需要一个类中的变量,而该类之外的任何人都无法访问该变量。

为什么在Python中不需要这样做?

I’m coming from the Java world and reading Bruce Eckels’ Python 3 Patterns, Recipes and Idioms.

While reading about classes, it goes on to say that in Python there is no need to declare instance variables. You just use them in the constructor, and boom, they are there.

So for example:

class Simple:
    def __init__(self, s):
        print("inside the simple constructor")
        self.s = s

    def show(self):
        print(self.s)

    def showMsg(self, msg):
        print(msg + ':', self.show())

If that’s true, then any object of class Simple can just change the value of variable s outside of the class.

For example:

if __name__ == "__main__":
    x = Simple("constructor argument")
    x.s = "test15" # this changes the value
    x.show()
    x.showMsg("A message")

In Java, we have been taught about public/private/protected variables. Those keywords make sense because at times you want variables in a class to which no one outside the class has access to.

Why is that not required in Python?


回答 0

这是文化的。在Python中,您无需写入其他类的实例或类变量。在Java中,如果您真的想做的话,什么也不能阻止您做同样的事情-毕竟,您始终可以编辑类本身的源代码以达到相同的效果。Python放弃了这种安全性的幌子,并鼓励程序员负责。实际上,这非常好用。

如果出于某种原因要模拟私有变量,则始终可以使用PEP 8中__前缀。Python会像这样对变量名称进行修饰,以使它们在包含它们的类之外的代码中不易被看到(尽管只要有足够的决心,您可以解决它,就像您可以使用它来避开Java保护一样)。__foo

按照相同的约定,即使没有从技术上阻止您这样做_前缀也意味着不要离开。您不会玩弄看起来像__foo或的另一个类的变量_bar

It’s cultural. In Python, you don’t write to other classes’ instance or class variables. In Java, nothing prevents you from doing the same if you really want to – after all, you can always edit the source of the class itself to achieve the same effect. Python drops that pretence of security and encourages programmers to be responsible. In practice, this works very nicely.

If you want to emulate private variables for some reason, you can always use the __ prefix from PEP 8. Python mangles the names of variables like __foo so that they’re not easily visible to code outside the class that contains them (although you can get around it if you’re determined enough, just like you can get around Java’s protections if you work at it).

By the same convention, the _ prefix means stay away even if you’re not technically prevented from doing so. You don’t play around with another class’s variables that look like __foo or _bar.


回答 1

python中的私有变量或多或少是一种技巧:解释器故意重命名该变量。

class A:
    def __init__(self):
        self.__var = 123
    def printVar(self):
        print self.__var

现在,如果您尝试__var在类定义之外进行访问,它将失败:

 >>>x = A()
 >>>x.__var # this will return error: "A has no attribute __var"

 >>>x.printVar() # this gives back 123

但是您可以轻松地摆脱这一点:

 >>>x.__dict__ # this will show everything that is contained in object x
               # which in this case is something like {'_A__var' : 123}

 >>>x._A__var = 456 # you now know the masked name of private variables
 >>>x.printVar() # this gives back 456

您可能知道OOP中的方法是这样调用的:x.printVar() => A.printVar(x),如果A.printVar()可以访问中的某个字段,那么x也可以在外部 访问该字段A.printVar()…毕竟,创建函数是为了可重用性,内部的语句没有特殊的功能。

当涉及到编译器时,游戏就不同了(隐私是编译器级别的概念)。它知道具有访问控制修饰符的类定义,因此如果在编译时未遵循规则,则可能会出错

Private variables in python is more or less a hack: the interpreter intentionally renames the variable.

class A:
    def __init__(self):
        self.__var = 123
    def printVar(self):
        print self.__var

Now, if you try to access __var outside the class definition, it will fail:

 >>>x = A()
 >>>x.__var # this will return error: "A has no attribute __var"

 >>>x.printVar() # this gives back 123

But you can easily get away with this:

 >>>x.__dict__ # this will show everything that is contained in object x
               # which in this case is something like {'_A__var' : 123}

 >>>x._A__var = 456 # you now know the masked name of private variables
 >>>x.printVar() # this gives back 456

You probably know that methods in OOP are invoked like this: x.printVar() => A.printVar(x), if A.printVar() can access some field in x, this field can also be accessed outside A.printVar()…after all, functions are created for reusability, there is no special power given to the statements inside.

The game is different when there is a compiler involved (privacy is a compiler level concept). It know about class definition with access control modifiers so it can error out if the rules are not being followed at compile time


回答 2

正如上面的许多评论所正确提到的,我们不要忘记访问修饰符的主要目标:帮助代码用户理解应该更改的内容和不应该更改的内容。当您看到一个私有字段时,您不会把它弄乱。因此,主要是语法糖,可以通过_和__在Python中轻松实现。

As correctly mentioned by many of the comments above, let’s not forget the main goal of Access Modifiers: To help users of code understand what is supposed to change and what is supposed not to. When you see a private field you don’t mess around with it. So it’s mostly syntactic sugar which is easily achieved in Python by the _ and __.


回答 3

下划线约定中存在私有变量的变体。

In [5]: class Test(object):
   ...:     def __private_method(self):
   ...:         return "Boo"
   ...:     def public_method(self):
   ...:         return self.__private_method()
   ...:     

In [6]: x = Test()

In [7]: x.public_method()
Out[7]: 'Boo'

In [8]: x.__private_method()
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-8-fa17ce05d8bc> in <module>()
----> 1 x.__private_method()

AttributeError: 'Test' object has no attribute '__private_method'

有一些细微的差异,但是出于编程模式思想纯净的考虑,其足够好。

@private装饰器中有一些示例可以更紧密地实现该概念,但是可以使用YMMV。可以说也可以编写一个使用meta的类定义

There is a variation of private variables in the underscore convention.

In [5]: class Test(object):
   ...:     def __private_method(self):
   ...:         return "Boo"
   ...:     def public_method(self):
   ...:         return self.__private_method()
   ...:     

In [6]: x = Test()

In [7]: x.public_method()
Out[7]: 'Boo'

In [8]: x.__private_method()
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-8-fa17ce05d8bc> in <module>()
----> 1 x.__private_method()

AttributeError: 'Test' object has no attribute '__private_method'

There are some subtle differences, but for the sake of programming pattern ideological purity, its good enough.

There are examples out there of @private decorators that more closely implement the concept, but YMMV. Arguably one could also write a class defintion that uses meta


回答 4

“在Java中,我们被教导有关公共/私有/保护变量”

“为什么在python中不需要?”

出于同样的原因,在Java中不需要

您可以自由使用-或不使用privateand protected

作为一个Python和Java程序员,我发现,privateprotected是非常,非常重要的设计理念。但实际上,在成千上万的Java和Python行中,我从未真正使用过privateprotected

为什么不?

这是我的问题“不受谁保护?”

我团队中的其他程序员?他们有出处。受保护的人何时可以更改它意味着什么?

其他团队的其他程序员?他们在同一家公司工作。他们可以-通过电话-获取消息来源。

客户?(通常)是按需租用的程序。客户(通常)拥有代码。

那么,到底是谁在保护我?

“In java, we have been taught about public/private/protected variables”

“Why is that not required in python?”

For the same reason, it’s not required in Java.

You’re free to use — or not use private and protected.

As a Python and Java programmer, I’ve found that private and protected are very, very important design concepts. But as a practical matter, in tens of thousands of lines of Java and Python, I’ve never actually used private or protected.

Why not?

Here’s my question “protected from whom?”

Other programmers on my team? They have the source. What does protected mean when they can change it?

Other programmers on other teams? They work for the same company. They can — with a phone call — get the source.

Clients? It’s work-for-hire programming (generally). The clients (generally) own the code.

So, who — precisely — am I protecting it from?


回答 5

如前所述,您可以通过在变量或方法前加上下划线作为前缀来表明该变量或方法是私有的。如果您觉得不够,可以随时使用property装饰器。这是一个例子:

class Foo:

    def __init__(self, bar):
        self._bar = bar

    @property
    def bar(self):
        """Getter for '_bar'."""
        return self._bar

这样,引用的某人或某物bar实际上是在引用bar函数的返回值,而不是变量本身,因此可以访问但不能更改。但是,如果有人真的想要,他们可以简单地使用_bar并为其分配新的值。就像反复提到的那样,没有一种万无一失的方法可以防止某人访问您想要隐藏的变量和方法。但是,使用property可以发送的最清晰的消息是不要编辑变量。property也可以用于更复杂的getter / setter / deleter访问路径,如下所示:https : //docs.python.org/3/library/functions.html#property

As mentioned earlier, you can indicate that a variable or method is private by prefixing it with an underscore. If you don’t feel like this is enough, you can always use the property decorator. Here’s an example:

class Foo:

    def __init__(self, bar):
        self._bar = bar

    @property
    def bar(self):
        """Getter for '_bar'."""
        return self._bar

This way, someone or something that references bar is actually referencing the return value of the bar function rather than the variable itself, and therefore it can be accessed but not changed. However, if someone really wanted to, they could simply use _bar and assign a new value to it. There is no surefire way to prevent someone from accessing variables and methods that you wish to hide, as has been said repeatedly. However, using property is the clearest message you can send that a variable is not to be edited. property can also be used for more complex getter/setter/deleter access paths, as explained here: https://docs.python.org/3/library/functions.html#property


回答 6

Python通过自动将类名添加到以两个下划线开头的任何标识符的功能,对私有标识符的支持有限。在大多数情况下,这对程序员是透明的,但是最终结果是,以此方式命名的任何变量都可以用作私有变量。

有关更多信息,请参见此处

通常,与其他语言相比,Python的面向对象的实现有点原始。但实际上,我很喜欢。从概念上讲,这是一种非常简单的实现,非常适合该语言的动态样式。

Python has limited support for private identifiers, through a feature that automatically prepends the class name to any identifiers starting with two underscores. This is transparent to the programmer, for the most part, but the net effect is that any variables named this way can be used as private variables.

See here for more on that.

In general, Python’s implementation of object orientation is a bit primitive compared to other languages. But I enjoy this, actually. It’s a very conceptually simple implementation and fits well with the dynamic style of the language.


回答 7

我唯一使用私有变量的时间是在写入或读取变量时需要做其他事情时,因此需要强制使用setter和/或getter。

如前所述,这再次涉及文化。我一直在从事免费阅读和编写其他类变量的项目。一个实现被弃用时,识别使用该功能的所有代码路径的时间要长得多。当强制使用setter和getter时,可以很容易地编写一条调试语句来识别已调用了不赞成使用的方法以及调用该方法的代码路径。

当您在任何人都可以编写扩展的项目上时,通知用户有关已弃用的方法的信息,这些方法将在几个发行版中消失,因此对于将升级时模块的损坏降至最低至关重要。

所以我的答案是;如果您和您的同事维护一个简单的代码集,那么保护类变量并非总是必要的。如果您正在编写一个可扩展的系统,那么对内核进行的更改就变得势在必行,而所有的扩展都需要使用代码来捕获这些更改。

The only time I ever use private variables is when I need to do other things when writing to or reading from the variable and as such I need to force the use of a setter and/or getter.

Again this goes to culture, as already stated. I’ve been working on projects where reading and writing other classes variables was free-for-all. When one implementation became deprecated it took a lot longer to identify all code paths that used that function. When use of setters and getters was forced, a debug statement could easily be written to identify that the deprecated method had been called and the code path that calls it.

When you are on a project where anyone can write an extension, notifying users about deprecated methods that are to disappear in a few releases hence is vital to keep module breakage at a minimum upon upgrades.

So my answer is; if you and your colleagues maintain a simple code set then protecting class variables is not always necessary. If you are writing an extensible system then it becomes imperative when changes to the core is made that needs to be caught by all extensions using the code.


回答 8

私有和受保护的概念非常重要。但是python-只是用于原型开发和快速开发的工具,可用于开发的资源有限,这就是为什么在python中并没有严格遵循某些保护级别的原因。您可以在类成员中使用“ __”,它可以正常工作,但看起来不够好-每次访问此类字段都包含这些字符。

另外,您会注意到python OOP概念并不完美,smaltalk或ruby更接近于纯OOP概念。甚至C#或Java都更接近。

Python是非常好的工具。但是它是简化的OOP语言。从语法和概念上简化。python存在的主要目的是使开发人员能够以非常快的方式编写具有高抽象级别的易读代码。

private and protected concepts are very important. But python – just a tool for prototyping and rapid development with restricted resources available for development, that is why some of protection levels are not so strict followed in python. You can use “__” in class member, it works properly, but looks not good enough – each access to such field contains these characters.

Also, you can noticed that python OOP concept is not perfect, smaltalk or ruby much closer to pure OOP concept. Even C# or Java are closer.

Python is very good tool. But it is simplified OOP language. Syntactically and conceptually simplified. The main goal of python existence is to bring to developers possibility to write easy readable code with high abstraction level in a very fast manner.


回答 9

抱歉,“恢复”线程,但是,我希望这会对某人有所帮助:

在Python3中,如果您只想“封装”类属性(例如在Java中),则可以执行以下操作:

class Simple:
    def __init__(self, str):
        print("inside the simple constructor")
        self.__s = str

    def show(self):
        print(self.__s)

    def showMsg(self, msg):
        print(msg + ':', self.show())

要实例化此操作,请执行以下操作:

ss = Simple("lol")
ss.show()

注意:print(ss.__s)会抛出错误。

实际上,Python3将混淆全局属性名称。像在Java中一样,将其变为“私有”属性。该属性的名称仍然是全局的,但是以一种无法访问的方式,就像其他语言中的私有属性一样。

但是不要害怕。没关系 它也做这项工作。;)

Sorry guys for “resurrecting” the thread, but, I hope this will help someone:

In Python3 if you just want to “encapsulate” the class attributes, like in Java, you can just do the same thing like this:

class Simple:
    def __init__(self, str):
        print("inside the simple constructor")
        self.__s = str

    def show(self):
        print(self.__s)

    def showMsg(self, msg):
        print(msg + ':', self.show())

To instantiate this do:

ss = Simple("lol")
ss.show()

Note that: print(ss.__s) will throw an error.

In practice, Python3 will obfuscate the global attribute name. Turning this like a “private” attribute, like in Java. The attribute’s name is still global, but in an inaccessible way, like a private attribute in other languages.

But don’t be afraid of it. It doesn’t matter. It does the job too. ;)


回答 10

Python没有像C ++或Java那样的任何私有变量。如果需要,您也可以随时访问任何成员变量。但是,在Python中不需要私有变量,因为在Python中公开类成员变量也不错。如果需要封装成员变量,则可以稍后使用“ @property”来实现,而无需破坏现有的客户端代码。

在python中,单个下划线“ _”用于表示方法或变量不被视为类的公共api的一部分,并且该api的这一部分可以在不同版本之间进行更改。您可以使用这些方法/变量,但如果使用此类的较新版本,则代码可能会中断。

双下划线“ __”并不表示“私有变量”。您可以使用它来定义“局部类”的变量,并且这些变量不能轻易被子类覆盖。它处理变量名称。

例如:

class A(object):
    def __init__(self):
        self.__foobar = None # will be automatically mangled to self._A__foobar

class B(A):
    def __init__(self):
        self.__foobar = 1 # will be automatically mangled to self._B__foobar

self .__ foobar的名称会在A类中自动更改为self._A__foobar。在B类中,其名称将更改为self._B__foobar。因此,每个子类都可以定义自己的变量__foobar而不覆盖其父变量。但是没有什么可以阻止您访问以双下划线开头的变量。但是,名称修改可防止您偶然调用此变量/方法。

我强烈建议观看Raymond Hettingers谈论Pycon 2013上的“ Pythons类开发工具包”(应该在Youtube上提供),该示例很好地说明了为什么以及如何使用@property和“ __”-instance变量。

Python does not have any private variables like C++ or Java does. You could access any member variable at any time if wanted, too. However, you don’t need private variables in Python, because in Python it is not bad to expose your classes member variables. If you have the need to encapsulate a member variable, you can do this by using “@property” later on without breaking existing client code.

In python the single underscore “_” is used to indicate, that a method or variable is not considered as part of the public api of a class and that this part of the api could change between different versions. You can use these methods/variables, but your code could break, if you use a newer version of this class.

The double underscore “__” does not mean a “private variable”. You use it to define variables which are “class local” and which can not be easily overidden by subclasses. It mangles the variables name.

For example:

class A(object):
    def __init__(self):
        self.__foobar = None # will be automatically mangled to self._A__foobar

class B(A):
    def __init__(self):
        self.__foobar = 1 # will be automatically mangled to self._B__foobar

self.__foobar’s name is automatically mangled to self._A__foobar in class A. In class B it is mangled to self._B__foobar. So every subclass can define its own variable __foobar without overriding its parents variable(s). But nothing prevents you from accessing variables beginning with double underscores. However, name-mangling prevents you from calling this variables /methods incidentally.

I strongly recommend to watch Raymond Hettingers talk “Pythons class development toolkit” from Pycon 2013 (should be available on Youtube), which gives a good example why and how you should use @property and “__”-instance variables.


回答 11

实际上,您可以C#使用以下简单技巧来模拟吸气剂和吸气剂:

class Screen(object):

    def getter_setter_y(self, y, get=True):
        if get is True:
            Screen.getter_setter_y.value = y
        else:
            return Screen.getter_setter_y.value

     def getter_setter_x(self, x, get=True):
         if get is True:
             Screen.getter_setter_x.value = x
         else:
             return Screen.getter_setter_x.value

然后像这样使用它C#

scr = Screen()
scr.getter_setter_x(100)
value =  scr.getter_setter_x(0, get=False)
print (value)

这只是在函数中声明一个静态局部变量,该变量将扮演获取/设置的角色,因为这是通过get和set方法共享变量的唯一方法,而无需将其全局化为类或文件。

Actually you can simulate a C# getter and setter using this simple trick:

class Screen(object):

    def getter_setter_y(self, y, get=True):
        if get is True:
            Screen.getter_setter_y.value = y
        else:
            return Screen.getter_setter_y.value

     def getter_setter_x(self, x, get=True):
         if get is True:
             Screen.getter_setter_x.value = x
         else:
             return Screen.getter_setter_x.value

Then use it similar like in C#:

scr = Screen()
scr.getter_setter_x(100)
value =  scr.getter_setter_x(0, get=False)
print (value)

It’s just declaring a static local variable in a function that will play a get/set role, since that’s the only way to share a variable via get and set methods, without make it global for a class or file.


Python中的“ @”(@)符号有什么作用?

问题:Python中的“ @”(@)符号有什么作用?

我正在看一些使用 @符号的,但我不知道它的作用。我也不清楚要搜索的内容,因为搜索Python文档时会发现该@符号,否则Google不会返回相关结果。

I’m looking at some Python code which used the @ symbol, but I have no idea what it does. I also do not know what to search for as searching Python docs or Google does not return relevant results when the @ symbol is included.


回答 0

行首的@符号用于类,函数和方法修饰符

在这里阅读更多:

PEP 318:装饰器

Python装饰器

您会遇到的最常见的Python装饰器是:

@属性

@classmethod

@staticmethod

如果您@在一行的中间看到一个,那就是矩阵乘法。向下滚动以查看其他解决使用的答案@

An @ symbol at the beginning of a line is used for class, function and method decorators.

Read more here:

PEP 318: Decorators

Python Decorators

The most common Python decorators you’ll run into are:

@property

@classmethod

@staticmethod

If you see an @ in the middle of a line, that’s a different thing, matrix multiplication. Scroll down to see other answers that address that use of @.


回答 1

class Pizza(object):
    def __init__(self):
        self.toppings = []

    def __call__(self, topping):
        # When using '@instance_of_pizza' before a function definition
        # the function gets passed onto 'topping'.
        self.toppings.append(topping())

    def __repr__(self):
        return str(self.toppings)

pizza = Pizza()

@pizza
def cheese():
    return 'cheese'
@pizza
def sauce():
    return 'sauce'

print pizza
# ['cheese', 'sauce']

这表明在修饰符之后定义的function/ method/ 基本上只是作为符号传递到/ 之后的/ 。classargumentfunctionmethod@

第一次发现

微框架Flask从一开始就以以下格式引入装饰器

from flask import Flask
app = Flask(__name__)

@app.route("/")
def hello():
    return "Hello World!"

依次将其翻译为:

rule      = "/"
view_func = hello
# They go as arguments here in 'flask/app.py'
def add_url_rule(self, rule, endpoint=None, view_func=None, **options):
    pass

意识到这一点终于使我与Flask和平相处。

Example

class Pizza(object):
    def __init__(self):
        self.toppings = []

    def __call__(self, topping):
        # When using '@instance_of_pizza' before a function definition
        # the function gets passed onto 'topping'.
        self.toppings.append(topping())

    def __repr__(self):
        return str(self.toppings)

pizza = Pizza()

@pizza
def cheese():
    return 'cheese'
@pizza
def sauce():
    return 'sauce'

print pizza
# ['cheese', 'sauce']

This shows that the function/method/class you’re defining after a decorator is just basically passed on as an argument to the function/method immediately after the @ sign.

First sighting

The microframework Flask introduces decorators from the very beginning in the following format:

from flask import Flask
app = Flask(__name__)

@app.route("/")
def hello():
    return "Hello World!"

This in turn translates to:

rule      = "/"
view_func = hello
# They go as arguments here in 'flask/app.py'
def add_url_rule(self, rule, endpoint=None, view_func=None, **options):
    pass

Realizing this finally allowed me to feel at peace with Flask.


回答 2

此代码段:

def decorator(func):
   return func

@decorator
def some_func():
    pass

等效于以下代码:

def decorator(func):
    return func

def some_func():
    pass

some_func = decorator(some_func)

在装饰器的定义中,您可以添加一些通常不会由函数返回的修改内容。

This code snippet:

def decorator(func):
   return func

@decorator
def some_func():
    pass

Is equivalent to this code:

def decorator(func):
    return func

def some_func():
    pass

some_func = decorator(some_func)

In the definition of a decorator you can add some modified things that wouldn’t be returned by a function normally.


回答 3

在Python 3.5中,您可以重载@为运算符。之所以命名为__matmul__,是因为它被设计用于进行矩阵乘法,但是它可以是任何您想要的。有关详细信息,请参见PEP465

这是矩阵乘法的简单实现。

class Mat(list):
    def __matmul__(self, B):
        A = self
        return Mat([[sum(A[i][k]*B[k][j] for k in range(len(B)))
                    for j in range(len(B[0])) ] for i in range(len(A))])

A = Mat([[1,3],[7,5]])
B = Mat([[6,8],[4,2]])

print(A @ B)

此代码生成:

[[18, 14], [62, 66]]

In Python 3.5 you can overload @ as an operator. It is named as __matmul__, because it is designed to do matrix multiplication, but it can be anything you want. See PEP465 for details.

This is a simple implementation of matrix multiplication.

class Mat(list):
    def __matmul__(self, B):
        A = self
        return Mat([[sum(A[i][k]*B[k][j] for k in range(len(B)))
                    for j in range(len(B[0])) ] for i in range(len(A))])

A = Mat([[1,3],[7,5]])
B = Mat([[6,8],[4,2]])

print(A @ B)

This code yields:

[[18, 14], [62, 66]]

回答 4

Python中的“ @”(@)符号有什么作用?

简而言之,它用于装饰器语法和矩阵乘法。

在装饰器的上下文中,此语法为:

@decorator
def decorated_function():
    """this function is decorated"""

等效于此:

def decorated_function():
    """this function is decorated"""

decorated_function = decorator(decorated_function)

在矩阵乘法的上下文中,a @ b调用a.__matmul__(b)-使用以下语法:

a @ b

相当于

dot(a, b)

a @= b

相当于

a = dot(a, b)

其中dot,例如是numpy矩阵乘法函数,并且aand b是矩阵。

您如何独自发现呢?

我也不知道要搜索什么,因为搜索Python文档时会出现,或者当包含@符号时Google不会返回相关结果。

如果您想对某个特定的python语法有一个比较完整的了解,请直接查看语法文件。对于Python 3分支:

~$ grep -C 1 "@" cpython/Grammar/Grammar 

decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE
decorators: decorator+
--
testlist_star_expr: (test|star_expr) (',' (test|star_expr))* [',']
augassign: ('+=' | '-=' | '*=' | '@=' | '/=' | '%=' | '&=' | '|=' | '^=' |
            '<<=' | '>>=' | '**=' | '//=')
--
arith_expr: term (('+'|'-') term)*
term: factor (('*'|'@'|'/'|'%'|'//') factor)*
factor: ('+'|'-'|'~') factor | power

我们可以在这里看到@在三种情况下使用的内容:

  • 装饰工
  • 因子之间的运算符
  • 扩充的赋值运算符

装饰语法:

在Google上搜索“ decorator python docs”时,将“ Python语言参考”的“复合语句”部分作为最高结果之一。向下滚动至函数定义部分,我们可以通过搜索“ decorator”一词找到该部分,我们发现……有很多东西可供阅读。但是“ decorator”这个词是词汇表的链接,它告诉我们:

装饰工

返回另一个函数的函数,通常使用@wrapper语法将其用作函数转换。装饰器的常见示例是classmethod()staticmethod()

装饰器语法只是语法糖,以下两个函数定义在语义上是等效的:

def f(...):
    ...
f = staticmethod(f)

@staticmethod
def f(...):
    ...

类存在相同的概念,但在该类中较少使用。有关装饰器的更多信息,请参见函数定义和类定义的文档。

所以,我们看到

@foo
def bar():
    pass

在语义上与:

def bar():
    pass

bar = foo(bar)

它们并不完全相同,因为Python在装饰器(@)语法之前在bar之前评估foo表达式(可能是点分查找和函数调用),但在另一种情况下,则 bar 之后评估foo表达式。

(如果这种差异使代码的含义有所不同,则应重新考虑自己的生活,因为那会是病态的。)

堆叠式装饰器

如果我们回到函数定义语法文档,则会看到:

@f1(arg)
@f2
def func(): pass

大致相当于

def func(): pass
func = f1(arg)(f2(func))

这是一个演示,我们可以调用首先是装饰器的函数以及堆栈装饰器。在Python中,函数是一流的对象-这意味着您可以将一个函数作为参数传递给另一个函数,然后返回函数。装饰者可以做这两种事情。

如果我们堆叠装饰器,则已定义的函数会首先传递到紧接其上的装饰器,然后传递给下一个,依此类推。

这就总结了@装饰器上下文中的用法。

运营商, @

在语言参考的词法分析部分,我们有一个关于运算符部分,其中包括@,这使得它同时也是一个运算符:

以下标记是运算符:

+       -       *       **      /       //      %      @
<<      >>      &       |       ^       ~
<       >       <=      >=      ==      !=

在下一页的数据模型中,我们有模拟数字类型一节,

object.__add__(self, other)
object.__sub__(self, other) 
object.__mul__(self, other) 
object.__matmul__(self, other) 
object.__truediv__(self, other) 
object.__floordiv__(self, other)

[…]这些方法称为执行二进制算术运算(+-*@///,[…]

我们看到__matmul__对应于@。如果我们在文档中搜索“ matmul” ,则会在标题“ PEP 465-矩阵乘法的专用中缀运算符”下获得指向“ matmul”的Python 3.5新增功能的链接。

可以通过定义__matmul__()__rmatmul__()以及 __imatmul__()常规,反射和就地矩阵乘法来实现。

(所以现在我们了解到它@=是就地版本)。它进一步说明:

在数学,科学,工程学的许多领域中,矩阵乘法是一种常见的操作,并且@的加法允许编写更简洁的代码:

S = (H @ beta - r).T @ inv(H @ V @ H.T) @ (H @ beta - r)

代替:

S = dot((dot(H, beta) - r).T,
        dot(inv(dot(dot(H, V), H.T)), dot(H, beta) - r))

尽管可以重载该运算符以执行几乎所有操作,numpy例如,在中,我们将使用以下语法来计算数组和矩阵的内乘和外乘:

>>> from numpy import array, matrix
>>> array([[1,2,3]]).T @ array([[1,2,3]])
array([[1, 2, 3],
       [2, 4, 6],
       [3, 6, 9]])
>>> array([[1,2,3]]) @ array([[1,2,3]]).T
array([[14]])
>>> matrix([1,2,3]).T @ matrix([1,2,3])
matrix([[1, 2, 3],
        [2, 4, 6],
        [3, 6, 9]])
>>> matrix([1,2,3]) @ matrix([1,2,3]).T
matrix([[14]])

就地矩阵乘法: @=

在研究现有用法时,我们了解到还有就地矩阵乘法。如果尝试使用它,我们可能会发现尚未为numpy实现它:

>>> m = matrix([1,2,3])
>>> m @= m.T
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: In-place matrix multiplication is not (yet) supported. Use 'a = a @ b' instead of 'a @= b'.

实施后,我希望结果看起来像这样:

>>> m = matrix([1,2,3])
>>> m @= m.T
>>> m
matrix([[14]])

What does the “at” (@) symbol do in Python?

In short, it is used in decorator syntax and for matrix multiplication.

In the context of decorators, this syntax:

@decorator
def decorated_function():
    """this function is decorated"""

is equivalent to this:

def decorated_function():
    """this function is decorated"""

decorated_function = decorator(decorated_function)

In the context of matrix multiplication, a @ b invokes a.__matmul__(b) – making this syntax:

a @ b

equivalent to

dot(a, b)

and

a @= b

equivalent to

a = dot(a, b)

where dot is, for example, the numpy matrix multiplication function and a and b are matrices.

How could you discover this on your own?

I also do not know what to search for as searching Python docs or Google does not return relevant results when the @ symbol is included.

If you want to have a rather complete view of what a particular piece of python syntax does, look directly at the grammar file. For the Python 3 branch:

~$ grep -C 1 "@" cpython/Grammar/Grammar 

decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE
decorators: decorator+
--
testlist_star_expr: (test|star_expr) (',' (test|star_expr))* [',']
augassign: ('+=' | '-=' | '*=' | '@=' | '/=' | '%=' | '&=' | '|=' | '^=' |
            '<<=' | '>>=' | '**=' | '//=')
--
arith_expr: term (('+'|'-') term)*
term: factor (('*'|'@'|'/'|'%'|'//') factor)*
factor: ('+'|'-'|'~') factor | power

We can see here that @ is used in three contexts:

  • decorators
  • an operator between factors
  • an augmented assignment operator

Decorator Syntax:

A google search for “decorator python docs” gives as one of the top results, the “Compound Statements” section of the “Python Language Reference.” Scrolling down to the section on function definitions, which we can find by searching for the word, “decorator”, we see that… there’s a lot to read. But the word, “decorator” is a link to the glossary, which tells us:

decorator

A function returning another function, usually applied as a function transformation using the @wrapper syntax. Common examples for decorators are classmethod() and staticmethod().

The decorator syntax is merely syntactic sugar, the following two function definitions are semantically equivalent:

def f(...):
    ...
f = staticmethod(f)

@staticmethod
def f(...):
    ...

The same concept exists for classes, but is less commonly used there. See the documentation for function definitions and class definitions for more about decorators.

So, we see that

@foo
def bar():
    pass

is semantically the same as:

def bar():
    pass

bar = foo(bar)

They are not exactly the same because Python evaluates the foo expression (which could be a dotted lookup and a function call) before bar with the decorator (@) syntax, but evaluates the foo expression after bar in the other case.

(If this difference makes a difference in the meaning of your code, you should reconsider what you’re doing with your life, because that would be pathological.)

Stacked Decorators

If we go back to the function definition syntax documentation, we see:

@f1(arg)
@f2
def func(): pass

is roughly equivalent to

def func(): pass
func = f1(arg)(f2(func))

This is a demonstration that we can call a function that’s a decorator first, as well as stack decorators. Functions, in Python, are first class objects – which means you can pass a function as an argument to another function, and return functions. Decorators do both of these things.

If we stack decorators, the function, as defined, gets passed first to the decorator immediately above it, then the next, and so on.

That about sums up the usage for @ in the context of decorators.

The Operator, @

In the lexical analysis section of the language reference, we have a section on operators, which includes @, which makes it also an operator:

The following tokens are operators:

+       -       *       **      /       //      %      @
<<      >>      &       |       ^       ~
<       >       <=      >=      ==      !=

and in the next page, the Data Model, we have the section Emulating Numeric Types,

object.__add__(self, other)
object.__sub__(self, other) 
object.__mul__(self, other) 
object.__matmul__(self, other) 
object.__truediv__(self, other) 
object.__floordiv__(self, other)

[…] These methods are called to implement the binary arithmetic operations (+, -, *, @, /, //, […]

And we see that __matmul__ corresponds to @. If we search the documentation for “matmul” we get a link to What’s new in Python 3.5 with “matmul” under a heading “PEP 465 – A dedicated infix operator for matrix multiplication”.

it can be implemented by defining __matmul__(), __rmatmul__(), and __imatmul__() for regular, reflected, and in-place matrix multiplication.

(So now we learn that @= is the in-place version). It further explains:

Matrix multiplication is a notably common operation in many fields of mathematics, science, engineering, and the addition of @ allows writing cleaner code:

S = (H @ beta - r).T @ inv(H @ V @ H.T) @ (H @ beta - r)

instead of:

S = dot((dot(H, beta) - r).T,
        dot(inv(dot(dot(H, V), H.T)), dot(H, beta) - r))

While this operator can be overloaded to do almost anything, in numpy, for example, we would use this syntax to calculate the inner and outer product of arrays and matrices:

>>> from numpy import array, matrix
>>> array([[1,2,3]]).T @ array([[1,2,3]])
array([[1, 2, 3],
       [2, 4, 6],
       [3, 6, 9]])
>>> array([[1,2,3]]) @ array([[1,2,3]]).T
array([[14]])
>>> matrix([1,2,3]).T @ matrix([1,2,3])
matrix([[1, 2, 3],
        [2, 4, 6],
        [3, 6, 9]])
>>> matrix([1,2,3]) @ matrix([1,2,3]).T
matrix([[14]])

Inplace matrix multiplication: @=

While researching the prior usage, we learn that there is also the inplace matrix multiplication. If we attempt to use it, we may find it is not yet implemented for numpy:

>>> m = matrix([1,2,3])
>>> m @= m.T
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: In-place matrix multiplication is not (yet) supported. Use 'a = a @ b' instead of 'a @= b'.

When it is implemented, I would expect the result to look like this:

>>> m = matrix([1,2,3])
>>> m @= m.T
>>> m
matrix([[14]])

回答 5

Python中的“ @”(@)符号有什么作用?

@符号是python提供的语法糖decorator
以解释这个问题,这恰恰是关于decorator在Python中的作用?

简而言之,decorator您可以修改给定函数的定义,而无需触摸其最内层(即封闭)。
从第三方导入精美的包时,最常见的情况是。您可以可视化它,可以使用它,但不能触摸它的最内层和内心。

这是一个简单的示例,
假设我read_a_book在Ipython上定义了一个函数

In [9]: def read_a_book():
   ...:     return "I am reading the book: "
   ...: 
In [10]: read_a_book()
Out[10]: 'I am reading the book: '

你看,我忘了给它加一个名字。
如何解决这样的问题?当然,我可以将函数重新定义为:

def read_a_book():
    return "I am reading the book: 'Python Cookbook'"

但是,如果不允许我操作原始功能,或者要处理成千上万个此类功能,该怎么办。

通过不同的思维来解决问题并定义一个new_function

def add_a_book(func):
    def wrapper():
        return func() + "Python Cookbook"
    return wrapper

然后雇用它。

In [14]: read_a_book = add_a_book(read_a_book)
In [15]: read_a_book()
Out[15]: 'I am reading the book: Python Cookbook'

Tada,您知道,我在read_a_book不触及内部封闭的情况下进行了修改。没有什么可以阻止我装备decorator

关于什么 @

@add_a_book
def read_a_book():
    return "I am reading the book: "
In [17]: read_a_book()
Out[17]: 'I am reading the book: Python Cookbook'

@add_a_book这是一种花哨且方便的表达方式read_a_book = add_a_book(read_a_book),它是一种语法糖,没有比这更奇特的了。

What does the “at” (@) symbol do in Python?

@ symbol is a syntactic sugar python provides to utilize decorator,
to paraphrase the question, It’s exactly about what does decorator do in Python?

Put it simple decorator allow you to modify a given function’s definition without touch its innermost (it’s closure).
It’s the most case when you import wonderful package from third party. You can visualize it, you can use it, but you cannot touch its innermost and its heart.

Here is a quick example,
suppose I define a read_a_book function on Ipython

In [9]: def read_a_book():
   ...:     return "I am reading the book: "
   ...: 
In [10]: read_a_book()
Out[10]: 'I am reading the book: '

You see, I forgot to add a name to it.
How to solve such a problem? Of course, I could re-define the function as:

def read_a_book():
    return "I am reading the book: 'Python Cookbook'"

Nevertheless, what if I’m not allowed to manipulate the original function, or if there are thousands of such function to be handled.

Solve the problem by thinking different and define a new_function

def add_a_book(func):
    def wrapper():
        return func() + "Python Cookbook"
    return wrapper

Then employ it.

In [14]: read_a_book = add_a_book(read_a_book)
In [15]: read_a_book()
Out[15]: 'I am reading the book: Python Cookbook'

Tada, you see, I amended read_a_book without touching it inner closure. Nothing stops me equipped with decorator.

What’s about @

@add_a_book
def read_a_book():
    return "I am reading the book: "
In [17]: read_a_book()
Out[17]: 'I am reading the book: Python Cookbook'

@add_a_book is a fancy and handy way to say read_a_book = add_a_book(read_a_book), it’s a syntactic sugar, there’s nothing more fancier about it.


回答 6

如果您在使用Numpy库的python笔记本中引用某些代码,则@ operator表示矩阵乘法。例如:

import numpy as np
def forward(xi, W1, b1, W2, b2):
    z1 = W1 @ xi + b1
    a1 = sigma(z1)
    z2 = W2 @ a1 + b2
    return z2, a1

If you are referring to some code in a python notebook which is using Numpy library, then @ operator means Matrix Multiplication. For example:

import numpy as np
def forward(xi, W1, b1, W2, b2):
    z1 = W1 @ xi + b1
    a1 = sigma(z1)
    z2 = W2 @ a1 + b2
    return z2, a1

回答 7

从Python 3.5开始,“ @”用作MATRIX MULTIPLICATION(PEP 0465-参见https://www.python.org/dev/peps/pep-0465/)的专用中缀符号。

Starting with Python 3.5, the ‘@’ is used as a dedicated infix symbol for MATRIX MULTIPLICATION (PEP 0465 — see https://www.python.org/dev/peps/pep-0465/)


回答 8

在Python中添加了装饰器,以使函数和方法包装(接收函数并返回增强函数的函数)更易于阅读和理解。最初的用例是能够在定义的顶部将方法定义为类方法或静态方法。没有装饰器语法,将需要一个相当稀疏且重复的定义:

class WithoutDecorators:
def some_static_method():
    print("this is static method")
some_static_method = staticmethod(some_static_method)

def some_class_method(cls):
    print("this is class method")
some_class_method = classmethod(some_class_method)

如果将装饰器语法用于相同目的,则代码将更短且更易于理解:

class WithDecorators:
    @staticmethod
    def some_static_method():
        print("this is static method")

    @classmethod
    def some_class_method(cls):
        print("this is class method")

通用语法和可能的实现

装饰器通常是一个命名对象(不允许使用lambda表达式),该对象在被调用时将接受单个参数(它将成为装饰后的函数)并返回另一个可调用对象。此处使用“可调用”代替带有预想的“功能”。尽管装饰器通常在方法和功能的范围内进行讨论,但它们不限于此。实际上,任何可调用的对象(实现_call__方法的任何对象都被视为可调用对象)可以用作修饰符,并且它们返回的对象通常不是简单的函数,而是更多复杂类的实例,这些实例实现了自己的__call_方法。

装饰器语法只是一个语法糖。考虑以下装饰器用法:

@some_decorator
def decorated_function():
    pass

总是可以用显式的装饰器调用和函数重新分配来代替:

def decorated_function():
    pass
decorated_function = some_decorator(decorated_function)

但是,如果在单个函数上使用多个装饰器,则后者的可读性较低,并且也很难理解。可以以多种不同方式使用装饰器,如下所示:

作为功​​能

编写自定义装饰器的方法有很多,但是最简单的方法是编写一个函数,该函数返回包装原始函数调用的子函数。

通用模式如下:

def mydecorator(function):
    def wrapped(*args, **kwargs):
        # do some stuff before the original
        # function gets called
        result = function(*args, **kwargs)
        # do some stuff after function call and
        # return the result
        return result
    # return wrapper as a decorated function
    return wrapped

上课

尽管装饰器几乎总是可以使用函数来实现,但在某些情况下,使用用户定义的类是更好的选择。当装饰器需要复杂的参数化或取决于特定状态时,通常会发生这种情况。

非参数化装饰器作为类的通用模式如下:

class DecoratorAsClass:
    def __init__(self, function):
        self.function = function

    def __call__(self, *args, **kwargs):
        # do some stuff before the original
        # function gets called
        result = self.function(*args, **kwargs)
        # do some stuff after function call and
        # return the result
        return result

参数化装饰器

在实际代码中,经常需要使用可以参数化的装饰器。当将该函数用作装饰器时,解决方案很简单-必须使用第二层包装。这是装饰器的一个简单示例,该装饰器每次被调用都会重复执行装饰函数指定次数:

def repeat(number=3):
"""Cause decorated function to be repeated a number of times.

Last value of original function call is returned as a result
:param number: number of repetitions, 3 if not specified
"""
def actual_decorator(function):
    def wrapper(*args, **kwargs):
        result = None
        for _ in range(number):
            result = function(*args, **kwargs)
        return result
    return wrapper
return actual_decorator

通过这种方式定义的装饰器可以接受参数:

>>> @repeat(2)
... def foo():
...     print("foo")
...
>>> foo()
foo
foo

请注意,即使参数化装饰器的参数具有默认值,也必须在其名称后加上括号。使用带有默认参数的前面装饰器的正确方法如下:

>>> @repeat()
... def bar():
...     print("bar")
...
>>> bar()
bar
bar
bar

最后,让我们看看带有Properties的装饰器。

物产

这些属性提供了一个内置的描述符类型,该描述符类型知道如何将属性链接到一组方法。一个属性带有四个可选参数:fget,fset,fdel和doc。可以提供最后一个来定义链接到属性的文档字符串,就好像它是方法一样。这是一个Rectangle类的示例,可以通过直接访问存储两个角点的属性或使用width和height属性来控制它:

class Rectangle:
    def __init__(self, x1, y1, x2, y2):
        self.x1, self.y1 = x1, y1
        self.x2, self.y2 = x2, y2

    def _width_get(self):
        return self.x2 - self.x1

    def _width_set(self, value):
        self.x2 = self.x1 + value

    def _height_get(self):
        return self.y2 - self.y1

    def _height_set(self, value):
        self.y2 = self.y1 + value

    width = property(
        _width_get, _width_set,
        doc="rectangle width measured from left"
    )
    height = property(
        _height_get, _height_set,
        doc="rectangle height measured from top"
    )

    def __repr__(self):
        return "{}({}, {}, {}, {})".format(
            self.__class__.__name__,
            self.x1, self.y1, self.x2, self.y2
    )

创建属性的最佳语法是使用属性作为装饰器。这将减少类内部方法签名的数量,并使代码更具可读性和可维护性。使用装饰器,以上类变为:

class Rectangle:
    def __init__(self, x1, y1, x2, y2):
        self.x1, self.y1 = x1, y1
        self.x2, self.y2 = x2, y2

    @property
    def width(self):
        """rectangle height measured from top"""
        return self.x2 - self.x1

    @width.setter
    def width(self, value):
        self.x2 = self.x1 + value

    @property
    def height(self):
        """rectangle height measured from top"""
        return self.y2 - self.y1

    @height.setter
    def height(self, value):
        self.y2 = self.y1 + value

Decorators were added in Python to make function and method wrapping (a function that receives a function and returns an enhanced one) easier to read and understand. The original use case was to be able to define the methods as class methods or static methods on the head of their definition. Without the decorator syntax, it would require a rather sparse and repetitive definition:

class WithoutDecorators:
def some_static_method():
    print("this is static method")
some_static_method = staticmethod(some_static_method)

def some_class_method(cls):
    print("this is class method")
some_class_method = classmethod(some_class_method)

If the decorator syntax is used for the same purpose, the code is shorter and easier to understand:

class WithDecorators:
    @staticmethod
    def some_static_method():
        print("this is static method")

    @classmethod
    def some_class_method(cls):
        print("this is class method")

General syntax and possible implementations

The decorator is generally a named object ( lambda expressions are not allowed) that accepts a single argument when called (it will be the decorated function) and returns another callable object. “Callable” is used here instead of “function” with premeditation. While decorators are often discussed in the scope of methods and functions, they are not limited to them. In fact, anything that is callable (any object that implements the _call__ method is considered callable), can be used as a decorator and often objects returned by them are not simple functions but more instances of more complex classes implementing their own __call_ method.

The decorator syntax is simply only a syntactic sugar. Consider the following decorator usage:

@some_decorator
def decorated_function():
    pass

This can always be replaced by an explicit decorator call and function reassignment:

def decorated_function():
    pass
decorated_function = some_decorator(decorated_function)

However, the latter is less readable and also very hard to understand if multiple decorators are used on a single function. Decorators can be used in multiple different ways as shown below:

As a function

There are many ways to write custom decorators, but the simplest way is to write a function that returns a subfunction that wraps the original function call.

The generic patterns is as follows:

def mydecorator(function):
    def wrapped(*args, **kwargs):
        # do some stuff before the original
        # function gets called
        result = function(*args, **kwargs)
        # do some stuff after function call and
        # return the result
        return result
    # return wrapper as a decorated function
    return wrapped

As a class

While decorators almost always can be implemented using functions, there are some situations when using user-defined classes is a better option. This is often true when the decorator needs complex parametrization or it depends on a specific state.

The generic pattern for a nonparametrized decorator as a class is as follows:

class DecoratorAsClass:
    def __init__(self, function):
        self.function = function

    def __call__(self, *args, **kwargs):
        # do some stuff before the original
        # function gets called
        result = self.function(*args, **kwargs)
        # do some stuff after function call and
        # return the result
        return result

Parametrizing decorators

In real code, there is often a need to use decorators that can be parametrized. When the function is used as a decorator, then the solution is simple—a second level of wrapping has to be used. Here is a simple example of the decorator that repeats the execution of a decorated function the specified number of times every time it is called:

def repeat(number=3):
"""Cause decorated function to be repeated a number of times.

Last value of original function call is returned as a result
:param number: number of repetitions, 3 if not specified
"""
def actual_decorator(function):
    def wrapper(*args, **kwargs):
        result = None
        for _ in range(number):
            result = function(*args, **kwargs)
        return result
    return wrapper
return actual_decorator

The decorator defined this way can accept parameters:

>>> @repeat(2)
... def foo():
...     print("foo")
...
>>> foo()
foo
foo

Note that even if the parametrized decorator has default values for its arguments, the parentheses after its name is required. The correct way to use the preceding decorator with default arguments is as follows:

>>> @repeat()
... def bar():
...     print("bar")
...
>>> bar()
bar
bar
bar

Finally lets see decorators with Properties.

Properties

The properties provide a built-in descriptor type that knows how to link an attribute to a set of methods. A property takes four optional arguments: fget , fset , fdel , and doc . The last one can be provided to define a docstring that is linked to the attribute as if it were a method. Here is an example of a Rectangle class that can be controlled either by direct access to attributes that store two corner points or by using the width , and height properties:

class Rectangle:
    def __init__(self, x1, y1, x2, y2):
        self.x1, self.y1 = x1, y1
        self.x2, self.y2 = x2, y2

    def _width_get(self):
        return self.x2 - self.x1

    def _width_set(self, value):
        self.x2 = self.x1 + value

    def _height_get(self):
        return self.y2 - self.y1

    def _height_set(self, value):
        self.y2 = self.y1 + value

    width = property(
        _width_get, _width_set,
        doc="rectangle width measured from left"
    )
    height = property(
        _height_get, _height_set,
        doc="rectangle height measured from top"
    )

    def __repr__(self):
        return "{}({}, {}, {}, {})".format(
            self.__class__.__name__,
            self.x1, self.y1, self.x2, self.y2
    )

The best syntax for creating properties is using property as a decorator. This will reduce the number of method signatures inside of the class and make code more readable and maintainable. With decorators the above class becomes:

class Rectangle:
    def __init__(self, x1, y1, x2, y2):
        self.x1, self.y1 = x1, y1
        self.x2, self.y2 = x2, y2

    @property
    def width(self):
        """rectangle height measured from top"""
        return self.x2 - self.x1

    @width.setter
    def width(self, value):
        self.x2 = self.x1 + value

    @property
    def height(self):
        """rectangle height measured from top"""
        return self.y2 - self.y1

    @height.setter
    def height(self, value):
        self.y2 = self.y1 + value

回答 9

用其他方式说出别人的想法:是的,它是一个装饰器。

在Python中,就像:

  1. 创建一个函数(在@调用之后)
  2. 调用另一个函数以对您创建的函数进行操作。这将返回一个新函数。您调用的函数是@的参数。
  3. 用返回的新函数替换定义的函数。

这可以用于各种有用的东西,因为功能是对象,而只是指令而已,因此成为可能。

To say what others have in a different way: yes, it is a decorator.

In Python, it’s like:

  1. Creating a function (follows under the @ call)
  2. Calling another function to operate on your created function. This returns a new function. The function that you call is the argument of the @.
  3. Replacing the function defined with the new function returned.

This can be used for all kinds of useful things, made possible because functions are objects and just necessary just instructions.


回答 10

@符号还用于访问plydata / pandas数据框查询中的变量pandas.DataFrame.query。例:

df = pandas.DataFrame({'foo': [1,2,15,17]})
y = 10
df >> query('foo > @y') # plydata
df.query('foo > @y') # pandas

@ symbol is also used to access variables inside a plydata / pandas dataframe query, pandas.DataFrame.query. Example:

df = pandas.DataFrame({'foo': [1,2,15,17]})
y = 10
df >> query('foo > @y') # plydata
df.query('foo > @y') # pandas

回答 11

它表明您正在使用装饰器。这是Bruce Eckel在2008年的例子

It indicates that you are using a decorator. Here is Bruce Eckel’s example from 2008.


Python模块和Python包之间有什么区别?

问题:Python模块和Python包之间有什么区别?

Python模块和Python包之间有什么区别?

另请参阅:“程序包”和“模块”之间有什么区别(对于其他语言)

What’s the difference between a Python module and a Python package?

See also: What’s the difference between “package” and “module” (for other languages)


回答 0

模块是在一个导入下导入并使用的单个文件。例如

import my_module

软件包是目录中提供软件包层次结构的模块的集合。

from my_package.timing.danger.internets import function_of_love

模块文档

套餐介绍

A module is a single file (or files) that are imported under one import and used. e.g.

import my_module

A package is a collection of modules in directories that give a package hierarchy.

from my_package.timing.danger.internets import function_of_love

Documentation for modules

Introduction to packages


回答 1

任何Python文件都是一个模块,其名称是文件的基础名称,不带.py扩展名。甲是Python模块的集合:而一个模块是一个Python文件,一个包是含有一个额外的Python模块的目录__init__.py文件中,一个包从恰好包含一堆Python脚本的一个目录区分开。包可以嵌套到任何深度,只要相应的目录包含它们自己的__init__.py文件即可。

模块和软件包之间的区别似乎仅在文件系统级别上存在。导入模块或包时,Python创建的相应对象始终为类型module。但是请注意,当您导入软件包时,仅__init__.py该软件包文件中的变量/函数/类是直接可见的,子软件包或模块则不可见。例如,考虑xmlPython标准库中的包:其xml目录包含一个__init__.py文件和四个子目录;子目录etree包含一个__init__.py文件,以及其他ElementTree.py文件。查看当您尝试以交互方式导入包/模块时会发生什么:

>>> import xml
>>> type(xml)
<type 'module'>
>>> xml.etree.ElementTree
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute 'etree'
>>> import xml.etree
>>> type(xml.etree)
<type 'module'>
>>> xml.etree.ElementTree
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute 'ElementTree'
>>> import xml.etree.ElementTree
>>> type(xml.etree.ElementTree)
<type 'module'>
>>> xml.etree.ElementTree.parse
<function parse at 0x00B135B0>

在Python中,还有一些内置模块(例如)sys,这些模块都是用C语言编写的,但我认为您并不是要考虑问题中的那些模块。

Any Python file is a module, its name being the file’s base name without the .py extension. A package is a collection of Python modules: while a module is a single Python file, a package is a directory of Python modules containing an additional __init__.py file, to distinguish a package from a directory that just happens to contain a bunch of Python scripts. Packages can be nested to any depth, provided that the corresponding directories contain their own __init__.py file.

The distinction between module and package seems to hold just at the file system level. When you import a module or a package, the corresponding object created by Python is always of type module. Note, however, when you import a package, only variables/functions/classes in the __init__.py file of that package are directly visible, not sub-packages or modules. As an example, consider the xml package in the Python standard library: its xml directory contains an __init__.py file and four sub-directories; the sub-directory etree contains an __init__.py file and, among others, an ElementTree.py file. See what happens when you try to interactively import package/modules:

>>> import xml
>>> type(xml)
<type 'module'>
>>> xml.etree.ElementTree
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute 'etree'
>>> import xml.etree
>>> type(xml.etree)
<type 'module'>
>>> xml.etree.ElementTree
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute 'ElementTree'
>>> import xml.etree.ElementTree
>>> type(xml.etree.ElementTree)
<type 'module'>
>>> xml.etree.ElementTree.parse
<function parse at 0x00B135B0>

In Python there also are built-in modules, such as sys, that are written in C, but I don’t think you meant to consider those in your question.


回答 2

Python词汇表中

重要的是要记住,所有软件包都是模块,但并非所有模块都是软件包。换句话说,包只是一种特殊的模块。具体来说,任何包含__path__属性的模块都被视为包。

名称中带有破折号的Python文件(如my-file.py)无法通过简单的import语句导入。代码明智的,import my-file是一样的import my - file,这将引发异常。这样的文件可以更好地描述为脚本,而可导入文件是模块

From the Python glossary:

It’s important to keep in mind that all packages are modules, but not all modules are packages. Or put another way, packages are just a special kind of module. Specifically, any module that contains a __path__ attribute is considered a package.

Python files with a dash in the name, like my-file.py, cannot be imported with a simple import statement. Code-wise, import my-file is the same as import my - file which will raise an exception. Such files are better characterized as scripts whereas importable files are modules.


回答 3

首先,请记住,按照其精确定义,模块是Python解释器内存中的对象,通常是通过从磁盘读取一个或多个文件来创建的。虽然我们可以非正式地称呼磁盘文件(例如a/b/c.py“模块”),但实际上它并没有与其他来自其他来源(例如sys.path)的信息组合在一起以创建模块对象,而是变成一个文件。

(例如,请注意,可以根据相同的sys.path设置和其他设置,从同一个文件中加载名称不同的两个模块。这正是在解释器中python -m my.module后面跟着的情况import my.module;将有两个模块对象,__main__并且my.module都创建了来自磁盘上的同一文件,my/module.py。)

是可以具有子模块(包括子包)的模块。并非所有模块都能做到这一点。例如,创建一个小的模块层次结构:

$ mkdir -p a/b
$ touch a/b/c.py

确保下没有其他文件a。启动Python 3.4或更高版本的解释器(例如,使用python3 -i)并检查以下语句的结果:

import a
a                 <module 'a' (namespace)>
a.b               AttributeError: module 'a' has no attribute 'b'
import a.b.c
a.b               <module 'a.b' (namespace)>
a.b.c             <module 'a.b.c' from '/home/cjs/a/b/c.py'>

模块aa.b是程序包(实际上,一种程序包称为“命名空间程序包”,尽管我们在这里不必担心)。但是,模块a.b.c不是包。我们可以通过a/b.py在上面的目录结构中添加另一个文件并启动一个新的解释器来演示这一点:

import a.b.c
 ImportError: No module named 'a.b.c'; 'a.b' is not a package
import a.b
a                 <module 'a' (namespace)>
a.__path__        _NamespacePath(['/.../a'])
a.b               <module 'a.b' from '/home/cjs/tmp/a/b.py'>
a.b.__path__      AttributeError: 'module' object has no attribute '__path__'

Python确保在加载子模块之前先加载所有父模块。在其上方找到a/一个目录,因此创建了一个命名空间包a,这a/b.py是一个Python源文件,它被加载并用于创建(非包)模块a.b。此时,您无法拥有模块,a.b.c因为a.b它不是软件包,因此不能拥有子模块。

您还可以在此处看到package模块a具有__path__属性(packages必须具有此属性),但非package模块a.b则没有。

First, keep in mind that, in its precise definition, a module is an object in the memory of a Python interpreter, often created by reading one or more files from disk. While we may informally call a disk file such as a/b/c.py a “module,” it doesn’t actually become one until it’s combined with information from several other sources (such as sys.path) to create the module object.

(Note, for example, that two modules with different names can be loaded from the same file, depending on sys.path and other settings. This is exactly what happens with python -m my.module followed by an import my.module in the interpreter; there will be two module objects, __main__ and my.module, both created from the same file on disk, my/module.py.)

A package is a module that may have submodules (including subpackages). Not all modules can do this. As an example, create a small module hierarchy:

$ mkdir -p a/b
$ touch a/b/c.py

Ensure that there are no other files under a. Start a Python 3.4 or later interpreter (e.g., with python3 -i) and examine the results of the following statements:

import a
a                ⇒ <module 'a' (namespace)>
a.b              ⇒ AttributeError: module 'a' has no attribute 'b'
import a.b.c
a.b              ⇒ <module 'a.b' (namespace)>
a.b.c            ⇒ <module 'a.b.c' from '/home/cjs/a/b/c.py'>

Modules a and a.b are packages (in fact, a certain kind of package called a “namespace package,” though we wont’ worry about that here). However, module a.b.c is not a package. We can demonstrate this by adding another file, a/b.py to the directory structure above and starting a fresh interpreter:

import a.b.c
⇒ ImportError: No module named 'a.b.c'; 'a.b' is not a package
import a.b
a                ⇒ <module 'a' (namespace)>
a.__path__       ⇒ _NamespacePath(['/.../a'])
a.b              ⇒ <module 'a.b' from '/home/cjs/tmp/a/b.py'>
a.b.__path__     ⇒ AttributeError: 'module' object has no attribute '__path__'

Python ensures that all parent modules are loaded before a child module is loaded. Above it finds that a/ is a directory, and so creates a namespace package a, and that a/b.py is a Python source file which it loads and uses to create a (non-package) module a.b. At this point you cannot have a module a.b.c because a.b is not a package, and thus cannot have submodules.

You can also see here that the package module a has a __path__ attribute (packages must have this) but the non-package module a.b does not.


回答 4

一个较晚的答案,还有另一个定义:

包由导入的顶级实体表示,该顶级实体可以是一个独立的模块,也可以是__init__.py特殊模块,它是子目录结构中一组模块中的顶级实体。

因此,从物理上说,包装就是一个分配单元,它提供一个或多个模块。

A late answer, yet another definition:

A package is represented by an imported top-entity which could either be a self-contained module, or the __init__.py special module as the top-entity from a set of modules within a sub directory structure.

So physically a package is a distribution unit, which provides one or more modules.


回答 5

包也是一个模块,可以包含其他模块,“基于文件的简单模块和包(子包)”。与模块的包装类型相关的代码进入该__init__.py文件。

import pack1
print(type(pack1))

而模块是一个简单的文件,可以包含函数,类,可运行代码等。导入模块后,它的行为就像一个对象,您可以通过该对象访问模块中定义的标识符。

The Package is also a module that can contain other modules, ‘simple file-based modules, and packages (sub-package)’. The code related to the package type of module goes into the __init__.py file.

import pack1
print(type(pack1))

whereas modules are a simple file that can contain functions, classes, runnable code, etc. after importing a module it behaves like an object by which you can access the identifiers defined in the module.


如何将字符串拆分为列表?

问题:如何将字符串拆分为列表?

我希望我的Python函数拆分一个句子(输入)并将每个单词存储在列表中。我当前的代码拆分了句子,但没有将单词存储为列表。我怎么做?

def split_line(text):

    # split the text
    words = text.split()

    # for each word in the line:
    for word in words:

        # print the word
        print(words)

I want my Python function to split a sentence (input) and store each word in a list. My current code splits the sentence, but does not store the words as a list. How do I do that?

def split_line(text):

    # split the text
    words = text.split()

    # for each word in the line:
    for word in words:

        # print the word
        print(words)

回答 0

text.split()

这应该足以将每个单词存储在列表中。 words已经是句子中单词的列表,因此不需要循环。

其次,这可能是一个错字,但是您的循环有点混乱。如果您确实确实想使用附加,它将是:

words.append(word)

word.append(words)
text.split()

This should be enough to store each word in a list. words is already a list of the words from the sentence, so there is no need for the loop.

Second, it might be a typo, but you have your loop a little messed up. If you really did want to use append, it would be:

words.append(word)

not

word.append(words)

回答 1

text在任何连续的空格运行中拆分字符串。

words = text.split()      

text在分隔符上分割字符串","

words = text.split(",")   

单词变量将为a,list并包含text分隔符上的split 单词。

Splits the string in text on any consecutive runs of whitespace.

words = text.split()      

Split the string in text on delimiter: ",".

words = text.split(",")   

The words variable will be a list and contain the words from text split on the delimiter.


回答 2

str.split()

返回字符串中的单词列表,使用sep作为定界符…如果未指定sep或为None,则应用不同的拆分算法:连续空格的运行被视为单个分隔符,并且结果将包含如果字符串的开头或结尾有空格,则开头或结尾不得有空字符串。

>>> line="a sentence with a few words"
>>> line.split()
['a', 'sentence', 'with', 'a', 'few', 'words']
>>> 

str.split()

Return a list of the words in the string, using sep as the delimiter … If sep is not specified or is None, a different splitting algorithm is applied: runs of consecutive whitespace are regarded as a single separator, and the result will contain no empty strings at the start or end if the string has leading or trailing whitespace.

>>> line="a sentence with a few words"
>>> line.split()
['a', 'sentence', 'with', 'a', 'few', 'words']
>>> 

回答 3

根据您打算如何处理列表中的句子,您可能需要查看Natural Language Took Kit。它主要处理文本处理和评估。您也可以使用它来解决您的问题:

import nltk
words = nltk.word_tokenize(raw_sentence)

这具有将标点符号分开的额外好处。

例:

>>> import nltk
>>> s = "The fox's foot grazed the sleeping dog, waking it."
>>> words = nltk.word_tokenize(s)
>>> words
['The', 'fox', "'s", 'foot', 'grazed', 'the', 'sleeping', 'dog', ',', 
'waking', 'it', '.']

这使您可以过滤掉不需要的标点,而仅使用单词。

请注意,string.split()如果您不打算对句子进行任何复杂的处理,则使用其他解决方案会更好。

[编辑]

Depending on what you plan to do with your sentence-as-a-list, you may want to look at the Natural Language Took Kit. It deals heavily with text processing and evaluation. You can also use it to solve your problem:

import nltk
words = nltk.word_tokenize(raw_sentence)

This has the added benefit of splitting out punctuation.

Example:

>>> import nltk
>>> s = "The fox's foot grazed the sleeping dog, waking it."
>>> words = nltk.word_tokenize(s)
>>> words
['The', 'fox', "'s", 'foot', 'grazed', 'the', 'sleeping', 'dog', ',', 
'waking', 'it', '.']

This allows you to filter out any punctuation you don’t want and use only words.

Please note that the other solutions using string.split() are better if you don’t plan on doing any complex manipulation of the sentence.

[Edited]


回答 4

这个算法怎么样?在空白处分割文本,然后修剪标点符号。这会仔细删除单词边缘的标点符号,而不会损害单词内的撇号,例如we're

>>> text
"'Oh, you can't help that,' said the Cat: 'we're all mad here. I'm mad. You're mad.'"

>>> text.split()
["'Oh,", 'you', "can't", 'help', "that,'", 'said', 'the', 'Cat:', "'we're", 'all', 'mad', 'here.', "I'm", 'mad.', "You're", "mad.'"]

>>> import string
>>> [word.strip(string.punctuation) for word in text.split()]
['Oh', 'you', "can't", 'help', 'that', 'said', 'the', 'Cat', "we're", 'all', 'mad', 'here', "I'm", 'mad', "You're", 'mad']

How about this algorithm? Split text on whitespace, then trim punctuation. This carefully removes punctuation from the edge of words, without harming apostrophes inside words such as we're.

>>> text
"'Oh, you can't help that,' said the Cat: 'we're all mad here. I'm mad. You're mad.'"

>>> text.split()
["'Oh,", 'you', "can't", 'help', "that,'", 'said', 'the', 'Cat:', "'we're", 'all', 'mad', 'here.', "I'm", 'mad.', "You're", "mad.'"]

>>> import string
>>> [word.strip(string.punctuation) for word in text.split()]
['Oh', 'you', "can't", 'help', 'that', 'said', 'the', 'Cat', "we're", 'all', 'mad', 'here', "I'm", 'mad', "You're", 'mad']

回答 5

我希望我的python函数拆分一个句子(输入)并将每个单词存储在列表中

str().split()方法执行此操作,它需要一个字符串,并将其拆分为一个列表:

>>> the_string = "this is a sentence"
>>> words = the_string.split(" ")
>>> print(words)
['this', 'is', 'a', 'sentence']
>>> type(words)
<type 'list'> # or <class 'list'> in Python 3.0

您遇到的问题是由于输入错误,print(words)而不是您写的print(word)

word变量重命名为current_word,这就是您所拥有的:

def split_line(text):
    words = text.split()
    for current_word in words:
        print(words)

..什么时候应该完成:

def split_line(text):
    words = text.split()
    for current_word in words:
        print(current_word)

如果出于某种原因要在for循环中手动构造列表,则可以使用list append()方法,也许是因为您想对所有单词都小写(例如):

my_list = [] # make empty list
for current_word in words:
    my_list.append(current_word.lower())

或者使用list-comprehension更加整洁:

my_list = [current_word.lower() for current_word in words]

I want my python function to split a sentence (input) and store each word in a list

The str().split() method does this, it takes a string, splits it into a list:

>>> the_string = "this is a sentence"
>>> words = the_string.split(" ")
>>> print(words)
['this', 'is', 'a', 'sentence']
>>> type(words)
<type 'list'> # or <class 'list'> in Python 3.0

The problem you’re having is because of a typo, you wrote print(words) instead of print(word):

Renaming the word variable to current_word, this is what you had:

def split_line(text):
    words = text.split()
    for current_word in words:
        print(words)

..when you should have done:

def split_line(text):
    words = text.split()
    for current_word in words:
        print(current_word)

If for some reason you want to manually construct a list in the for loop, you would use the list append() method, perhaps because you want to lower-case all words (for example):

my_list = [] # make empty list
for current_word in words:
    my_list.append(current_word.lower())

Or more a bit neater, using a list-comprehension:

my_list = [current_word.lower() for current_word in words]

回答 6

shlex具有.split()功能。它的不同之处str.split()在于,它不保留引号,并且将带引号的词组视为一个单词:

>>> import shlex
>>> shlex.split("sudo echo 'foo && bar'")
['sudo', 'echo', 'foo && bar']

shlex has a .split() function. It differs from str.split() in that it does not preserve quotes and treats a quoted phrase as a single word:

>>> import shlex
>>> shlex.split("sudo echo 'foo && bar'")
['sudo', 'echo', 'foo && bar']

回答 7

如果要在列表中包含单词/句子的所有字符,请执行以下操作:

print(list("word"))
#  ['w', 'o', 'r', 'd']


print(list("some sentence"))
#  ['s', 'o', 'm', 'e', ' ', 's', 'e', 'n', 't', 'e', 'n', 'c', 'e']

If you want all the chars of a word/sentence in a list, do this:

print(list("word"))
#  ['w', 'o', 'r', 'd']


print(list("some sentence"))
#  ['s', 'o', 'm', 'e', ' ', 's', 'e', 'n', 't', 'e', 'n', 'c', 'e']

回答 8

我认为您因错字而感到困惑。

更换print(words)print(word)您的循环内已印刷在另一条线路的每一个字

I think you are confused because of a typo.

Replace print(words) with print(word) inside your loop to have every word printed on a different line