标签归档:syntax

用于除法时,“ /”和“ //”之间有什么区别?

问题:用于除法时,“ /”和“ //”之间有什么区别?

将一个使用在另一个上是否有好处?在Python 2中,它们似乎都返回相同的结果:

>>> 6/3
2
>>> 6//3
2

Is there a benefit to using one over the other? In Python 2, they both seem to return the same results:

>>> 6/3
2
>>> 6//3
2

回答 0

在Python 3.x中,5 / 2将返回2.5并且5 // 2将返回2。前者是浮点除法,后者是地板除法,有时也称为整数除法

在Python 2.2或更高版本的2.x行中,除非执行from __future__ import division,否则整数没有区别,这会使Python 2.x采取3.x行为。

不管将来的进口是什么,5.0 // 2都会归还,2.0因为这是操作的地板分割结果。

您可以在https://docs.python.org/whatsnew/2.2.html#pep-238-changing-the-division-operator中找到详细说明

In Python 3.x, 5 / 2 will return 2.5 and 5 // 2 will return 2. The former is floating point division, and the latter is floor division, sometimes also called integer division.

In Python 2.2 or later in the 2.x line, there is no difference for integers unless you perform a from __future__ import division, which causes Python 2.x to adopt the 3.x behavior.

Regardless of the future import, 5.0 // 2 will return 2.0 since that’s the floor division result of the operation.

You can find a detailed description at https://docs.python.org/whatsnew/2.2.html#pep-238-changing-the-division-operator


回答 1

Python 2.x澄清:

为了阐明Python 2.x系列,/既不是楼层划分也不是真正的划分。当前接受的答案尚不清楚。

/是地板除法时 ARG游戏int,但真正当师之一或两者的参数的个数是float

上面讲了更多的事实,并且比接受的答案中的第二段更清楚。

Python 2.x Clarification:

To clarify for the Python 2.x line, / is neither floor division nor true division. The current accepted answer is not clear on this.

/ is floor division when both args are int, but is true division when either or both of the args are float.

The above tells more truth, and is more clear than the 2nd paragraph in the accepted answer.


回答 2

//不论您使用哪种类型,都可以实施“楼层划分”。所以 1.0/2.0会给0.5,但两者1/21//2并且1.0//2.0会给0

有关详细信息,请参见https://docs.python.org/whatsnew/2.2.html#pep-238-changing-the-division-operator

// implements “floor division”, regardless of your type. So 1.0/2.0 will give 0.5, but both 1/2, 1//2 and 1.0//2.0 will give 0.

See https://docs.python.org/whatsnew/2.2.html#pep-238-changing-the-division-operator for details


回答 3

// -浮点除法

// ->楼层划分

让我们在python 2.7和python 3.5中查看一些示例。

Python 2.7.10和Python 3.5

print (2/3)  ----> 0                   Python 2.7
print (2/3)  ----> 0.6666666666666666  Python 3.5

Python 2.7.10和Python 3.5

  print (4/2)  ----> 2         Python 2.7
  print (4/2)  ----> 2.0       Python 3.5

现在,如果您希望在python 2.7中具有与python 3.5相同的输出,则可以执行以下操作:

Python 2.7.10

from __future__ import division
print (2/3)  ----> 0.6666666666666666   #Python 2.7
print (4/2)  ----> 2.0                  #Python 2.7

在python 2.7和python 3.5中,Floor划分之间没有区别

138.93//3 ---> 46.0        #Python 2.7
138.93//3 ---> 46.0        #Python 3.5
4//3      ---> 1           #Python 2.7
4//3      ---> 1           #Python 3.5

/ –> Floating point division

// –> Floor division

Lets see some examples in both python 2.7 and in Python 3.5.

Python 2.7.10 vs. Python 3.5

print (2/3)  ----> 0                   Python 2.7
print (2/3)  ----> 0.6666666666666666  Python 3.5

Python 2.7.10 vs. Python 3.5

  print (4/2)  ----> 2         Python 2.7
  print (4/2)  ----> 2.0       Python 3.5

Now if you want to have (in python 2.7) same output as in python 3.5, you can do the following:

Python 2.7.10

from __future__ import division
print (2/3)  ----> 0.6666666666666666   #Python 2.7
print (4/2)  ----> 2.0                  #Python 2.7

Where as there is no differece between Floor division in both python 2.7 and in Python 3.5

138.93//3 ---> 46.0        #Python 2.7
138.93//3 ---> 46.0        #Python 3.5
4//3      ---> 1           #Python 2.7
4//3      ---> 1           #Python 3.5

回答 4

正如大家已经回答的那样,//是楼层划分。

之所以如此重要,是因为//在所有2.2版本的Python版本中,包括Python 3.x版本,都明确地进行了地域划分。

的行为/可能会有所不同,具体取决于:

  • 是否有效__future__导入(模块本地)
  • Python命令行选项,-Q old或者-Q new

As everyone has already answered, // is floor division.

Why this is important is that // is unambiguously floor division, in all Python versions from 2.2, including Python 3.x versions.

The behavior of / can change depending on:

  • Active __future__ import or not (module-local)
  • Python command line option, either -Q old or -Q new

回答 5

>>> print 5.0 / 2
2.5

>>> print 5.0 // 2
2.0
>>> print 5.0 / 2
2.5

>>> print 5.0 // 2
2.0

回答 6

Python 2.7和其他即将发布的python版本:

  • 部门(/

将左操作数除以右操作数

例: 4 / 2 = 2

  • 楼层部门(//

操作数的除法,结果是除掉小数点后的数字的商。但是,如果其中一个操作数是负数,则结果是下限的,即从零开始舍入(朝负无穷大):

例如:9//2 = 49.0//2.0 = 4.0-11//3 = -4-11.0//3 = -4.0

这两个/师和//地板除法运算的操作以类似的方式。

Python 2.7 and other upcoming version of python:

  • Division (/)

Divides left hand operand by right hand operand

Example: 4 / 2 = 2

  • Floor Division (//)

The division of operands where the result is the quotient in which the digits after the decimal point are removed. But if one of the operands is negative, the result is floored, i.e., rounded away from zero (towards negative infinity):

Examples: 9//2 = 4 and 9.0//2.0 = 4.0, -11//3 = -4, -11.0//3 = -4.0

Both / Division and // floor division operator are operating in similar fashion.


回答 7

双斜线//是地板分割:

>>> 7//3
2

The double slash, //, is floor division:

>>> 7//3
2

回答 8

//是底数除法,它将始终为您提供结果的整数底数。另一个是“常规”划分。

// is floor division, it will always give you the integer floor of the result. The other is ‘regular’ division.


回答 9

等式的答案四舍五入为下一个较小的整数,或者以.0作为小数点进行浮点运算。

>>>print 5//2
2
>>> print 5.0//2
2.0
>>>print 5//2.0
2.0
>>>print 5.0//2.0
2.0

The answer of the equation is rounded to the next smaller integer or float with .0 as decimal point.

>>>print 5//2
2
>>> print 5.0//2
2.0
>>>print 5//2.0
2.0
>>>print 5.0//2.0
2.0

回答 10

上面的答案是好的。我想补充一点。最多两个值都导致相同的商。在该楼层之后,除法运算符(//)正常工作,但除法运算符()无效/

 - > int(755349677599789174/2)
 - > 377674838799894592      #wrong answer
 - > 755349677599789174 //2
 - > 377674838799894587      #correct answer

The above answers are good. I want to add another point. Up to some values both of them result in the same quotient. After that floor division operator (//) works fine but not division (/) operator.

 - > int(755349677599789174/2)
 - > 377674838799894592      #wrong answer
 - > 755349677599789174 //2
 - > 377674838799894587      #correct answer

回答 11

5.0//2会导致2.0,而不是2因为运算符返回值的返回类型//遵循python强制(类型转换)规则。

Python促进将较低数据类型(整数)转换为较高数据类型(浮点数),以避免数据丢失。

5.0//2 results in 2.0, and not 2 because the return type of the return value from // operator follows python coercion (type casting) rules.

Python promotes conversion of lower datatype (integer) to higher data type (float) to avoid data loss.


回答 12

  • // 是底数划分,它将始终为您提供结果的底数。
  • 另一个/是浮点除法。

以下是之间的差///; 我已经在Python 3.7.2中运行了这些算术运算

>>> print (11 / 3)
3.6666666666666665

>>> print (11 // 3)
3

>>> print (11.3 / 3)
3.7666666666666667

>>> print (11.3 // 3)
3.0
  • // is floor division, it will always give you the floor value of the result.
  • And the other one / is the floating-point division.

Followings are the difference between / and //; I have run these arithmetic operations in Python 3.7.2

>>> print (11 / 3)
3.6666666666666665

>>> print (11 // 3)
3

>>> print (11.3 / 3)
3.7666666666666667

>>> print (11.3 // 3)
3.0

**(双星号/星号)和*(星号/星号)对参数有什么作用?

问题:**(双星号/星号)和*(星号/星号)对参数有什么作用?

在以下方法定义中,***param2什么?

def foo(param1, *param2):
def bar(param1, **param2):

In the following method definitions, what does the * and ** do for param2?

def foo(param1, *param2):
def bar(param1, **param2):

回答 0

*args**kwargs是一种常见的成语,以允许参数,以作为部分所述功能的任意数量的多个上定义函数 Python文档英寸

*args给你的所有函数参数为一个元组

def foo(*args):
    for a in args:
        print(a)        

foo(1)
# 1

foo(1,2,3)
# 1
# 2
# 3

**kwargs会给你所有的 关键字参数除了那些与作为字典的形式参数。

def bar(**kwargs):
    for a in kwargs:
        print(a, kwargs[a])  

bar(name='one', age=27)
# age 27
# name one

这两个习惯用法都可以与普通参数混合使用,以允许使用一组固定参数和一些可变参数:

def foo(kind, *args, **kwargs):
   pass

也可以以其他方式使用此方法:

def foo(a, b, c):
    print(a, b, c)

obj = {'b':10, 'c':'lee'}

foo(100,**obj)
# 100 10 lee

*l习惯用法的另一种用法是在调用函数时解压缩参数列表

def foo(bar, lee):
    print(bar, lee)

l = [1,2]

foo(*l)
# 1 2

在Python 3中,可以*l在分配的左侧使用(Extended Iterable Unpacking),尽管在这种情况下它提供的是列表而不是元组:

first, *rest = [1,2,3,4]
first, *l, last = [1,2,3,4]

Python 3还添加了新的语义(请参阅PEP 3102):

def func(arg1, arg2, arg3, *, kwarg1, kwarg2):
    pass

该函数仅接受3个位置参数,之后的所有内容*只能作为关键字参数传递。

The *args and **kwargs is a common idiom to allow arbitrary number of arguments to functions as described in the section more on defining functions in the Python documentation.

The *args will give you all function parameters as a tuple:

def foo(*args):
    for a in args:
        print(a)        

foo(1)
# 1

foo(1,2,3)
# 1
# 2
# 3

The **kwargs will give you all keyword arguments except for those corresponding to a formal parameter as a dictionary.

def bar(**kwargs):
    for a in kwargs:
        print(a, kwargs[a])  

bar(name='one', age=27)
# age 27
# name one

Both idioms can be mixed with normal arguments to allow a set of fixed and some variable arguments:

def foo(kind, *args, **kwargs):
   pass

It is also possible to use this the other way around:

def foo(a, b, c):
    print(a, b, c)

obj = {'b':10, 'c':'lee'}

foo(100,**obj)
# 100 10 lee

Another usage of the *l idiom is to unpack argument lists when calling a function.

def foo(bar, lee):
    print(bar, lee)

l = [1,2]

foo(*l)
# 1 2

In Python 3 it is possible to use *l on the left side of an assignment (Extended Iterable Unpacking), though it gives a list instead of a tuple in this context:

first, *rest = [1,2,3,4]
first, *l, last = [1,2,3,4]

Also Python 3 adds new semantic (refer PEP 3102):

def func(arg1, arg2, arg3, *, kwarg1, kwarg2):
    pass

Such function accepts only 3 positional arguments, and everything after * can only be passed as keyword arguments.


回答 1

另外值得一提的是,你可以使用***调用功能,以及时。这是一个快捷方式,允许您使用列表/元组或字典将多个参数直接传递给函数。例如,如果您具有以下功能:

def foo(x,y,z):
    print("x=" + str(x))
    print("y=" + str(y))
    print("z=" + str(z))

您可以执行以下操作:

>>> mylist = [1,2,3]
>>> foo(*mylist)
x=1
y=2
z=3

>>> mydict = {'x':1,'y':2,'z':3}
>>> foo(**mydict)
x=1
y=2
z=3

>>> mytuple = (1, 2, 3)
>>> foo(*mytuple)
x=1
y=2
z=3

注意:中的键mydict必须完全像function参数一样命名foo。否则会抛出TypeError

>>> mydict = {'x':1,'y':2,'z':3,'badnews':9}
>>> foo(**mydict)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: foo() got an unexpected keyword argument 'badnews'

It’s also worth noting that you can use * and ** when calling functions as well. This is a shortcut that allows you to pass multiple arguments to a function directly using either a list/tuple or a dictionary. For example, if you have the following function:

def foo(x,y,z):
    print("x=" + str(x))
    print("y=" + str(y))
    print("z=" + str(z))

You can do things like:

>>> mylist = [1,2,3]
>>> foo(*mylist)
x=1
y=2
z=3

>>> mydict = {'x':1,'y':2,'z':3}
>>> foo(**mydict)
x=1
y=2
z=3

>>> mytuple = (1, 2, 3)
>>> foo(*mytuple)
x=1
y=2
z=3

Note: The keys in mydict have to be named exactly like the parameters of function foo. Otherwise it will throw a TypeError:

>>> mydict = {'x':1,'y':2,'z':3,'badnews':9}
>>> foo(**mydict)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: foo() got an unexpected keyword argument 'badnews'

回答 2

单个*表示可以有任意数量的额外位置参数。foo()可以像这样调用foo(1,2,3,4,5)。在foo()主体中,param2是一个包含2-5的序列。

双**表示可以有任意数量的额外命名参数。bar()可以像这样调用bar(1, a=2, b=3)。在bar()的主体中,param2是一个包含{‘a’:2,’b’:3}的字典。

使用以下代码:

def foo(param1, *param2):
    print(param1)
    print(param2)

def bar(param1, **param2):
    print(param1)
    print(param2)

foo(1,2,3,4,5)
bar(1,a=2,b=3)

输出是

1
(2, 3, 4, 5)
1
{'a': 2, 'b': 3}

The single * means that there can be any number of extra positional arguments. foo() can be invoked like foo(1,2,3,4,5). In the body of foo() param2 is a sequence containing 2-5.

The double ** means there can be any number of extra named parameters. bar() can be invoked like bar(1, a=2, b=3). In the body of bar() param2 is a dictionary containing {‘a’:2, ‘b’:3 }

With the following code:

def foo(param1, *param2):
    print(param1)
    print(param2)

def bar(param1, **param2):
    print(param1)
    print(param2)

foo(1,2,3,4,5)
bar(1,a=2,b=3)

the output is

1
(2, 3, 4, 5)
1
{'a': 2, 'b': 3}

回答 3

这是什么**(双星)和*(明星)的参数做

它们允许定义函数以接受并允许用户传递任意数量的参数,位置(*)和关键字(**)。

定义功能

*args允许任意数量的可选位置参数(参数),这些参数将分配给名为的元组args

**kwargs允许任意数量的可选关键字参数(参数),这些参数将位于名为的字典中kwargs

您可以(并且应该)选择任何适当的名称,但是如果目的是使参数具有非特定的语义,args并且kwargs是标准名称。

扩展,传递任意数量的参数

您还可以分别使用*args**kwargs传入列表(或任何可迭代的)和字典(或任何映射)的参数。

接收参数的函数不必知道它们正在扩展。

例如,Python 2的xrange并不明确期望*args,但是因为它使用3个整数作为参数:

>>> x = xrange(3) # create our *args - an iterable of 3 integers
>>> xrange(*x)    # expand here
xrange(0, 2, 2)

再举一个例子,我们可以在下面使用dict扩展str.format

>>> foo = 'FOO'
>>> bar = 'BAR'
>>> 'this is foo, {foo} and bar, {bar}'.format(**locals())
'this is foo, FOO and bar, BAR'

Python 3的新功能:使用仅关键字参数定义函数

您可以在- 之后添加仅关键字参数*args -例如,在此处,kwarg2必须将其作为关键字参数-而不是位置:

def foo(arg, kwarg=None, *args, kwarg2=None, **kwargs): 
    return arg, kwarg, args, kwarg2, kwargs

用法:

>>> foo(1,2,3,4,5,kwarg2='kwarg2', bar='bar', baz='baz')
(1, 2, (3, 4, 5), 'kwarg2', {'bar': 'bar', 'baz': 'baz'})

同样,*可以单独用于表示仅关键字参数跟随,而不允许无限的位置参数。

def foo(arg, kwarg=None, *, kwarg2=None, **kwargs): 
    return arg, kwarg, kwarg2, kwargs

在这里,kwarg2再次必须是一个明确命名的关键字参数:

>>> foo(1,2,kwarg2='kwarg2', foo='foo', bar='bar')
(1, 2, 'kwarg2', {'foo': 'foo', 'bar': 'bar'})

而且我们不再可以接受无限的位置参数,因为我们没有*args*

>>> foo(1,2,3,4,5, kwarg2='kwarg2', foo='foo', bar='bar')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: foo() takes from 1 to 2 positional arguments 
    but 5 positional arguments (and 1 keyword-only argument) were given

再次,更简单地说,在这里我们需要kwarg使用名称,而不是位置:

def bar(*, kwarg=None): 
    return kwarg

在此示例中,我们看到如果尝试通过kwarg位置传递,则会收到错误消息:

>>> bar('kwarg')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: bar() takes 0 positional arguments but 1 was given

我们必须显式传递kwarg参数作为关键字参数。

>>> bar(kwarg='kwarg')
'kwarg'

兼容Python 2的演示

*args(通常说“ star-args”)和**kwargs(可以通过说“ kwargs”来暗示星号,但是用“ double-star kwargs”来明确表示)是使用***表示法的Python的常见用法。这些特定的变量名称不是必需的(例如,您可以使用*foos**bars),但是背离约定可能会激怒您的Python编码人员。

当我们不知道函数将要接收什么或我们可能传递多少个参数时,我们通常会使用它们,有时甚至即使分别命名每个变量也会变得非常混乱和多余(但这是通常显式的情况比隐式更好)。

例子1

以下功能描述了如何使用它们,并演示了行为。请注意,命名b参数将由前面的第二个位置参数使用:

def foo(a, b=10, *args, **kwargs):
    '''
    this function takes required argument a, not required keyword argument b
    and any number of unknown positional arguments and keyword arguments after
    '''
    print('a is a required argument, and its value is {0}'.format(a))
    print('b not required, its default value is 10, actual value: {0}'.format(b))
    # we can inspect the unknown arguments we were passed:
    #  - args:
    print('args is of type {0} and length {1}'.format(type(args), len(args)))
    for arg in args:
        print('unknown arg: {0}'.format(arg))
    #  - kwargs:
    print('kwargs is of type {0} and length {1}'.format(type(kwargs),
                                                        len(kwargs)))
    for kw, arg in kwargs.items():
        print('unknown kwarg - kw: {0}, arg: {1}'.format(kw, arg))
    # But we don't have to know anything about them 
    # to pass them to other functions.
    print('Args or kwargs can be passed without knowing what they are.')
    # max can take two or more positional args: max(a, b, c...)
    print('e.g. max(a, b, *args) \n{0}'.format(
      max(a, b, *args))) 
    kweg = 'dict({0})'.format( # named args same as unknown kwargs
      ', '.join('{k}={v}'.format(k=k, v=v) 
                             for k, v in sorted(kwargs.items())))
    print('e.g. dict(**kwargs) (same as {kweg}) returns: \n{0}'.format(
      dict(**kwargs), kweg=kweg))

我们可以检查函数的签名的在线帮助,以help(foo),它告诉我们

foo(a, b=10, *args, **kwargs)

让我们用 foo(1, 2, 3, 4, e=5, f=6, g=7)

打印:

a is a required argument, and its value is 1
b not required, its default value is 10, actual value: 2
args is of type <type 'tuple'> and length 2
unknown arg: 3
unknown arg: 4
kwargs is of type <type 'dict'> and length 3
unknown kwarg - kw: e, arg: 5
unknown kwarg - kw: g, arg: 7
unknown kwarg - kw: f, arg: 6
Args or kwargs can be passed without knowing what they are.
e.g. max(a, b, *args) 
4
e.g. dict(**kwargs) (same as dict(e=5, f=6, g=7)) returns: 
{'e': 5, 'g': 7, 'f': 6}

例子2

我们还可以使用另一个函数来调用它a

def bar(a):
    b, c, d, e, f = 2, 3, 4, 5, 6
    # dumping every local variable into foo as a keyword argument 
    # by expanding the locals dict:
    foo(**locals()) 

bar(100) 印刷品:

a is a required argument, and its value is 100
b not required, its default value is 10, actual value: 2
args is of type <type 'tuple'> and length 0
kwargs is of type <type 'dict'> and length 4
unknown kwarg - kw: c, arg: 3
unknown kwarg - kw: e, arg: 5
unknown kwarg - kw: d, arg: 4
unknown kwarg - kw: f, arg: 6
Args or kwargs can be passed without knowing what they are.
e.g. max(a, b, *args) 
100
e.g. dict(**kwargs) (same as dict(c=3, d=4, e=5, f=6)) returns: 
{'c': 3, 'e': 5, 'd': 4, 'f': 6}

示例3:装饰器中的实际用法

好的,所以也许我们还没有看到该实用程序。因此,假设您在区分代码之前和/或之后有多个带有冗余代码的功能。为了说明的目的,以下命名函数只是伪代码。

def foo(a, b, c, d=0, e=100):
    # imagine this is much more code than a simple function call
    preprocess() 
    differentiating_process_foo(a,b,c,d,e)
    # imagine this is much more code than a simple function call
    postprocess()

def bar(a, b, c=None, d=0, e=100, f=None):
    preprocess()
    differentiating_process_bar(a,b,c,d,e,f)
    postprocess()

def baz(a, b, c, d, e, f):
    ... and so on

我们也许可以用不同的方式处理此问题,但是我们当然可以用装饰器提取冗余,因此下面的示例演示了如何*args并且**kwargs非常有用:

def decorator(function):
    '''function to wrap other functions with a pre- and postprocess'''
    @functools.wraps(function) # applies module, name, and docstring to wrapper
    def wrapper(*args, **kwargs):
        # again, imagine this is complicated, but we only write it once!
        preprocess()
        function(*args, **kwargs)
        postprocess()
    return wrapper

现在,由于我们考虑了冗余性,每个包装函数都可以更加简洁地编写:

@decorator
def foo(a, b, c, d=0, e=100):
    differentiating_process_foo(a,b,c,d,e)

@decorator
def bar(a, b, c=None, d=0, e=100, f=None):
    differentiating_process_bar(a,b,c,d,e,f)

@decorator
def baz(a, b, c=None, d=0, e=100, f=None, g=None):
    differentiating_process_baz(a,b,c,d,e,f, g)

@decorator
def quux(a, b, c=None, d=0, e=100, f=None, g=None, h=None):
    differentiating_process_quux(a,b,c,d,e,f,g,h)

通过分解*args**kwargs允许我们这样做的代码,我们减少了代码行,提高了可读性和可维护性,并且在程序中具有唯一的规范逻辑位置。如果需要更改此结构的任何部分,则可以在一个位置进行每次更改。

What does ** (double star) and * (star) do for parameters

They allow for functions to be defined to accept and for users to pass any number of arguments, positional (*) and keyword (**).

Defining Functions

*args allows for any number of optional positional arguments (parameters), which will be assigned to a tuple named args.

**kwargs allows for any number of optional keyword arguments (parameters), which will be in a dict named kwargs.

You can (and should) choose any appropriate name, but if the intention is for the arguments to be of non-specific semantics, args and kwargs are standard names.

Expansion, Passing any number of arguments

You can also use *args and **kwargs to pass in parameters from lists (or any iterable) and dicts (or any mapping), respectively.

The function recieving the parameters does not have to know that they are being expanded.

For example, Python 2’s xrange does not explicitly expect *args, but since it takes 3 integers as arguments:

>>> x = xrange(3) # create our *args - an iterable of 3 integers
>>> xrange(*x)    # expand here
xrange(0, 2, 2)

As another example, we can use dict expansion in str.format:

>>> foo = 'FOO'
>>> bar = 'BAR'
>>> 'this is foo, {foo} and bar, {bar}'.format(**locals())
'this is foo, FOO and bar, BAR'

New in Python 3: Defining functions with keyword only arguments

You can have keyword only arguments after the *args – for example, here, kwarg2 must be given as a keyword argument – not positionally:

def foo(arg, kwarg=None, *args, kwarg2=None, **kwargs): 
    return arg, kwarg, args, kwarg2, kwargs

Usage:

>>> foo(1,2,3,4,5,kwarg2='kwarg2', bar='bar', baz='baz')
(1, 2, (3, 4, 5), 'kwarg2', {'bar': 'bar', 'baz': 'baz'})

Also, * can be used by itself to indicate that keyword only arguments follow, without allowing for unlimited positional arguments.

def foo(arg, kwarg=None, *, kwarg2=None, **kwargs): 
    return arg, kwarg, kwarg2, kwargs

Here, kwarg2 again must be an explicitly named, keyword argument:

>>> foo(1,2,kwarg2='kwarg2', foo='foo', bar='bar')
(1, 2, 'kwarg2', {'foo': 'foo', 'bar': 'bar'})

And we can no longer accept unlimited positional arguments because we don’t have *args*:

>>> foo(1,2,3,4,5, kwarg2='kwarg2', foo='foo', bar='bar')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: foo() takes from 1 to 2 positional arguments 
    but 5 positional arguments (and 1 keyword-only argument) were given

Again, more simply, here we require kwarg to be given by name, not positionally:

def bar(*, kwarg=None): 
    return kwarg

In this example, we see that if we try to pass kwarg positionally, we get an error:

>>> bar('kwarg')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: bar() takes 0 positional arguments but 1 was given

We must explicitly pass the kwarg parameter as a keyword argument.

>>> bar(kwarg='kwarg')
'kwarg'

Python 2 compatible demos

*args (typically said “star-args”) and **kwargs (stars can be implied by saying “kwargs”, but be explicit with “double-star kwargs”) are common idioms of Python for using the * and ** notation. These specific variable names aren’t required (e.g. you could use *foos and **bars), but a departure from convention is likely to enrage your fellow Python coders.

We typically use these when we don’t know what our function is going to receive or how many arguments we may be passing, and sometimes even when naming every variable separately would get very messy and redundant (but this is a case where usually explicit is better than implicit).

Example 1

The following function describes how they can be used, and demonstrates behavior. Note the named b argument will be consumed by the second positional argument before :

def foo(a, b=10, *args, **kwargs):
    '''
    this function takes required argument a, not required keyword argument b
    and any number of unknown positional arguments and keyword arguments after
    '''
    print('a is a required argument, and its value is {0}'.format(a))
    print('b not required, its default value is 10, actual value: {0}'.format(b))
    # we can inspect the unknown arguments we were passed:
    #  - args:
    print('args is of type {0} and length {1}'.format(type(args), len(args)))
    for arg in args:
        print('unknown arg: {0}'.format(arg))
    #  - kwargs:
    print('kwargs is of type {0} and length {1}'.format(type(kwargs),
                                                        len(kwargs)))
    for kw, arg in kwargs.items():
        print('unknown kwarg - kw: {0}, arg: {1}'.format(kw, arg))
    # But we don't have to know anything about them 
    # to pass them to other functions.
    print('Args or kwargs can be passed without knowing what they are.')
    # max can take two or more positional args: max(a, b, c...)
    print('e.g. max(a, b, *args) \n{0}'.format(
      max(a, b, *args))) 
    kweg = 'dict({0})'.format( # named args same as unknown kwargs
      ', '.join('{k}={v}'.format(k=k, v=v) 
                             for k, v in sorted(kwargs.items())))
    print('e.g. dict(**kwargs) (same as {kweg}) returns: \n{0}'.format(
      dict(**kwargs), kweg=kweg))

We can check the online help for the function’s signature, with help(foo), which tells us

foo(a, b=10, *args, **kwargs)

Let’s call this function with foo(1, 2, 3, 4, e=5, f=6, g=7)

which prints:

a is a required argument, and its value is 1
b not required, its default value is 10, actual value: 2
args is of type <type 'tuple'> and length 2
unknown arg: 3
unknown arg: 4
kwargs is of type <type 'dict'> and length 3
unknown kwarg - kw: e, arg: 5
unknown kwarg - kw: g, arg: 7
unknown kwarg - kw: f, arg: 6
Args or kwargs can be passed without knowing what they are.
e.g. max(a, b, *args) 
4
e.g. dict(**kwargs) (same as dict(e=5, f=6, g=7)) returns: 
{'e': 5, 'g': 7, 'f': 6}

Example 2

We can also call it using another function, into which we just provide a:

def bar(a):
    b, c, d, e, f = 2, 3, 4, 5, 6
    # dumping every local variable into foo as a keyword argument 
    # by expanding the locals dict:
    foo(**locals()) 

bar(100) prints:

a is a required argument, and its value is 100
b not required, its default value is 10, actual value: 2
args is of type <type 'tuple'> and length 0
kwargs is of type <type 'dict'> and length 4
unknown kwarg - kw: c, arg: 3
unknown kwarg - kw: e, arg: 5
unknown kwarg - kw: d, arg: 4
unknown kwarg - kw: f, arg: 6
Args or kwargs can be passed without knowing what they are.
e.g. max(a, b, *args) 
100
e.g. dict(**kwargs) (same as dict(c=3, d=4, e=5, f=6)) returns: 
{'c': 3, 'e': 5, 'd': 4, 'f': 6}

Example 3: practical usage in decorators

OK, so maybe we’re not seeing the utility yet. So imagine you have several functions with redundant code before and/or after the differentiating code. The following named functions are just pseudo-code for illustrative purposes.

def foo(a, b, c, d=0, e=100):
    # imagine this is much more code than a simple function call
    preprocess() 
    differentiating_process_foo(a,b,c,d,e)
    # imagine this is much more code than a simple function call
    postprocess()

def bar(a, b, c=None, d=0, e=100, f=None):
    preprocess()
    differentiating_process_bar(a,b,c,d,e,f)
    postprocess()

def baz(a, b, c, d, e, f):
    ... and so on

We might be able to handle this differently, but we can certainly extract the redundancy with a decorator, and so our below example demonstrates how *args and **kwargs can be very useful:

def decorator(function):
    '''function to wrap other functions with a pre- and postprocess'''
    @functools.wraps(function) # applies module, name, and docstring to wrapper
    def wrapper(*args, **kwargs):
        # again, imagine this is complicated, but we only write it once!
        preprocess()
        function(*args, **kwargs)
        postprocess()
    return wrapper

And now every wrapped function can be written much more succinctly, as we’ve factored out the redundancy:

@decorator
def foo(a, b, c, d=0, e=100):
    differentiating_process_foo(a,b,c,d,e)

@decorator
def bar(a, b, c=None, d=0, e=100, f=None):
    differentiating_process_bar(a,b,c,d,e,f)

@decorator
def baz(a, b, c=None, d=0, e=100, f=None, g=None):
    differentiating_process_baz(a,b,c,d,e,f, g)

@decorator
def quux(a, b, c=None, d=0, e=100, f=None, g=None, h=None):
    differentiating_process_quux(a,b,c,d,e,f,g,h)

And by factoring out our code, which *args and **kwargs allows us to do, we reduce lines of code, improve readability and maintainability, and have sole canonical locations for the logic in our program. If we need to change any part of this structure, we have one place in which to make each change.


回答 4

首先让我们了解什么是位置参数和关键字参数。下面是带有位置参数的函数定义的示例

def test(a,b,c):
     print(a)
     print(b)
     print(c)

test(1,2,3)
#output:
1
2
3

因此,这是带有位置参数的函数定义。您也可以使用关键字/命名参数来调用它:

def test(a,b,c):
     print(a)
     print(b)
     print(c)

test(a=1,b=2,c=3)
#output:
1
2
3

现在让我们研究一个带有关键字参数的函数定义示例:

def test(a=0,b=0,c=0):
     print(a)
     print(b)
     print(c)
     print('-------------------------')

test(a=1,b=2,c=3)
#output :
1
2
3
-------------------------

您也可以使用位置参数调用此函数:

def test(a=0,b=0,c=0):
    print(a)
    print(b)
    print(c)
    print('-------------------------')

test(1,2,3)
# output :
1
2
3
---------------------------------

因此,我们现在知道带有位置参数以及关键字参数的函数定义。

现在让我们研究“ *”运算符和“ **”运算符。

请注意,这些运算符可以在两个区域中使用:

a)函数调用

b)功能定义

函数调用中使用“ *”运算符和“ **”运算符

让我们直接看一个例子,然后讨论它。

def sum(a,b):  #receive args from function calls as sum(1,2) or sum(a=1,b=2)
    print(a+b)

my_tuple = (1,2)
my_list = [1,2]
my_dict = {'a':1,'b':2}

# Let us unpack data structure of list or tuple or dict into arguments with help of '*' operator
sum(*my_tuple)   # becomes same as sum(1,2) after unpacking my_tuple with '*'
sum(*my_list)    # becomes same as sum(1,2) after unpacking my_list with  '*'
sum(**my_dict)   # becomes same as sum(a=1,b=2) after unpacking by '**' 

# output is 3 in all three calls to sum function.

所以记住

函数调用中使用“ *”或“ **”运算符时-

‘*’运算符将列表或元组等数据结构解压缩为函数定义所需的参数。

‘**’运算符将字典分解成函数定义所需的参数。

现在让我们研究函数定义中使用’*’运算符。例:

def sum(*args): #pack the received positional args into data structure of tuple. after applying '*' - def sum((1,2,3,4))
    sum = 0
    for a in args:
        sum+=a
    print(sum)

sum(1,2,3,4)  #positional args sent to function sum
#output:
10

在函数定义中,“ *”运算符将接收到的参数打包到一个元组中。

现在让我们看一下函数定义中使用的“ **”示例:

def sum(**args): #pack keyword args into datastructure of dict after applying '**' - def sum({a:1,b:2,c:3,d:4})
    sum=0
    for k,v in args.items():
        sum+=v
    print(sum)

sum(a=1,b=2,c=3,d=4) #positional args sent to function sum

在函数定义中,“ **”运算符将接收到的参数打包到字典中。

因此请记住:

函数调用中,“ *” 将元组或列表的数据结构解压缩为位置或关键字参数,以供函数定义接收。

函数调用中,“ **” 将字典的数据结构解压缩为位置或关键字参数,以供函数定义接收。

函数定义中,“ *” 位置参数打包到元组中。

函数定义中,“ **” 关键字参数打包到字典中。

Let us first understand what are positional arguments and keyword arguments. Below is an example of function definition with Positional arguments.

def test(a,b,c):
     print(a)
     print(b)
     print(c)

test(1,2,3)
#output:
1
2
3

So this is a function definition with positional arguments. You can call it with keyword/named arguments as well:

def test(a,b,c):
     print(a)
     print(b)
     print(c)

test(a=1,b=2,c=3)
#output:
1
2
3

Now let us study an example of function definition with keyword arguments:

def test(a=0,b=0,c=0):
     print(a)
     print(b)
     print(c)
     print('-------------------------')

test(a=1,b=2,c=3)
#output :
1
2
3
-------------------------

You can call this function with positional arguments as well:

def test(a=0,b=0,c=0):
    print(a)
    print(b)
    print(c)
    print('-------------------------')

test(1,2,3)
# output :
1
2
3
---------------------------------

So we now know function definitions with positional as well as keyword arguments.

Now let us study the ‘*’ operator and ‘**’ operator.

Please note these operators can be used in 2 areas:

a) function call

b) function definition

The use of ‘*’ operator and ‘**’ operator in function call.

Let us get straight to an example and then discuss it.

def sum(a,b):  #receive args from function calls as sum(1,2) or sum(a=1,b=2)
    print(a+b)

my_tuple = (1,2)
my_list = [1,2]
my_dict = {'a':1,'b':2}

# Let us unpack data structure of list or tuple or dict into arguments with help of '*' operator
sum(*my_tuple)   # becomes same as sum(1,2) after unpacking my_tuple with '*'
sum(*my_list)    # becomes same as sum(1,2) after unpacking my_list with  '*'
sum(**my_dict)   # becomes same as sum(a=1,b=2) after unpacking by '**' 

# output is 3 in all three calls to sum function.

So remember

when the ‘*’ or ‘**’ operator is used in a function call

‘*’ operator unpacks data structure such as a list or tuple into arguments needed by function definition.

‘**’ operator unpacks a dictionary into arguments needed by function definition.

Now let us study the ‘*’ operator use in function definition. Example:

def sum(*args): #pack the received positional args into data structure of tuple. after applying '*' - def sum((1,2,3,4))
    sum = 0
    for a in args:
        sum+=a
    print(sum)

sum(1,2,3,4)  #positional args sent to function sum
#output:
10

In function definition the ‘*’ operator packs the received arguments into a tuple.

Now let us see an example of ‘**’ used in function definition:

def sum(**args): #pack keyword args into datastructure of dict after applying '**' - def sum({a:1,b:2,c:3,d:4})
    sum=0
    for k,v in args.items():
        sum+=v
    print(sum)

sum(a=1,b=2,c=3,d=4) #positional args sent to function sum

In function definition The ‘**’ operator packs the received arguments into a dictionary.

So remember:

In a function call the ‘*’ unpacks data structure of tuple or list into positional or keyword arguments to be received by function definition.

In a function call the ‘**’ unpacks data structure of dictionary into positional or keyword arguments to be received by function definition.

In a function definition the ‘*’ packs positional arguments into a tuple.

In a function definition the ‘**’ packs keyword arguments into a dictionary.


回答 5

该表非常适合在函数构造和函数调用中使用*和使用:**

            In function construction         In function call
=======================================================================
          |  def f(*args):                 |  def f(a, b):
*args     |      for arg in args:          |      return a + b
          |          print(arg)            |  args = (1, 2)
          |  f(1, 2)                       |  f(*args)
----------|--------------------------------|---------------------------
          |  def f(a, b):                  |  def f(a, b):
**kwargs  |      return a + b              |      return a + b
          |  def g(**kwargs):              |  kwargs = dict(a=1, b=2)
          |      return f(**kwargs)        |  f(**kwargs)
          |  g(a=1, b=2)                   |
-----------------------------------------------------------------------

这实际上只是用来总结Lorin Hochstein的答案,但我发现它很有帮助。

相关:在Python 3中已扩展了star / splat运算符的用法

This table is handy for using * and ** in function construction and function call:

            In function construction         In function call
=======================================================================
          |  def f(*args):                 |  def f(a, b):
*args     |      for arg in args:          |      return a + b
          |          print(arg)            |  args = (1, 2)
          |  f(1, 2)                       |  f(*args)
----------|--------------------------------|---------------------------
          |  def f(a, b):                  |  def f(a, b):
**kwargs  |      return a + b              |      return a + b
          |  def g(**kwargs):              |  kwargs = dict(a=1, b=2)
          |      return f(**kwargs)        |  f(**kwargs)
          |  g(a=1, b=2)                   |
-----------------------------------------------------------------------

This really just serves to summarize Lorin Hochstein’s answer but I find it helpful.

Relatedly: uses for the star/splat operators have been expanded in Python 3


回答 6

***在函数参数列表中有特殊用法。* 表示该参数是一个列表,并且**表示该参数是一个字典。这允许函数接受任意数量的参数

* and ** have special usage in the function argument list. * implies that the argument is a list and ** implies that the argument is a dictionary. This allows functions to take arbitrary number of arguments


回答 7

对于那些通过榜样学习的人!

  1. 的目的* 是使您能够定义一个函数,该函数可以采用以列表形式提供的任意数量的参数(例如f(*myList))。
  2. 目的**是通过提供字典(例如f(**{'x' : 1, 'y' : 2}))使您能够输入函数的参数。

就让我们一起来通过定义一个函数,它有两个正常的变量xy以及可以接受更多的论据myArgs,并能接受更多的论据myKW。稍后,我们将展示如何y使用进行订阅myArgDict

def f(x, y, *myArgs, **myKW):
    print("# x      = {}".format(x))
    print("# y      = {}".format(y))
    print("# myArgs = {}".format(myArgs))
    print("# myKW   = {}".format(myKW))
    print("# ----------------------------------------------------------------------")

# Define a list for demonstration purposes
myList    = ["Left", "Right", "Up", "Down"]
# Define a dictionary for demonstration purposes
myDict    = {"Wubba": "lubba", "Dub": "dub"}
# Define a dictionary to feed y
myArgDict = {'y': "Why?", 'y0': "Why not?", "q": "Here is a cue!"}

# The 1st elem of myList feeds y
f("myEx", *myList, **myDict)
# x      = myEx
# y      = Left
# myArgs = ('Right', 'Up', 'Down')
# myKW   = {'Wubba': 'lubba', 'Dub': 'dub'}
# ----------------------------------------------------------------------

# y is matched and fed first
# The rest of myArgDict becomes additional arguments feeding myKW
f("myEx", **myArgDict)
# x      = myEx
# y      = Why?
# myArgs = ()
# myKW   = {'y0': 'Why not?', 'q': 'Here is a cue!'}
# ----------------------------------------------------------------------

# The rest of myArgDict becomes additional arguments feeding myArgs
f("myEx", *myArgDict)
# x      = myEx
# y      = y
# myArgs = ('y0', 'q')
# myKW   = {}
# ----------------------------------------------------------------------

# Feed extra arguments manually and append even more from my list
f("myEx", 4, 42, 420, *myList, *myDict, **myDict)
# x      = myEx
# y      = 4
# myArgs = (42, 420, 'Left', 'Right', 'Up', 'Down', 'Wubba', 'Dub')
# myKW   = {'Wubba': 'lubba', 'Dub': 'dub'}
# ----------------------------------------------------------------------

# Without the stars, the entire provided list and dict become x, and y:
f(myList, myDict)
# x      = ['Left', 'Right', 'Up', 'Down']
# y      = {'Wubba': 'lubba', 'Dub': 'dub'}
# myArgs = ()
# myKW   = {}
# ----------------------------------------------------------------------

注意事项

  1. ** 专为字典保留。
  2. 非可选参数分配首先发生。
  3. 您不能两次使用非可选参数。
  4. 如果适用,**必须*始终紧随其后。

For those of you who learn by examples!

  1. The purpose of * is to give you the ability to define a function that can take an arbitrary number of arguments provided as a list (e.g. f(*myList) ).
  2. The purpose of ** is to give you the ability to feed a function’s arguments by providing a dictionary (e.g. f(**{'x' : 1, 'y' : 2}) ).

Let us show this by defining a function that takes two normal variables x, y, and can accept more arguments as myArgs, and can accept even more arguments as myKW. Later, we will show how to feed y using myArgDict.

def f(x, y, *myArgs, **myKW):
    print("# x      = {}".format(x))
    print("# y      = {}".format(y))
    print("# myArgs = {}".format(myArgs))
    print("# myKW   = {}".format(myKW))
    print("# ----------------------------------------------------------------------")

# Define a list for demonstration purposes
myList    = ["Left", "Right", "Up", "Down"]
# Define a dictionary for demonstration purposes
myDict    = {"Wubba": "lubba", "Dub": "dub"}
# Define a dictionary to feed y
myArgDict = {'y': "Why?", 'y0': "Why not?", "q": "Here is a cue!"}

# The 1st elem of myList feeds y
f("myEx", *myList, **myDict)
# x      = myEx
# y      = Left
# myArgs = ('Right', 'Up', 'Down')
# myKW   = {'Wubba': 'lubba', 'Dub': 'dub'}
# ----------------------------------------------------------------------

# y is matched and fed first
# The rest of myArgDict becomes additional arguments feeding myKW
f("myEx", **myArgDict)
# x      = myEx
# y      = Why?
# myArgs = ()
# myKW   = {'y0': 'Why not?', 'q': 'Here is a cue!'}
# ----------------------------------------------------------------------

# The rest of myArgDict becomes additional arguments feeding myArgs
f("myEx", *myArgDict)
# x      = myEx
# y      = y
# myArgs = ('y0', 'q')
# myKW   = {}
# ----------------------------------------------------------------------

# Feed extra arguments manually and append even more from my list
f("myEx", 4, 42, 420, *myList, *myDict, **myDict)
# x      = myEx
# y      = 4
# myArgs = (42, 420, 'Left', 'Right', 'Up', 'Down', 'Wubba', 'Dub')
# myKW   = {'Wubba': 'lubba', 'Dub': 'dub'}
# ----------------------------------------------------------------------

# Without the stars, the entire provided list and dict become x, and y:
f(myList, myDict)
# x      = ['Left', 'Right', 'Up', 'Down']
# y      = {'Wubba': 'lubba', 'Dub': 'dub'}
# myArgs = ()
# myKW   = {}
# ----------------------------------------------------------------------

Caveats

  1. ** is exclusively reserved for dictionaries.
  2. Non-optional argument assignment happens first.
  3. You cannot use a non-optional argument twice.
  4. If applicable, ** must come after *, always.

回答 8

从Python文档中:

如果位置参数多于形式参数槽,则将引发TypeError异常,除非存在使用语法“ * identifier”的形式参数;否则,将引发TypeError异常。在这种情况下,该形式参数会接收包含多余位置参数的元组(如果没有多余位置参数,则为空元组)。

如果任何关键字参数与形式参数名称都不对应,则除非存在使用语法“ ** identifier”的形式参数,否则将引发TypeError异常;否则,将引发TypeError异常。在这种情况下,该形式参数将接收包含多余关键字参数的字典(使用关键字作为键,并将参数值用作对应的值),或者如果没有多余的关键字参数,则接收一个(新的)空字典。

From the Python documentation:

If there are more positional arguments than there are formal parameter slots, a TypeError exception is raised, unless a formal parameter using the syntax “*identifier” is present; in this case, that formal parameter receives a tuple containing the excess positional arguments (or an empty tuple if there were no excess positional arguments).

If any keyword argument does not correspond to a formal parameter name, a TypeError exception is raised, unless a formal parameter using the syntax “**identifier” is present; in this case, that formal parameter receives a dictionary containing the excess keyword arguments (using the keywords as keys and the argument values as corresponding values), or a (new) empty dictionary if there were no excess keyword arguments.


回答 9

* 表示将可变参数作为元组接收

** 表示接收可变参数作为字典

使用方式如下:

1)单*

def foo(*args):
    for arg in args:
        print(arg)

foo("two", 3)

输出:

two
3

2)现在 **

def bar(**kwargs):
    for key in kwargs:
        print(key, kwargs[key])

bar(dic1="two", dic2=3)

输出:

dic1 two
dic2 3

* means receive variable arguments as tuple

** means receive variable arguments as dictionary

Used like the following:

1) single *

def foo(*args):
    for arg in args:
        print(arg)

foo("two", 3)

Output:

two
3

2) Now **

def bar(**kwargs):
    for key in kwargs:
        print(key, kwargs[key])

bar(dic1="two", dic2=3)

Output:

dic1 two
dic2 3

回答 10

我想举一个别人没有提到的例子

*也可以打开生成器包装

Python3文档中的一个示例

x = [1, 2, 3]
y = [4, 5, 6]

unzip_x, unzip_y = zip(*zip(x, y))

unzip_x将为[1、2、3],unzip_y将为[4、5、6]

zip()接收多个可初始化的参数,并返回一个生成器。

zip(*zip(x,y)) -> zip((1, 4), (2, 5), (3, 6))

I want to give an example which others haven’t mentioned

* can also unpack a generator

An example from Python3 Document

x = [1, 2, 3]
y = [4, 5, 6]

unzip_x, unzip_y = zip(*zip(x, y))

unzip_x will be [1, 2, 3], unzip_y will be [4, 5, 6]

The zip() receives multiple iretable args, and return a generator.

zip(*zip(x,y)) -> zip((1, 4), (2, 5), (3, 6))

回答 11

在Python 3.5,你也可以使用这个语法listdicttuple,和set显示器(有时也称为文本)。请参阅PEP 488:其他拆包概述

>>> (0, *range(1, 4), 5, *range(6, 8))
(0, 1, 2, 3, 5, 6, 7)
>>> [0, *range(1, 4), 5, *range(6, 8)]
[0, 1, 2, 3, 5, 6, 7]
>>> {0, *range(1, 4), 5, *range(6, 8)}
{0, 1, 2, 3, 5, 6, 7}
>>> d = {'one': 1, 'two': 2, 'three': 3}
>>> e = {'six': 6, 'seven': 7}
>>> {'zero': 0, **d, 'five': 5, **e}
{'five': 5, 'seven': 7, 'two': 2, 'one': 1, 'three': 3, 'six': 6, 'zero': 0}

它还允许在单个函数调用中解压缩多个可迭代对象。

>>> range(*[1, 10], *[2])
range(1, 10, 2)

(感谢mgilson的PEP链接。)

In Python 3.5, you can also use this syntax in list, dict, tuple, and set displays (also sometimes called literals). See PEP 488: Additional Unpacking Generalizations.

>>> (0, *range(1, 4), 5, *range(6, 8))
(0, 1, 2, 3, 5, 6, 7)
>>> [0, *range(1, 4), 5, *range(6, 8)]
[0, 1, 2, 3, 5, 6, 7]
>>> {0, *range(1, 4), 5, *range(6, 8)}
{0, 1, 2, 3, 5, 6, 7}
>>> d = {'one': 1, 'two': 2, 'three': 3}
>>> e = {'six': 6, 'seven': 7}
>>> {'zero': 0, **d, 'five': 5, **e}
{'five': 5, 'seven': 7, 'two': 2, 'one': 1, 'three': 3, 'six': 6, 'zero': 0}

It also allows multiple iterables to be unpacked in a single function call.

>>> range(*[1, 10], *[2])
range(1, 10, 2)

(Thanks to mgilson for the PEP link.)


回答 12

除函数调用外,* args和** kwargs在类层次结构中很有用,并且还避免了必须__init__在Python中编写方法。在类似Django代码的框架中可以看到类似的用法。

例如,

def __init__(self, *args, **kwargs):
    for attribute_name, value in zip(self._expected_attributes, args):
        setattr(self, attribute_name, value)
        if kwargs.has_key(attribute_name):
            kwargs.pop(attribute_name)

    for attribute_name in kwargs.viewkeys():
        setattr(self, attribute_name, kwargs[attribute_name])

子类可以是

class RetailItem(Item):
    _expected_attributes = Item._expected_attributes + ['name', 'price', 'category', 'country_of_origin']

class FoodItem(RetailItem):
    _expected_attributes = RetailItem._expected_attributes +  ['expiry_date']

然后将该子类实例化为

food_item = FoodItem(name = 'Jam', 
                     price = 12.0, 
                     category = 'Foods', 
                     country_of_origin = 'US', 
                     expiry_date = datetime.datetime.now())

此外,具有仅对该子类实例有意义的新属性的子类可以调用Base类__init__以卸载属性设置。这是通过* args和** kwargs完成的。主要使用kwargs,以便使用命名参数可以读取代码。例如,

class ElectronicAccessories(RetailItem):
    _expected_attributes = RetailItem._expected_attributes +  ['specifications']
    # Depend on args and kwargs to populate the data as needed.
    def __init__(self, specifications = None, *args, **kwargs):
        self.specifications = specifications  # Rest of attributes will make sense to parent class.
        super(ElectronicAccessories, self).__init__(*args, **kwargs)

可以被形容为

usb_key = ElectronicAccessories(name = 'Sandisk', 
                                price = '$6.00', 
                                category = 'Electronics',
                                country_of_origin = 'CN',
                                specifications = '4GB USB 2.0/USB 3.0')

完整的代码在这里

In addition to function calls, *args and **kwargs are useful in class hierarchies and also avoid having to write __init__ method in Python. Similar usage can seen in frameworks like Django code.

For example,

def __init__(self, *args, **kwargs):
    for attribute_name, value in zip(self._expected_attributes, args):
        setattr(self, attribute_name, value)
        if kwargs.has_key(attribute_name):
            kwargs.pop(attribute_name)

    for attribute_name in kwargs.viewkeys():
        setattr(self, attribute_name, kwargs[attribute_name])

A subclass can then be

class RetailItem(Item):
    _expected_attributes = Item._expected_attributes + ['name', 'price', 'category', 'country_of_origin']

class FoodItem(RetailItem):
    _expected_attributes = RetailItem._expected_attributes +  ['expiry_date']

The subclass then be instantiated as

food_item = FoodItem(name = 'Jam', 
                     price = 12.0, 
                     category = 'Foods', 
                     country_of_origin = 'US', 
                     expiry_date = datetime.datetime.now())

Also, a subclass with a new attribute which makes sense only to that subclass instance can call the Base class __init__ to offload the attributes setting. This is done through *args and **kwargs. kwargs mainly used so that code is readable using named arguments. For example,

class ElectronicAccessories(RetailItem):
    _expected_attributes = RetailItem._expected_attributes +  ['specifications']
    # Depend on args and kwargs to populate the data as needed.
    def __init__(self, specifications = None, *args, **kwargs):
        self.specifications = specifications  # Rest of attributes will make sense to parent class.
        super(ElectronicAccessories, self).__init__(*args, **kwargs)

which can be instatiated as

usb_key = ElectronicAccessories(name = 'Sandisk', 
                                price = '$6.00', 
                                category = 'Electronics',
                                country_of_origin = 'CN',
                                specifications = '4GB USB 2.0/USB 3.0')

The complete code is here


回答 13

建立在昵称的答案上

def foo(param1, *param2):
    print(param1)
    print(param2)


def bar(param1, **param2):
    print(param1)
    print(param2)


def three_params(param1, *param2, **param3):
    print(param1)
    print(param2)
    print(param3)


foo(1, 2, 3, 4, 5)
print("\n")
bar(1, a=2, b=3)
print("\n")
three_params(1, 2, 3, 4, s=5)

输出:

1
(2, 3, 4, 5)

1
{'a': 2, 'b': 3}

1
(2, 3, 4)
{'s': 5}

基本上,任何数量的位置参数都可以使用* args,任何命名参数(或kwargs aka关键字参数)都可以使用** kwargs。

Building on nickd’s answer

def foo(param1, *param2):
    print(param1)
    print(param2)


def bar(param1, **param2):
    print(param1)
    print(param2)


def three_params(param1, *param2, **param3):
    print(param1)
    print(param2)
    print(param3)


foo(1, 2, 3, 4, 5)
print("\n")
bar(1, a=2, b=3)
print("\n")
three_params(1, 2, 3, 4, s=5)

Output:

1
(2, 3, 4, 5)

1
{'a': 2, 'b': 3}

1
(2, 3, 4)
{'s': 5}

Basically, any number of positional arguments can use *args and any named arguments (or kwargs aka keyword arguments) can use **kwargs.


回答 14

*args**kwargs:允许您将可变数量的参数传递给函数。

*args:用于将非关键字的可变长度参数列表发送给函数:

def args(normal_arg, *argv):
    print("normal argument:", normal_arg)

    for arg in argv:
        print("Argument in list of arguments from *argv:", arg)

args('animals', 'fish', 'duck', 'bird')

将生成:

normal argument: animals
Argument in list of arguments from *argv: fish
Argument in list of arguments from *argv: duck
Argument in list of arguments from *argv: bird

**kwargs*

**kwargs允许您将关键字的可变参数长度传递给函数。**kwargs如果要处理函数中的命名参数,则应使用。

def who(**kwargs):
    if kwargs is not None:
        for key, value in kwargs.items():
            print("Your %s is %s." % (key, value))

who(name="Nikola", last_name="Tesla", birthday="7.10.1856", birthplace="Croatia")  

将生成:

Your name is Nikola.
Your last_name is Tesla.
Your birthday is 7.10.1856.
Your birthplace is Croatia.

*args and **kwargs: allow you to pass a variable number of arguments to a function.

*args: is used to send a non-keyworded variable length argument list to the function:

def args(normal_arg, *argv):
    print("normal argument:", normal_arg)

    for arg in argv:
        print("Argument in list of arguments from *argv:", arg)

args('animals', 'fish', 'duck', 'bird')

Will produce:

normal argument: animals
Argument in list of arguments from *argv: fish
Argument in list of arguments from *argv: duck
Argument in list of arguments from *argv: bird

**kwargs*

**kwargs allows you to pass keyworded variable length of arguments to a function. You should use **kwargs if you want to handle named arguments in a function.

def who(**kwargs):
    if kwargs is not None:
        for key, value in kwargs.items():
            print("Your %s is %s." % (key, value))

who(name="Nikola", last_name="Tesla", birthday="7.10.1856", birthplace="Croatia")  

Will produce:

Your name is Nikola.
Your last_name is Tesla.
Your birthday is 7.10.1856.
Your birthplace is Croatia.

回答 15

这个例子可以帮助您记住*args**kwargs甚至super可以立即在Python中继承。

class base(object):
    def __init__(self, base_param):
        self.base_param = base_param


class child1(base): # inherited from base class
    def __init__(self, child_param, *args) # *args for non-keyword args
        self.child_param = child_param
        super(child1, self).__init__(*args) # call __init__ of the base class and initialize it with a NON-KEYWORD arg

class child2(base):
    def __init__(self, child_param, **kwargs):
        self.child_param = child_param
        super(child2, self).__init__(**kwargs) # call __init__ of the base class and initialize it with a KEYWORD arg

c1 = child1(1,0)
c2 = child2(1,base_param=0)
print c1.base_param # 0
print c1.child_param # 1
print c2.base_param # 0
print c2.child_param # 1

This example would help you remember *args, **kwargs and even super and inheritance in Python at once.

class base(object):
    def __init__(self, base_param):
        self.base_param = base_param


class child1(base): # inherited from base class
    def __init__(self, child_param, *args) # *args for non-keyword args
        self.child_param = child_param
        super(child1, self).__init__(*args) # call __init__ of the base class and initialize it with a NON-KEYWORD arg

class child2(base):
    def __init__(self, child_param, **kwargs):
        self.child_param = child_param
        super(child2, self).__init__(**kwargs) # call __init__ of the base class and initialize it with a KEYWORD arg

c1 = child1(1,0)
c2 = child2(1,base_param=0)
print c1.base_param # 0
print c1.child_param # 1
print c2.base_param # 0
print c2.child_param # 1

回答 16

在函数中同时使用两者的一个很好的例子是:

>>> def foo(*arg,**kwargs):
...     print arg
...     print kwargs
>>>
>>> a = (1, 2, 3)
>>> b = {'aa': 11, 'bb': 22}
>>>
>>>
>>> foo(*a,**b)
(1, 2, 3)
{'aa': 11, 'bb': 22}
>>>
>>>
>>> foo(a,**b) 
((1, 2, 3),)
{'aa': 11, 'bb': 22}
>>>
>>>
>>> foo(a,b) 
((1, 2, 3), {'aa': 11, 'bb': 22})
{}
>>>
>>>
>>> foo(a,*b)
((1, 2, 3), 'aa', 'bb')
{}

A good example of using both in a function is:

>>> def foo(*arg,**kwargs):
...     print arg
...     print kwargs
>>>
>>> a = (1, 2, 3)
>>> b = {'aa': 11, 'bb': 22}
>>>
>>>
>>> foo(*a,**b)
(1, 2, 3)
{'aa': 11, 'bb': 22}
>>>
>>>
>>> foo(a,**b) 
((1, 2, 3),)
{'aa': 11, 'bb': 22}
>>>
>>>
>>> foo(a,b) 
((1, 2, 3), {'aa': 11, 'bb': 22})
{}
>>>
>>>
>>> foo(a,*b)
((1, 2, 3), 'aa', 'bb')
{}

回答 17

TL; DR

以下是6种不同的使用情况*,并**在Python编程:

  1. 要使用*args:接受任意数量的位置参数 def foo(*args): pass,此处foo接受任意数量的位置参数,即以下调用有效foo(1)foo(1, 'bar')
  2. 要使用**kwargs:接受任意数量的关键字参数 def foo(**kwargs): pass,此处的’foo’接受任意数量的关键字参数,即以下调用有效foo(name='Tom')foo(name='Tom', age=33)
  3. 要使用*args, **kwargs:接受任意数量的位置和关键字参数 def foo(*args, **kwargs): pass,此处foo接受任意数量的位置和关键字参数,即以下调用是有效的foo(1,name='Tom')foo(1, 'bar', name='Tom', age=33)
  4. 要使用*:强制使用 仅关键字参数def foo(pos1, pos2, *, kwarg1): pass,这*意味着foo仅在pos2之后接受关键字参数,因此foo(1, 2, 3)引发TypeError但foo(1, 2, kwarg1=3)可以。
  5. 要使用*_(注:仅是一种约定)对更多的位置参数不再表示兴趣 def foo(bar, baz, *_): pass:(按约定)意味着(按约定)在其工作中foo仅使用barbaz参数,而将忽略其他参数。
  6. 要使用\**_(注:仅是一种约定)对更多关键字参数不再表示兴趣 def foo(bar, baz, **_): pass:(按约定)意味着(按约定)在其工作中foo仅使用barbaz参数,而将忽略其他参数。

奖励:从python 3.8开始,可以/在函数定义中使用来强制仅位置参数。在以下示例中,参数a和b是仅位置信息,而c或d可以是位置信息或关键字,而e或f必须是关键字:

def f(a, b, /, c, d, *, e, f):
    pass

TL;DR

Below are 6 different use cases for * and ** in python programming:

  1. To accept any number of positional arguments using *args: def foo(*args): pass, here foo accepts any number of positional arguments, i. e., the following calls are valid foo(1), foo(1, 'bar')
  2. To accept any number of keyword arguments using **kwargs: def foo(**kwargs): pass, here ‘foo’ accepts any number of keyword arguments, i. e., the following calls are valid foo(name='Tom'), foo(name='Tom', age=33)
  3. To accept any number of positional and keyword arguments using *args, **kwargs: def foo(*args, **kwargs): pass, here foo accepts any number of positional and keyword arguments, i. e., the following calls are valid foo(1,name='Tom'), foo(1, 'bar', name='Tom', age=33)
  4. To enforce keyword only arguments using *: def foo(pos1, pos2, *, kwarg1): pass, here * means that foo only accept keyword arguments after pos2, hence foo(1, 2, 3) raises TypeError but foo(1, 2, kwarg1=3) is ok.
  5. To express no further interest in more positional arguments using *_ (Note: this is a convention only): def foo(bar, baz, *_): pass means (by convention) foo only uses bar and baz arguments in its working and will ignore others.
  6. To express no further interest in more keyword arguments using \**_ (Note: this is a convention only): def foo(bar, baz, **_): pass means (by convention) foo only uses bar and baz arguments in its working and will ignore others.

BONUS: From python 3.8 onward, one can use / in function definition to enforce positional only parameters. In the following example, parameters a and b are positional-only, while c or d can be positional or keyword, and e or f are required to be keywords:

def f(a, b, /, c, d, *, e, f):
    pass

回答 18

TL; DR

它包传递给函数的参数将listdict分别在函数体中。当您定义函数签名时,如下所示:

def func(*args, **kwds):
    # do stuff

可以使用任意数量的参数和关键字参数来调用它。非关键字参数打包到args函数体内调用的列表中,而关键字参数打包到kwds函数体内调用的dict中。

func("this", "is a list of", "non-keyowrd", "arguments", keyword="ligma", options=[1,2,3])

现在函数体,当函数被调用里面,有两个局部变量,args这是一个有值列表["this", "is a list of", "non-keyword", "arguments"]kwds它是一个dict具有价值{"keyword" : "ligma", "options" : [1,2,3]}


这也可以反向进行,即从呼叫方进行。例如,如果您将函数定义为:

def f(a, b, c, d=1, e=10):
    # do stuff

您可以通过解压缩调用范围中的迭代器或映射来调用它:

iterable = [1, 20, 500]
mapping = {"d" : 100, "e": 3}
f(*iterable, **mapping)
# That call is equivalent to
f(1, 20, 500, d=100, e=3)

TL;DR

It packs arguments passed to the function into list and dict respectively inside the function body. When you define a function signature like this:

def func(*args, **kwds):
    # do stuff

it can be called with any number of arguments and keyword arguments. The non-keyword arguments get packed into a list called args inside the the function body and the keyword arguments get packed into a dict called kwds inside the function body.

func("this", "is a list of", "non-keyowrd", "arguments", keyword="ligma", options=[1,2,3])

now inside the function body, when the function is called, there are two local variables, args which is a list having value ["this", "is a list of", "non-keyword", "arguments"] and kwds which is a dict having value {"keyword" : "ligma", "options" : [1,2,3]}


This also works in reverse, i.e. from the caller side. for example if you have a function defined as:

def f(a, b, c, d=1, e=10):
    # do stuff

you can call it with by unpacking iterables or mappings you have in the calling scope:

iterable = [1, 20, 500]
mapping = {"d" : 100, "e": 3}
f(*iterable, **mapping)
# That call is equivalent to
f(1, 20, 500, d=100, e=3)

回答 19

语境

  • python 3.x
  • 开箱 **
  • 与字符串格式一起使用

与字符串格式一起使用

除了此主题中的答案外,这是其他地方未提及的另一个细节。这扩展了布拉德·所罗门答案

**使用python时,使用进行解包也很有用str.format

这有点类似于您可以使用python f-strings f-string进行的操作,但是增加了声明保留变量的字典的开销(f-string不需要字典)。

快速范例

  ## init vars
  ddvars = dict()
  ddcalc = dict()
  pass
  ddvars['fname']     = 'Huomer'
  ddvars['lname']     = 'Huimpson'
  ddvars['motto']     = 'I love donuts!'
  ddvars['age']       = 33
  pass
  ddcalc['ydiff']     = 5
  ddcalc['ycalc']     = ddvars['age'] + ddcalc['ydiff']
  pass
  vdemo = []

  ## ********************
  ## single unpack supported in py 2.7
  vdemo.append('''
  Hello {fname} {lname}!

  Today you are {age} years old!

  We love your motto "{motto}" and we agree with you!
  '''.format(**ddvars)) 
  pass

  ## ********************
  ## multiple unpack supported in py 3.x
  vdemo.append('''
  Hello {fname} {lname}!

  In {ydiff} years you will be {ycalc} years old!
  '''.format(**ddvars,**ddcalc)) 
  pass

  ## ********************
  print(vdemo[-1])

Context

  • python 3.x
  • unpacking with **
  • use with string formatting

Use with string formatting

In addition to the answers in this thread, here is another detail that was not mentioned elsewhere. This expands on the answer by Brad Solomon

Unpacking with ** is also useful when using python str.format.

This is somewhat similar to what you can do with python f-strings f-string but with the added overhead of declaring a dict to hold the variables (f-string does not require a dict).

Quick Example

  ## init vars
  ddvars = dict()
  ddcalc = dict()
  pass
  ddvars['fname']     = 'Huomer'
  ddvars['lname']     = 'Huimpson'
  ddvars['motto']     = 'I love donuts!'
  ddvars['age']       = 33
  pass
  ddcalc['ydiff']     = 5
  ddcalc['ycalc']     = ddvars['age'] + ddcalc['ydiff']
  pass
  vdemo = []

  ## ********************
  ## single unpack supported in py 2.7
  vdemo.append('''
  Hello {fname} {lname}!

  Today you are {age} years old!

  We love your motto "{motto}" and we agree with you!
  '''.format(**ddvars)) 
  pass

  ## ********************
  ## multiple unpack supported in py 3.x
  vdemo.append('''
  Hello {fname} {lname}!

  In {ydiff} years you will be {ycalc} years old!
  '''.format(**ddvars,**ddcalc)) 
  pass

  ## ********************
  print(vdemo[-1])


回答 20

  • def foo(param1, *param2):是一种方法,可以接受任意数量的值*param2
  • def bar(param1, **param2): 是一种可以使用键接受任意数量的值的方法 *param2
  • param1 是一个简单的参数。

例如,在Java中实现varargs的语法如下:

accessModifier methodName(datatype arg) {
    // method body
}
  • def foo(param1, *param2): is a method can accept arbitrary number of values for *param2,
  • def bar(param1, **param2): is a method can accept arbitrary number of values with keys for *param2
  • param1 is a simple parameter.

For example, the syntax for implementing varargs in Java as follows:

accessModifier methodName(datatype… arg) {
    // method body
}

如何在Python中进行换行(换行)?

问题:如何在Python中进行换行(换行)?

我有一长行代码,我想在多行中分解。我使用什么,语法是什么?

例如,添加一串字符串,

e = 'a' + 'b' + 'c' + 'd'

并分成两行,如下所示:

e = 'a' + 'b' +
    'c' + 'd'

I have a long line of code that I want to break up among multiple lines. What do I use and what is the syntax?

For example, adding a bunch of strings,

e = 'a' + 'b' + 'c' + 'd'

and have it in two lines like this:

e = 'a' + 'b' +
    'c' + 'd'

回答 0

什么线?您只需在下一行就有参数就不会有任何问题:

a = dostuff(blahblah1, blahblah2, blahblah3, blahblah4, blahblah5, 
            blahblah6, blahblah7)

否则,您可以执行以下操作:

if a == True and \
   b == False

查看样式指南以获取更多信息。

从示例行中:

a = '1' + '2' + '3' + \
    '4' + '5'

要么:

a = ('1' + '2' + '3' +
    '4' + '5')

请注意,样式指南指出,最好使用带括号的隐式连续符,但是在这种特殊情况下,仅在表达式周围加上括号可能是错误的方法。

What is the line? You can just have arguments on the next line without any problems:

a = dostuff(blahblah1, blahblah2, blahblah3, blahblah4, blahblah5, 
            blahblah6, blahblah7)

Otherwise you can do something like this:

if a == True and \
   b == False

Check the style guide for more information.

From your example line:

a = '1' + '2' + '3' + \
    '4' + '5'

Or:

a = ('1' + '2' + '3' +
    '4' + '5')

Note that the style guide says that using the implicit continuation with parentheses is preferred, but in this particular case just adding parentheses around your expression is probably the wrong way to go.


回答 1

PEP 8-Python代码样式指南

包装长行的首选方法是在括号,方括号和花括号内使用Python的隐含行连续性。通过将表达式包装在括号中,可以将长行分成多行。应优先使用这些,而不是使用反斜杠进行行连续。

有时反斜杠可能仍然合适。例如,长的多个with语句不能使用隐式连续,因此可以使用反斜杠:

with open('/path/to/some/file/you/want/to/read') as file_1, \
        open('/path/to/some/file/being/written', 'w') as file_2:
    file_2.write(file_1.read())

另一种此类情况是使用assert语句。

确保适当缩进续行。绕开二元运算符的首选位置是运算符之后,而不是在运算符之前。一些例子:

class Rectangle(Blob):

    def __init__(self, width, height,
                 color='black', emphasis=None, highlight=0):
        if (width == 0 and height == 0 and
                color == 'red' and emphasis == 'strong' or
                highlight > 100):
            raise ValueError("sorry, you lose")
        if width == 0 and height == 0 and (color == 'red' or
                                           emphasis is None):
            raise ValueError("I don't think so -- values are %s, %s" %
                             (width, height))
        Blob.__init__(self, width, height,
                      color, emphasis, highlight)

现在,PEP8建议数学家及其发布者使用相反的约定(用于在二进制运算处中断)以提高可读性。

唐纳德·克努斯(Donald Knuth)二元运算符垂直对齐之前先断后合的风格,从而减少了确定要添加和减去的项时的工作量。

PEP8:换行符应该在二进制运算符之前还是之后?

唐纳德·克努斯(Donald Knuth)在他的《计算机和排版》系列中解释了传统规则:“尽管段落中的公式总是在二进制运算和关系之后中断,但显示的公式总是在二进制运算和关系之前中断” [3]。

遵循数学的传统通常会导致代码更具可读性:

# Yes: easy to match operators with operands
income = (gross_wages
          + taxable_interest
          + (dividends - qualified_dividends)
          - ira_deduction
          - student_loan_interest)

在Python代码中,只要约定在本地是一致的,就可以在二进制运算符之前或之后中断。对于新代码,建议使用Knuth的样式。

[3]:Donald Knuth的The TeXBook,第195和196页

From PEP 8 — Style Guide for Python Code:

The preferred way of wrapping long lines is by using Python’s implied line continuation inside parentheses, brackets and braces. Long lines can be broken over multiple lines by wrapping expressions in parentheses. These should be used in preference to using a backslash for line continuation.

Backslashes may still be appropriate at times. For example, long, multiple with-statements cannot use implicit continuation, so backslashes are acceptable:

with open('/path/to/some/file/you/want/to/read') as file_1, \
        open('/path/to/some/file/being/written', 'w') as file_2:
    file_2.write(file_1.read())

Another such case is with assert statements.

Make sure to indent the continued line appropriately. The preferred place to break around a binary operator is after the operator, not before it. Some examples:

class Rectangle(Blob):

    def __init__(self, width, height,
                 color='black', emphasis=None, highlight=0):
        if (width == 0 and height == 0 and
                color == 'red' and emphasis == 'strong' or
                highlight > 100):
            raise ValueError("sorry, you lose")
        if width == 0 and height == 0 and (color == 'red' or
                                           emphasis is None):
            raise ValueError("I don't think so -- values are %s, %s" %
                             (width, height))
        Blob.__init__(self, width, height,
                      color, emphasis, highlight)

PEP8 now recommends the opposite convention (for breaking at binary operations) used by mathematicians and their publishers to improve readability.

Donald Knuth’s style of breaking before a binary operator aligns operators vertically, thus reducing the eye’s workload when determining which items are added and subtracted.

From PEP8: Should a line break before or after a binary operator?:

Donald Knuth explains the traditional rule in his Computers and Typesetting series: “Although formulas within a paragraph always break after binary operations and relations, displayed formulas always break before binary operations”[3].

Following the tradition from mathematics usually results in more readable code:

# Yes: easy to match operators with operands
income = (gross_wages
          + taxable_interest
          + (dividends - qualified_dividends)
          - ira_deduction
          - student_loan_interest)

In Python code, it is permissible to break before or after a binary operator, as long as the convention is consistent locally. For new code Knuth’s style is suggested.

[3]: Donald Knuth’s The TeXBook, pages 195 and 196


回答 2

使用反斜杠结束行的危险在于,如果在反斜杠之后添加空格(当然很难看到),则反斜杠将不再执行您原本的想法。

有关更多信息,请参见Python习语和反习语(对于Python 2Python 3)。

The danger in using a backslash to end a line is that if whitespace is added after the backslash (which, of course, is very hard to see), the backslash is no longer doing what you thought it was.

See Python Idioms and Anti-Idioms (for Python 2 or Python 3) for more.


回答 3

\在行末放置a 或将语句括在parens中( .. )。从IBM

b = ((i1 < 20) and
     (i2 < 30) and
     (i3 < 40))

要么

b = (i1 < 20) and \
    (i2 < 30) and \
    (i3 < 40)

Put a \ at the end of your line or enclose the statement in parens ( .. ). From IBM:

b = ((i1 < 20) and
     (i2 < 30) and
     (i3 < 40))

or

b = (i1 < 20) and \
    (i2 < 30) and \
    (i3 < 40)

回答 4

您可以在括号和大括号之间打断线。此外,您可以将反斜杠字符附加\到一行以显式中断它:

x = (tuples_first_value,
     second_value)
y = 1 + \
    2

You can break lines in between parenthesises and braces. Additionally, you can append the backslash character \ to a line to explicitly break it:

x = (tuples_first_value,
     second_value)
y = 1 + \
    2

回答 5

从马口中:显式线连接

可以使用反斜杠字符(\)将两条或更多条物理行连接为逻辑行,如下所示:当一条物理行以不属于字符串文字或注释的反斜杠结尾时,则将其与以下行合并成一条逻辑行,删除反斜杠和以下换行符。例如:

if 1900 < year < 2100 and 1 <= month <= 12 \
   and 1 <= day <= 31 and 0 <= hour < 24 \
   and 0 <= minute < 60 and 0 <= second < 60:   # Looks like a valid date
        return 1

以反斜杠结尾的行不能带有注释。反斜杠不会继续发表评论。除字符串文字外,反斜杠不会延续令牌(即,字符串文字之外的令牌无法使用反斜杠在物理行之间进行拆分)。反斜杠在字符串文字之外的其他行上是非法的。

From the horse’s mouth: Explicit line joining

Two or more physical lines may be joined into logical lines using backslash characters (\), as follows: when a physical line ends in a backslash that is not part of a string literal or comment, it is joined with the following forming a single logical line, deleting the backslash and the following end-of-line character. For example:

if 1900 < year < 2100 and 1 <= month <= 12 \
   and 1 <= day <= 31 and 0 <= hour < 24 \
   and 0 <= minute < 60 and 0 <= second < 60:   # Looks like a valid date
        return 1

A line ending in a backslash cannot carry a comment. A backslash does not continue a comment. A backslash does not continue a token except for string literals (i.e., tokens other than string literals cannot be split across physical lines using a backslash). A backslash is illegal elsewhere on a line outside a string literal.


回答 6

这可能不是Python的方式,但是我通常使用带有join函数的列表来编写长字符串,例如SQL查询:

query = " ".join([
    'SELECT * FROM "TableName"',
    'WHERE "SomeColumn1"=VALUE',
    'ORDER BY "SomeColumn2"',
    'LIMIT 5;'
])

It may not be the Pythonic way, but I generally use a list with the join function for writing a long string, like SQL queries:

query = " ".join([
    'SELECT * FROM "TableName"',
    'WHERE "SomeColumn1"=VALUE',
    'ORDER BY "SomeColumn2"',
    'LIMIT 5;'
])

回答 7

摘自《 The Hitchhiker’s Guide to Python(Line Continuation)》:

当逻辑代码行长于可接受的限制时,您需要将其划分为多条物理行。如果该行的最后符是反斜杠,则Python解释器将连接连续的行。在某些情况下这很有用,但由于其易碎性通常应避免使用:在反斜杠后的行末添加空格将破坏代码并可能产生意外结果。

更好的解决方案是在元素周围使用括号。在行尾留下未封闭的括号的情况下,Python解释器将加入下一行,直到括号被封闭为止。花括号和方括号的行为相同。

但是,通常情况下,必须分开一条较长的逻辑线表明您正在尝试同时执行太多操作,这可能会影响可读性。

话虽如此,这是一个考虑多次导入的示例(当超出行限制时,在PEP-8上定义),通常也适用于字符串:

from app import (
    app, abort, make_response, redirect, render_template, request, session
)

Taken from The Hitchhiker’s Guide to Python (Line Continuation):

When a logical line of code is longer than the accepted limit, you need to split it over multiple physical lines. The Python interpreter will join consecutive lines if the last character of the line is a backslash. This is helpful in some cases, but should usually be avoided because of its fragility: a white space added to the end of the line, after the backslash, will break the code and may have unexpected results.

A better solution is to use parentheses around your elements. Left with an unclosed parenthesis on an end-of-line the Python interpreter will join the next line until the parentheses are closed. The same behaviour holds for curly and square braces.

However, more often than not, having to split a long logical line is a sign that you are trying to do too many things at the same time, which may hinder readability.

Having that said, here’s an example considering multiple imports (when exceeding line limits, defined on PEP-8), also applied to strings in general:

from app import (
    app, abort, make_response, redirect, render_template, request, session
)

回答 8

如果由于长字符串而要中断行,可以将该字符串分成几部分:

long_string = "a very long string"
print("a very long string")

将被替换

long_string = (
  "a "
  "very "
  "long "
  "string"
)
print(
  "a "
  "very "
  "long "
  "string"
)

两个打印语句的输出:

a very long string

注意情感中的括号。

还要注意,将文字字符串分成几部分,只允许在部分字符串上使用文字前缀:

s = (
  "2+2="
  f"{2+2}"
)

If you want to break your line because of a long literal string, you can break that string into pieces:

long_string = "a very long string"
print("a very long string")

will be replaced by

long_string = (
  "a "
  "very "
  "long "
  "string"
)
print(
  "a "
  "very "
  "long "
  "string"
)

Output for both print statements:

a very long string

Notice the parenthesis in the affectation.

Notice also that breaking literal strings into pieces allows to use the literal prefix only on parts of the string:

s = (
  "2+2="
  f"{2+2}"
)

回答 9

使用行继续运算符,即“ \”

例子:

# Ex.1

x = 1
s =  x + x**2/2 + x**3/3 \
       + x**4/4 + x**5/5 \
       + x**6/6 + x**7/7 \
       + x**8/8
print(s)
# 2.7178571428571425


----------


# Ex.2

text = ('Put several strings within parentheses ' \
        'to have them joined together.')
print(text)


----------


# Ex.3

x = 1
s =  x + x**2/2 \
       + x**3/3 \
       + x**4/4 \
       + x**6/6 \
       + x**8/8
print(s)
# 2.3749999999999996

Use the line continuation operator i.e. “\”

Examples:

# Ex.1

x = 1
s =  x + x**2/2 + x**3/3 \
       + x**4/4 + x**5/5 \
       + x**6/6 + x**7/7 \
       + x**8/8
print(s)
# 2.7178571428571425


----------


# Ex.2

text = ('Put several strings within parentheses ' \
        'to have them joined together.')
print(text)


----------


# Ex.3

x = 1
s =  x + x**2/2 \
       + x**3/3 \
       + x**4/4 \
       + x**6/6 \
       + x**8/8
print(s)
# 2.3749999999999996

有人可以用Python解释__all__吗?

问题:有人可以用Python解释__all__吗?

我越来越多地使用Python,并且不断看到__all__在不同__init__.py文件中设置的变量。有人可以解释这是什么吗?

I have been using Python more and more, and I keep seeing the variable __all__ set in different __init__.py files. Can someone explain what this does?


回答 0

这是该模块的公共对象的列表,由解释import *。它覆盖了隐藏所有以下划线开头的所有内容的默认设置。

It’s a list of public objects of that module, as interpreted by import *. It overrides the default of hiding everything that begins with an underscore.


回答 1

链接到(但未在此处明确提及的)确切是何时__all__使用。它是一串字符串,定义了在模块from <module> import *上使用时将导出模块中的哪些符号。

例如,以下代码foo.py显式导出符号barbaz

__all__ = ['bar', 'baz']

waz = 5
bar = 10
def baz(): return 'baz'

然后可以像下面这样导入这些符号:

from foo import *

print(bar)
print(baz)

# The following will trigger an exception, as "waz" is not exported by the module
print(waz)

如果__all__上面的内容已被注释掉,则此代码将执行完毕,因为的默认行为import *是从给定的命名空间中导入所有不以下划线开头的符号。

参考:https : //docs.python.org/tutorial/modules.html#importing-from-a-package

注意:__all__影响from <module> import *行为。__all__仍然可以从模块外部访问未提及的成员,并可以使用导入from <module> import <member>

Linked to, but not explicitly mentioned here, is exactly when __all__ is used. It is a list of strings defining what symbols in a module will be exported when from <module> import * is used on the module.

For example, the following code in a foo.py explicitly exports the symbols bar and baz:

__all__ = ['bar', 'baz']

waz = 5
bar = 10
def baz(): return 'baz'

These symbols can then be imported like so:

from foo import *

print(bar)
print(baz)

# The following will trigger an exception, as "waz" is not exported by the module
print(waz)

If the __all__ above is commented out, this code will then execute to completion, as the default behaviour of import * is to import all symbols that do not begin with an underscore, from the given namespace.

Reference: https://docs.python.org/tutorial/modules.html#importing-from-a-package

NOTE: __all__ affects the from <module> import * behavior only. Members that are not mentioned in __all__ are still accessible from outside the module and can be imported with from <module> import <member>.


回答 2

用Python解释__all__吗?

我不断__all__在不同__init__.py文件中看到变量集。

这是做什么的?

怎么__all__办?

它从模块中声明语义上的“公共”名称。如果中有一个名称__all__,则希望用户使用它,并且他们可以期望它不会更改。

它也会对程序产生影响:

import *

__all__在一个模块中,例如module.py

__all__ = ['foo', 'Bar']

表示当您import *从模块__all__中导入时,仅导入中的名称:

from module import *               # imports foo and Bar

文档工具

文档和代码自动完成工具也可能(实际上应该)检查,__all__以确定哪些名称可以显示为模块可用。

__init__.py 使目录成为Python包

文档

这些__init__.py文件是使Python将目录视为包含包所必需的;这样做是为了防止具有通用名称的目录(例如字符串)无意间隐藏了稍后在模块搜索路径中出现的有效模块。

在最简单的情况下,__init__.py可以只是一个空文件,但它也可以执行包的初始化代码或设置__all__变量。

因此,__init__.py可以声明__all__一个

管理API:

程序包通常由可以相互导入但必须与__init__.py文件捆绑在一起的模块组成。该文件使目录成为实际的Python包。例如,假设您的软件包中包含以下文件:

package
├── __init__.py
├── module_1.py
└── module_2.py

让我们使用Python创建这些文件,以便您可以继续进行操作-您可以将以下内容粘贴到Python 3 Shell中:

from pathlib import Path

package = Path('package')
package.mkdir()

(package / '__init__.py').write_text("""
from .module_1 import *
from .module_2 import *
""")

package_module_1 = package / 'module_1.py'
package_module_1.write_text("""
__all__ = ['foo']
imp_detail1 = imp_detail2 = imp_detail3 = None
def foo(): pass
""")

package_module_2 = package / 'module_2.py'
package_module_2.write_text("""
__all__ = ['Bar']
imp_detail1 = imp_detail2 = imp_detail3 = None
class Bar: pass
""")

现在,您已经提供了一个完整的api,供其他人在导入您的软件包时使用,如下所示:

import package
package.foo()
package.Bar()

而且,该软件包不会包含您在创建使package命名空间混乱的模块时使用的所有其他实现细节。

__all____init__.py

经过更多的工作后,也许您已经确定模块太大(就像成千上万的线?),需要拆分。因此,您需要执行以下操作:

package
├── __init__.py
├── module_1
│   ├── foo_implementation.py
│   └── __init__.py
└── module_2
    ├── Bar_implementation.py
    └── __init__.py

首先,使子包目录具有与模块相同的名称:

subpackage_1 = package / 'module_1'
subpackage_1.mkdir()
subpackage_2 = package / 'module_2'
subpackage_2.mkdir()

移动实现:

package_module_1.rename(subpackage_1 / 'foo_implementation.py')
package_module_2.rename(subpackage_2 / 'Bar_implementation.py')

__init__.py为声明__all__每个子包的子包创建:

(subpackage_1 / '__init__.py').write_text("""
from .foo_implementation import *
__all__ = ['foo']
""")
(subpackage_2 / '__init__.py').write_text("""
from .Bar_implementation import *
__all__ = ['Bar']
""")

现在,您仍然在程序包级别配置了api:

>>> import package
>>> package.foo()
>>> package.Bar()
<package.module_2.Bar_implementation.Bar object at 0x7f0c2349d210>

而且,您可以轻松地在API中添加可以在子包级别而不是子包的模块级别进行管理的内容。如果要向API添加新名称,只需更新__init__.py,例如在module_2中:

from .Bar_implementation import *
from .Baz_implementation import *
__all__ = ['Bar', 'Baz']

如果您还没有准备好在Baz顶级API中进行发布,则__init__.py可以在顶级中进行以下操作:

from .module_1 import *       # also constrained by __all__'s
from .module_2 import *       # in the __init__.py's
__all__ = ['foo', 'Bar']     # further constraining the names advertised

并且如果您的用户知道的可用性Baz,他们可以使用它:

import package
package.Baz()

但是如果他们不知道,其他工具(例如pydoc)将不会通知他们。

您可以在Baz准备黄金时间时更改它:

from .module_1 import *
from .module_2 import *
__all__ = ['foo', 'Bar', 'Baz']

前缀___all__

默认情况下,Python将导出所有不以开头的名称_。您当然可以依靠这种机制。实际上,Python标准库中的某些软件包确实依赖于此,但是要这样做,它们会为导入内容加上别名,例如ctypes/__init__.py

import os as _os, sys as _sys

使用_约定可能更优雅,因为它消除了再次命名名称的麻烦。但这增加了导入的冗余(如果您有很多导入的话),很容易忘记一贯地执行此操作-最后要做的就是无限期地支持您打算仅作为实现细节的内容,只是因为您_在命名函数时忘了给加上前缀。

我个人__all__在模块开发生命周期的早期就编写了模块,以便其他可能使用我的代码的人知道应该使用什么而不应该使用什么。

标准库中的大多数软件包也使用__all__

当避免__all__是有道理的

坚持使用_前缀约定代替__all__什么时候是有意义的:

  • 您仍处于早期开发模式,没有用户,并且不断调整API。
  • 也许您确实有用户,但是您拥有涵盖该API的单元测试,但您仍在积极地添加到API并进行开发方面的调整。

一个export装饰

使用的缺点__all__是您必须编写两次导出的函数和类的名称-并且信息与定义保持分开。我们可以使用装饰器解决此问题。

我从大卫·比兹利(David Beazley)关于包装的演讲中想到了这样的出口装饰商。在CPython的传统导入器中,此实现似乎运行良好。如果您有一个特殊的导入挂钩或系统,我不保证,但是如果您采用它,撤消它就很简单了-您只需要手动将名称重新添加到__all__

因此,例如在实用程序库中,您将定义装饰器:

import sys

def export(fn):
    mod = sys.modules[fn.__module__]
    if hasattr(mod, '__all__'):
        mod.__all__.append(fn.__name__)
    else:
        mod.__all__ = [fn.__name__]
    return fn

然后,在定义的位置__all__执行以下操作:

$ cat > main.py
from lib import export
__all__ = [] # optional - we create a list if __all__ is not there.

@export
def foo(): pass

@export
def bar():
    'bar'

def main():
    print('main')

if __name__ == '__main__':
    main()

无论是作为主程序运行还是由其他函数导入,此方法都可以正常工作。

$ cat > run.py
import main
main.main()

$ python run.py
main

和API供应import *也将起作用:

$ cat > run.py
from main import *
foo()
bar()
main() # expected to error here, not exported

$ python run.py
Traceback (most recent call last):
  File "run.py", line 4, in <module>
    main() # expected to error here, not exported
NameError: name 'main' is not defined

Explain __all__ in Python?

I keep seeing the variable __all__ set in different __init__.py files.

What does this do?

What does __all__ do?

It declares the semantically “public” names from a module. If there is a name in __all__, users are expected to use it, and they can have the expectation that it will not change.

It also will have programmatic affects:

import *

__all__ in a module, e.g. module.py:

__all__ = ['foo', 'Bar']

means that when you import * from the module, only those names in the __all__ are imported:

from module import *               # imports foo and Bar

Documentation tools

Documentation and code autocompletion tools may (in fact, should) also inspect the __all__ to determine what names to show as available from a module.

__init__.py makes a directory a Python package

From the docs:

The __init__.py files are required to make Python treat the directories as containing packages; this is done to prevent directories with a common name, such as string, from unintentionally hiding valid modules that occur later on the module search path.

In the simplest case, __init__.py can just be an empty file, but it can also execute initialization code for the package or set the __all__ variable.

So the __init__.py can declare the __all__ for a package.

Managing an API:

A package is typically made up of modules that may import one another, but that are necessarily tied together with an __init__.py file. That file is what makes the directory an actual Python package. For example, say you have the following files in a package:

package
├── __init__.py
├── module_1.py
└── module_2.py

Let’s create these files with Python so you can follow along – you could paste the following into a Python 3 shell:

from pathlib import Path

package = Path('package')
package.mkdir()

(package / '__init__.py').write_text("""
from .module_1 import *
from .module_2 import *
""")

package_module_1 = package / 'module_1.py'
package_module_1.write_text("""
__all__ = ['foo']
imp_detail1 = imp_detail2 = imp_detail3 = None
def foo(): pass
""")

package_module_2 = package / 'module_2.py'
package_module_2.write_text("""
__all__ = ['Bar']
imp_detail1 = imp_detail2 = imp_detail3 = None
class Bar: pass
""")

And now you have presented a complete api that someone else can use when they import your package, like so:

import package
package.foo()
package.Bar()

And the package won’t have all the other implementation details you used when creating your modules cluttering up the package namespace.

__all__ in __init__.py

After more work, maybe you’ve decided that the modules are too big (like many thousands of lines?) and need to be split up. So you do the following:

package
├── __init__.py
├── module_1
│   ├── foo_implementation.py
│   └── __init__.py
└── module_2
    ├── Bar_implementation.py
    └── __init__.py

First make the subpackage directories with the same names as the modules:

subpackage_1 = package / 'module_1'
subpackage_1.mkdir()
subpackage_2 = package / 'module_2'
subpackage_2.mkdir()

Move the implementations:

package_module_1.rename(subpackage_1 / 'foo_implementation.py')
package_module_2.rename(subpackage_2 / 'Bar_implementation.py')

create __init__.pys for the subpackages that declare the __all__ for each:

(subpackage_1 / '__init__.py').write_text("""
from .foo_implementation import *
__all__ = ['foo']
""")
(subpackage_2 / '__init__.py').write_text("""
from .Bar_implementation import *
__all__ = ['Bar']
""")

And now you still have the api provisioned at the package level:

>>> import package
>>> package.foo()
>>> package.Bar()
<package.module_2.Bar_implementation.Bar object at 0x7f0c2349d210>

And you can easily add things to your API that you can manage at the subpackage level instead of the subpackage’s module level. If you want to add a new name to the API, you simply update the __init__.py, e.g. in module_2:

from .Bar_implementation import *
from .Baz_implementation import *
__all__ = ['Bar', 'Baz']

And if you’re not ready to publish Baz in the top level API, in your top level __init__.py you could have:

from .module_1 import *       # also constrained by __all__'s
from .module_2 import *       # in the __init__.py's
__all__ = ['foo', 'Bar']     # further constraining the names advertised

and if your users are aware of the availability of Baz, they can use it:

import package
package.Baz()

but if they don’t know about it, other tools (like pydoc) won’t inform them.

You can later change that when Baz is ready for prime time:

from .module_1 import *
from .module_2 import *
__all__ = ['foo', 'Bar', 'Baz']

Prefixing _ versus __all__:

By default, Python will export all names that do not start with an _. You certainly could rely on this mechanism. Some packages in the Python standard library, in fact, do rely on this, but to do so, they alias their imports, for example, in ctypes/__init__.py:

import os as _os, sys as _sys

Using the _ convention can be more elegant because it removes the redundancy of naming the names again. But it adds the redundancy for imports (if you have a lot of them) and it is easy to forget to do this consistently – and the last thing you want is to have to indefinitely support something you intended to only be an implementation detail, just because you forgot to prefix an _ when naming a function.

I personally write an __all__ early in my development lifecycle for modules so that others who might use my code know what they should use and not use.

Most packages in the standard library also use __all__.

When avoiding __all__ makes sense

It makes sense to stick to the _ prefix convention in lieu of __all__ when:

  • You’re still in early development mode and have no users, and are constantly tweaking your API.
  • Maybe you do have users, but you have unittests that cover the API, and you’re still actively adding to the API and tweaking in development.

An export decorator

The downside of using __all__ is that you have to write the names of functions and classes being exported twice – and the information is kept separate from the definitions. We could use a decorator to solve this problem.

I got the idea for such an export decorator from David Beazley’s talk on packaging. This implementation seems to work well in CPython’s traditional importer. If you have a special import hook or system, I do not guarantee it, but if you adopt it, it is fairly trivial to back out – you’ll just need to manually add the names back into the __all__

So in, for example, a utility library, you would define the decorator:

import sys

def export(fn):
    mod = sys.modules[fn.__module__]
    if hasattr(mod, '__all__'):
        mod.__all__.append(fn.__name__)
    else:
        mod.__all__ = [fn.__name__]
    return fn

and then, where you would define an __all__, you do this:

$ cat > main.py
from lib import export
__all__ = [] # optional - we create a list if __all__ is not there.

@export
def foo(): pass

@export
def bar():
    'bar'

def main():
    print('main')

if __name__ == '__main__':
    main()

And this works fine whether run as main or imported by another function.

$ cat > run.py
import main
main.main()

$ python run.py
main

And API provisioning with import * will work too:

$ cat > run.py
from main import *
foo()
bar()
main() # expected to error here, not exported

$ python run.py
Traceback (most recent call last):
  File "run.py", line 4, in <module>
    main() # expected to error here, not exported
NameError: name 'main' is not defined

回答 3

我只是添加这是为了精确:

所有其他答案均涉及模块__all____init__.py文件中明确提到了原始问题,所以这是关于python

通常,__all__仅在使用语句的from xxx import *变体时才起作用import。这适用于软件包以及模块。

模块的行为在其他答案中进行了说明。包的确切行为在此处详细描述。

简而言之,__all__在程序包级别,它与模块大致相同,只是它处理程序包中的模块 (与在模块中指定名称相反)。因此__all__指定当我们使用时应加载并导入到当前命名空间中的所有模块from package import *

最大的区别是,当你忽略的声明__all__在包的__init__.py,该声明from package import *将完全不进口任何东西(有exceptions的文档中解释,见上面的链接)。

另一方面,如果__all__在模块中省略,则“加星号的导入”将导入模块中定义的所有名称(不是以下划线开头)。

I’m just adding this to be precise:

All other answers refer to modules. The original question explicitely mentioned __all__ in __init__.py files, so this is about python packages.

Generally, __all__ only comes into play when the from xxx import * variant of the import statement is used. This applies to packages as well as to modules.

The behaviour for modules is explained in the other answers. The exact behaviour for packages is described here in detail.

In short, __all__ on package level does approximately the same thing as for modules, except it deals with modules within the package (in contrast to specifying names within the module). So __all__ specifies all modules that shall be loaded and imported into the current namespace when us use from package import *.

The big difference is, that when you omit the declaration of __all__ in a package’s __init__.py, the statement from package import * will not import anything at all (with exceptions explained in the documentation, see link above).

On the other hand, if you omit __all__ in a module, the “starred import” will import all names (not starting with an underscore) defined in the module.


回答 4

它还更改了pydoc将显示的内容:

module1.py

a = "A"
b = "B"
c = "C"

module2.py

__all__ = ['a', 'b']

a = "A"
b = "B"
c = "C"

$ pydoc module1

关于模块module1的帮助:

名称
    模块1

文件
    module1.py

数据
    a ='
     A'b ='
     B'c ='C'

$ pydoc module2

关于模块module2的帮助:

名称
    模块2

文件
    module2.py

数据
    __all__ = ['a','b']
     a ='
     A'b ='B'

__all__在所有模块中都声明了内容,并强调了内部细节,这些内容在使用实时解释器会话中从未使用过的功能时确实有用。

It also changes what pydoc will show:

module1.py

a = "A"
b = "B"
c = "C"

module2.py

__all__ = ['a', 'b']

a = "A"
b = "B"
c = "C"

$ pydoc module1

Help on module module1:

NAME
    module1

FILE
    module1.py

DATA
    a = 'A'
    b = 'B'
    c = 'C'

$ pydoc module2

Help on module module2:

NAME
    module2

FILE
    module2.py

DATA
    __all__ = ['a', 'b']
    a = 'A'
    b = 'B'

I declare __all__ in all my modules, as well as underscore internal details, these really help when using things you’ve never used before in live interpreter sessions.


回答 5

__all__定制*from <module> import *

__all__定制*from <package> import *


一个模块.py意味着要导入的文件。

是一个目录__init__.py文件。软件包通常包含模块。


模组

""" cheese.py - an example module """

__all__ = ['swiss', 'cheddar']

swiss = 4.99
cheddar = 3.99
gouda = 10.99

__all__让人们知道模块的“公共”功能。[ @AaronHall ] 另外,pydoc可以识别它们。[ @Longpoke ]

模块导入*

了解如何swisscheddar被带入当地的命名空间,而不是gouda

>>> from cheese import *
>>> swiss, cheddar
(4.99, 3.99)
>>> gouda
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'gouda' is not defined

没有__all__,任何符号(不以下划线开头)都将可用。


进口*不受影响__all__


导入模块

>>> import cheese
>>> cheese.swiss, cheese.cheddar, cheese.gouda
(4.99, 3.99, 10.99)

来自模块导入名称

>>> from cheese import swiss, cheddar, gouda
>>> swiss, cheddar, gouda
(4.99, 3.99, 10.99)

导入模块作为本地名称

>>> import cheese as ch
>>> ch.swiss, ch.cheddar, ch.gouda
(4.99, 3.99, 10.99)

包数

软件包__init__.py文件中是带有公共模块或其他对象名称的字符串列表。这些功能可用于通配符导入。与模块一样,自定义从软件包导入通配符的时间。[ @MartinStettner ] __all____all__*

这是Python MySQL Connector 的摘录__init__.py

__all__ = [
    'MySQLConnection', 'Connect', 'custom_error_exception',

    # Some useful constants
    'FieldType', 'FieldFlag', 'ClientFlag', 'CharacterSet', 'RefreshOption',
    'HAVE_CEXT',

    # Error handling
    'Error', 'Warning',

    ...etc...

    ]

缺省情况下,对于软件包不带星号的__all__情况很复杂,因为明显的行为是很昂贵的:使用文件系统搜索软件包中的所有模块。相反,在我阅读文档时,仅__init__.py导入中定义的对象:

如果__all__没有定义,语句from sound.effects import *不会导入从包中的所有子模块sound.effects到当前的命名空间; 它仅确保sound.effects已导入包(可能在中运行任何初始化代码__init__.py),然后导入包中定义的任何名称。这包括由定义的任何名称(以及明确加载的子模块)__init__.py。它还包括以前的import语句显式加载的包的所有子模块。


应避免使用通配符导入,因为它们会使读者和许多自动化工具感到困惑。

[ PEP 8,@ ToolmakerSteve]

__all__ customizes * in from <module> import *

__all__ customizes * in from <package> import *


A module is a .py file meant to be imported.

A package is a directory with a __init__.py file. A package usually contains modules.


MODULES

""" cheese.py - an example module """

__all__ = ['swiss', 'cheddar']

swiss = 4.99
cheddar = 3.99
gouda = 10.99

__all__ lets humans know the “public” features of a module.[@AaronHall] Also, pydoc recognizes them.[@Longpoke]

from module import *

See how swiss and cheddar are brought into the local namespace, but not gouda:

>>> from cheese import *
>>> swiss, cheddar
(4.99, 3.99)
>>> gouda
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'gouda' is not defined

Without __all__, any symbol (that doesn’t start with an underscore) would have been available.


Imports without * are not affected by __all__


import module

>>> import cheese
>>> cheese.swiss, cheese.cheddar, cheese.gouda
(4.99, 3.99, 10.99)

from module import names

>>> from cheese import swiss, cheddar, gouda
>>> swiss, cheddar, gouda
(4.99, 3.99, 10.99)

import module as localname

>>> import cheese as ch
>>> ch.swiss, ch.cheddar, ch.gouda
(4.99, 3.99, 10.99)

PACKAGES

In the __init__.py file of a package __all__ is a list of strings with the names of public modules or other objects. Those features are available to wildcard imports. As with modules, __all__ customizes the * when wildcard-importing from the package.[@MartinStettner]

Here’s an excerpt from the Python MySQL Connector __init__.py:

__all__ = [
    'MySQLConnection', 'Connect', 'custom_error_exception',

    # Some useful constants
    'FieldType', 'FieldFlag', 'ClientFlag', 'CharacterSet', 'RefreshOption',
    'HAVE_CEXT',

    # Error handling
    'Error', 'Warning',

    ...etc...

    ]

The default case, asterisk with no __all__ for a package, is complicated, because the obvious behavior would be expensive: to use the file system to search for all modules in the package. Instead, in my reading of the docs, only the objects defined in __init__.py are imported:

If __all__ is not defined, the statement from sound.effects import * does not import all submodules from the package sound.effects into the current namespace; it only ensures that the package sound.effects has been imported (possibly running any initialization code in __init__.py) and then imports whatever names are defined in the package. This includes any names defined (and submodules explicitly loaded) by __init__.py. It also includes any submodules of the package that were explicitly loaded by previous import statements.


Wildcard imports … should be avoided as they [confuse] readers and many automated tools.

[PEP 8, @ToolmakerSteve]


回答 6

摘自(非官方)Python参考维基

模块定义的公共名称是通过检查模块的命名空间中名为的变量来确定的__all__;如果已定义,则它必须是由该模块定义或导入的名称的字符串序列。给出的名称__all__均被视为公开名称,必须存在。如果__all__未定义,则公共名称集将包含在模块命名空间中找到的所有名称,这些名称不以下划线字符(“ _”)开头。__all__应该包含整个公共API。目的是避免意外导出不属于API的项目(例如在模块中导入和使用的库模块)。

From (An Unofficial) Python Reference Wiki:

The public names defined by a module are determined by checking the module’s namespace for a variable named __all__; if defined, it must be a sequence of strings which are names defined or imported by that module. The names given in __all__ are all considered public and are required to exist. If __all__ is not defined, the set of public names includes all names found in the module’s namespace which do not begin with an underscore character (“_”). __all__ should contain the entire public API. It is intended to avoid accidentally exporting items that are not part of the API (such as library modules which were imported and used within the module).


回答 7

__all__用于记录Python模块的公共API。尽管它是可选的,但__all__应使用。

这是Python语言参考中的相关摘录:

模块定义的公共名称是通过检查模块的命名空间中名为的变量来确定的__all__;如果已定义,则它必须是由该模块定义或导入的名称的字符串序列。给出的名称__all__均被视为公开名称,必须存在。如果__all__未定义,则公共名称集将包含在模块命名空间中找到的所有名称,这些名称不以下划线字符(_)开头。__all__应该包含整个公共API。目的是避免意外导出不属于API的项目(例如在模块中导入和使用的库模块)。

PEP 8使用类似的措辞,尽管它也清楚地表明,如果__all__缺少导入的名称,则它们不属于公共API :

为了更好地支持自省,模块应使用__all__属性在其公共API中显式声明名称。设置__all__为空列表表示该模块没有公共API。

[…]

导入的名称应始终被视为实现细节。其他模块不得依赖对此类导入名称的间接访问,除非它们是包含模块的API中明确记录的一部分,例如os.path__init__暴露了子模块功能的软件包模块。

此外,如其他答案所指出的,__all__用于启用软件包的通配符导入

import语句使用以下约定:如果程序包的__init__.py代码定义了名为的列表__all__,则将其视为from package import *遇到时应导入的模块名称的列表。

__all__ is used to document the public API of a Python module. Although it is optional, __all__ should be used.

Here is the relevant excerpt from the Python language reference:

The public names defined by a module are determined by checking the module’s namespace for a variable named __all__; if defined, it must be a sequence of strings which are names defined or imported by that module. The names given in __all__ are all considered public and are required to exist. If __all__ is not defined, the set of public names includes all names found in the module’s namespace which do not begin with an underscore character (‘_’). __all__ should contain the entire public API. It is intended to avoid accidentally exporting items that are not part of the API (such as library modules which were imported and used within the module).

PEP 8 uses similar wording, although it also makes it clear that imported names are not part of the public API when __all__ is absent:

To better support introspection, modules should explicitly declare the names in their public API using the __all__ attribute. Setting __all__ to an empty list indicates that the module has no public API.

[…]

Imported names should always be considered an implementation detail. Other modules must not rely on indirect access to such imported names unless they are an explicitly documented part of the containing module’s API, such as os.path or a package’s __init__ module that exposes functionality from submodules.

Furthermore, as pointed out in other answers, __all__ is used to enable wildcard importing for packages:

The import statement uses the following convention: if a package’s __init__.py code defines a list named __all__, it is taken to be the list of module names that should be imported when from package import * is encountered.


回答 8

简短答案

__all__影响from <module> import *陈述。

长答案

考虑以下示例:

foo
├── bar.py
└── __init__.py

foo/__init__.py

  • (隐式)如果不定义__all__from foo import *则将仅导入在中定义的名称foo/__init__.py

  • (明确)如果定义__all__ = [],则from foo import *不会导入任何内容。

  • (显式)如果定义__all__ = [ <name1>, ... ]from foo import *则将仅导入这些名称。

请注意,在隐式情况下,python不会导入以开头的名称_。但是,您可以使用以下命令强制导入此类名称__all__

您可以在此处查看Python文档。

Short answer

__all__ affects from <module> import * statements.

Long answer

Consider this example:

foo
├── bar.py
└── __init__.py

In foo/__init__.py:

  • (Implicit) If we don’t define __all__, then from foo import * will only import names defined in foo/__init__.py.

  • (Explicit) If we define __all__ = [], then from foo import * will import nothing.

  • (Explicit) If we define __all__ = [ <name1>, ... ], then from foo import * will only import those names.

Note that in the implicit case, python won’t import names starting with _. However, you can force importing such names using __all__.

You can view the Python document here.


回答 9

__all__影响from foo import *工作方式。

在模块主体内(但不在函数或类主体内)的代码可以*from语句中使用星号():

from foo import *

*所有属性模块的要求foo(除了那些下划线开头)绑定为导入模块中的全局变量。当foo具有属性时__all__,属性的值是受此类型的绑定的名称的列表from语句。

If foo是一个,它__init__.py定义了一个名为__all__,则将其视为from foo import *遇到时应导入的子模块名称的列表。如果__all__未定义,则该语句将from foo import *导入包中定义的任何名称。这包括由定义的任何名称(以及明确加载的子模块)__init__.py

请注意,__all__不必一定是列表。根据import声明中的文档,如果已定义,则__all__必须是字符串序列是模块定义或导入的名称。因此,您也可以使用元组来节省一些内存和CPU周期。只是不要忘记逗号,以防模块定义了单个公共名称:

__all__ = ('some_name',)

另请参阅“ import *”为什么不好?

__all__ affects how from foo import * works.

Code that is inside a module body (but not in the body of a function or class) may use an asterisk (*) in a from statement:

from foo import *

The * requests that all attributes of module foo (except those beginning with underscores) be bound as global variables in the importing module. When foo has an attribute __all__, the attribute’s value is the list of the names that are bound by this type of from statement.

If foo is a package and its __init__.py defines a list named __all__, it is taken to be the list of submodule names that should be imported when from foo import * is encountered. If __all__ is not defined, the statement from foo import * imports whatever names are defined in the package. This includes any names defined (and submodules explicitly loaded) by __init__.py.

Note that __all__ doesn’t have to be a list. As per the documentation on the import statement, if defined, __all__ must be a sequence of strings which are names defined or imported by the module. So you may as well use a tuple to save some memory and CPU cycles. Just don’t forget a comma in case the module defines a single public name:

__all__ = ('some_name',)

See also Why is “import *” bad?


回答 10

这在PEP8定义在这里

全局变量名

(我们希望这些变量只能在一个模块内使用。)约定与函数的约定大致相同。

设计用于via的模块from M import *应使用__all__防止导出全局变量的机制,或使用在下划线之前为此类全局变量加上前缀的较早的约定(您可能需要这样做以指示这些全局变量是“模块非公共的”)。

PEP8为包含主要Python发行版中的标准库的Python代码提供了编码约定。您遵循的越多,您就越接近原始意图。

This is defined in PEP8 here:

Global Variable Names

(Let’s hope that these variables are meant for use inside one module only.) The conventions are about the same as those for functions.

Modules that are designed for use via from M import * should use the __all__ mechanism to prevent exporting globals, or use the older convention of prefixing such globals with an underscore (which you might want to do to indicate these globals are “module non-public”).

PEP8 provides coding conventions for the Python code comprising the standard library in the main Python distribution. The more you follow this, closer you are to the original intent.