Python中函数参数的默认值

paw*_*que 56 python function defaults default-parameters

可能重复:
作为实例方法的结果的参数的默认值

虽然可以在python中将默认值设置为函数参数:

def my_function(param_one='default')
    ...
Run Code Online (Sandbox Code Playgroud)

似乎无法访问当前实例(self):

class MyClass(..):

    def my_function(self, param_one=self.one_of_the_vars):
        ...
Run Code Online (Sandbox Code Playgroud)

我的问题:

  • 这是真的,我无法访问当前实例来设置函数中的默认参数吗?
  • 如果它不可能:原因是什么,可以想象在未来的python版本中这是可能的?

Jon*_*nts 57

它被写成:

def my_function(self, param_one=None): # Or custom sentinel if None is vaild
    if param_one is None:
        param_one = self.one_of_the_vars
Run Code Online (Sandbox Code Playgroud)

而且我认为可以说在Python中永远不会发生由于self在函数启动之前不存在的本质...(你不能在它自己的定义中引用它 - 就像其他一切一样)

例如:你做不到 d = {'x': 3, 'y': d['x'] * 5}

  • 这是一个很好的答案。我认为编写一个函数将更有启发性:`def my_func(a,foo = a.bar):...`并说明该函数不起作用,因为`a`是该函数的参数,但是foo的默认值是在定义函数时关联的。很高兴看到self并没有什么特别的。与其他所有函数一样,它只是函数调用中的一个参数((恰好是在执行“ instance.method()”时隐式传递的参数))。 (2认同)

Ano*_*sse 22

它比你想象的要多得多.将默认值视为静态(=指向一个对象的常量引用)并存储在定义中的某个位置; 在方法定义时评估; 作为课程的一部分,而不是实例.因为它们是不变的,所以它们不能依赖self.

这是一个例子.这是违反直觉的,但实际上是完全合理的:

def add(item, s=[]):
    s.append(item)
    print len(s)

add(1)     # 1
add(1)     # 2
add(1, []) # 1
add(1, []) # 1
add(1)     # 3
Run Code Online (Sandbox Code Playgroud)

这将打印1 2 1 1 3.

因为它的工作原理与之相同

default_s=[]
def add(item, s=default_s):
    s.append(item)
Run Code Online (Sandbox Code Playgroud)

显然,如果你修改default_s,它会保留这些修改.

有各种解决方法,包括

def add(item, s=None):
    if not s: s = []
    s.append(item)
Run Code Online (Sandbox Code Playgroud)

或者你可以这样做:

def add(self, item, s=None):
    if not s: s = self.makeDefaultS()
    s.append(item)
Run Code Online (Sandbox Code Playgroud)

然后该方法makeDefaultS将有权访问self.

另一种变化:

import types
def add(item, s=lambda self:[]):
    if isinstance(s, types.FunctionType): s = s("example")
    s.append(item)
Run Code Online (Sandbox Code Playgroud)

这里的默认值s工厂函数.

您可以结合所有这些技术:

class Foo:
    import types
    def add(self, item, s=Foo.defaultFactory):
        if isinstance(s, types.FunctionType): s = s(self)
        s.append(item)

    def defaultFactory(self):
        """ Can be overridden in a subclass, too!"""
        return []
Run Code Online (Sandbox Code Playgroud)