Python 使用当前类实例的属性作为方法';s参数

Python 使用当前类实例的属性作为方法';s参数,python,function,default,default-parameters,Python,Function,Default,Default Parameters,可能重复: 虽然可以在python中为函数参数设置默认值: def my_function(param_one='default') ... 似乎无法访问当前实例(self): 我的问题: 我不能访问当前实例来设置函数中的默认参数,这是真的吗 如果不可能:原因是什么?在python的未来版本中,这是可以想象的吗 它写为: def my_function(self, param_one=None): # Or custom sentinel if None is vaild

可能重复:

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

def my_function(param_one='default')
    ...
似乎无法访问当前实例(self):

我的问题:

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

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
我认为可以肯定地说,这在Python中永远不会发生,因为函数启动之前,
self
实际上并不存在。。。(在它自己的定义中,你不能引用它——就像其他任何东西一样)


例如:您不能执行
d={'x':3,'y':d['x']*5}

参数的默认值在“编译”时计算一次。因此,显然您无法访问
self
。经典示例是将
列表
作为默认参数。如果向其中添加元素,参数的默认值将更改


解决方法是使用另一个默认参数,通常是
None
,然后检查并更新变量。

它比您想象的要多得多。默认值是静态的(=常数引用指向一个对象),并存储在定义中的某个地方;在方法定义时进行评估;作为类的一部分,而不是实例。因为它们是常量,所以它们不能依赖于
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
这将打印
1 2 1 3

因为它的工作原理和

default_s=[]
def add(item, s=default_s):
    s.append(item)
显然,如果您修改
默认值
,它将保留这些修改

有多种变通方法,包括

def add(item, s=None):
    if not s: s = []
    s.append(item)
或者你可以这样做:

def add(self, item, s=None):
    if not s: s = self.makeDefaultS()
    s.append(item)
然后方法
makeDefaultS
将访问
self

另一个变化:

import types
def add(item, s=lambda self:[]):
    if isinstance(s, types.FunctionType): s = s("example")
    s.append(item)
此处,
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 []

这里有很多错误的假设——首先,函数属于一个类而不是一个实例,这意味着涉及的实际函数对于一个类的任意两个实例都是相同的。第二,默认参数在编译时进行计算,并且是常量(如中所示,常量对象引用-如果参数是可变对象,则可以对其进行更改)。因此,您无法在默认参数中访问
self
,也永远无法访问。

但使用list作为默认参数值可能会导致
最不令人惊讶的事情。
。我不确定您想说什么。。。它遵循规则,但如果你不知道规则,这当然是一个很大的惊喜这有点不同,阿什维尼。那篇文章是关于实例方法的,这是关于实例属性的。这两个问题的原因是相同的,是的,但问题肯定不同。@Maxwell,但有点相同,因为他试图在默认参数值中使用
self.someattribute
。@Ashwini当然,但这不是投票以重复方式关闭的原因,因为要求是完全相同的内容,并且这个问题的答案可以和其他问题的答案合并在一起。“可能被合并”的表述隐含的意思是,这些合并的问题不应该像拇指酸痛一样突出,因为它们没有回答问题。@lazyr它没有投票,是其他人做的。我刚刚添加了注释。重要的一点是默认参数是在定义时设置的,但是
self
直到运行时才存在。我不知道我会在这里使用术语常量,因为您可以改变对象。但是指出在定义函数时,默认值与关键字关联是有帮助的。谢谢,是的,我是说静态的。@mgilson它是一个常量对象引用;如果对象是可变的,则可以对其进行变异,但不能更改引用。虽然常量一词可能会让人困惑,但如果您将其视为一个引用,它是合适的。我还添加了一些解决方案来获得所需的行为:工厂函数,或将默认值初始化委托给一个单独的方法。@l4mpi--您完全正确地认为它是一个常量引用,但我认为这个词对可能会问这样一个问题的人来说仍然很困惑。这是一个很好的答案。我认为编写一个函数会更有指导意义:
def my_func(a,foo=a.bar):…
并说明该函数如何工作,因为
a
是函数的一个参数,但定义函数时会关联
foo
的默认值。很高兴看到
self
实际上没有什么特别之处。它只是函数调用中的一个参数,就像其他任何东西一样——(它只是一个在执行
instance.method()
时隐式传递的参数)。为了完整起见:如果您的
变量中的一个碰巧是同一类中定义的常量属性,然后,您可以通过
def my_函数(self,param_one=u常数中的一个)在方法中引用它。它会起作用的。
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 []