如何使用实例的属性作为方法的默认参数?
我想使用实例的属性值将默认参数传递给实例方法:
class C:
def __init__(self, format):
self.format = format
def process(self, formatting=self.format):
print(formatting)
尝试这样做时,我收到以下错误消息:
NameError: name 'self' is not defined
我希望该方法的行为如下:
C("abc").process() # prints "abc"
C("abc").process("xyz") # prints "xyz"
这里有什么问题,为什么会这样不工作?我怎样才能做到这一点?
I want to pass a default argument to an instance method using the value of an attribute of the instance:
class C:
def __init__(self, format):
self.format = format
def process(self, formatting=self.format):
print(formatting)
When trying that, I get the following error message:
NameError: name 'self' is not defined
I want the method to behave like this:
C("abc").process() # prints "abc"
C("abc").process("xyz") # prints "xyz"
What is the problem here, why does this not work? And how could I make this work?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
您不能真正将其定义为默认值,因为在定义方法时(在任何实例存在之前)都会评估默认值。通常的模式是执行类似以下操作:
仅当
formatting
为None
时才会使用self.format
。要演示默认值如何工作的要点,请参见以下示例:
以及此处的输出:
请注意
mk_default
是如何仅被调用一次的,而且是在调用该函数之前发生的!You can't really define this as the default value, since the default value is evaluated when the method is defined which is before any instances exist. The usual pattern is to do something like this instead:
self.format
will only be used ifformatting
isNone
.To demonstrate the point of how default values work, see this example:
And the output here:
Notice how
mk_default
was called only once, and that happened before the function was ever called!在 Python 中,名称
self
并不特殊。这只是参数名称的约定,这就是为什么__init__
中有一个self
参数。 (实际上,__init__
也不是很特别,特别是它没有实际创建对象......这是一个更长的故事)C("abc" ).process()
创建一个C
实例,在C
类中查找process
方法,并使用以下命令调用该方法C
实例作为第一个参数。因此,如果您提供了它,它最终会出现在self
参数中。即使您有该参数,您也不会被允许编写类似
def process(self,formatting = self.formatting)
的内容,因为self
不在范围内但在您设置默认值的地方。在Python中,参数的默认值是在编译函数时计算的,并“粘在”函数中。 (这就是为什么如果您使用像[]
这样的默认值,该列表将记住函数调用之间的更改的原因。)传统方法是使用
None
作为默认值,检查该值并在函数内替换它。您可能会发现为此目的创建一个特殊值会更安全一些(您只需要一个object
实例,只要隐藏它以便调用代码不使用相同的实例)而不是无
。无论哪种方式,您都应该使用is
检查该值,而不是==
。In Python, the name
self
is not special. It's just a convention for the parameter name, which is why there is aself
parameter in__init__
. (Actually,__init__
is not very special either, and in particular it does not actually create the object... that's a longer story)C("abc").process()
creates aC
instance, looks up theprocess
method in theC
class, and calls that method with theC
instance as the first parameter. So it will end up in theself
parameter if you provided it.Even if you had that parameter, though, you would not be allowed to write something like
def process(self, formatting = self.formatting)
, becauseself
is not in scope yet at the point where you set the default value. In Python, the default value for a parameter is calculated when the function is compiled, and "stuck" to the function. (This is the same reason why, if you use a default like[]
, that list will remember changes between calls to the function.)The traditional way is to use
None
as a default, and check for that value and replace it inside the function. You may find it is a little safer to make a special value for the purpose (anobject
instance is all you need, as long as you hide it so that the calling code does not use the same instance) instead ofNone
. Either way, you should check for this value withis
, not==
.由于您想使用 self.format 作为默认参数,这意味着该方法需要是特定于实例的(即无法在类级别定义它)。相反,您可以在类的
__init__
期间定义特定方法。您可以在此处访问实例特定属性。一种方法是使用
functools.partial
以获得方法的更新(特定)版本:请注意,使用这种方法,您只能通过关键字传递相应的参数,因为如果您按位置提供它,这会在
partial< 中产生冲突/代码>。
另一种方法是在 __init__ 中定义和设置方法:
这也允许按位置传递参数,但是方法解析顺序变得不太明显(例如,这可能会影响 IDE 检查,但我认为有是 IDE 特定的解决方法)。
另一种方法是为这些“实例属性默认值”创建一个自定义类型,并使用一个特殊的装饰器来执行相应的 getattr 参数填充:
Since you want to use
self.format
as a default argument this implies that the method needs to be instance specific (i.e. there is no way to define this at class level). Instead you can define the specific method during the class'__init__
for example. This is where you have access to instance specific attributes.One approach is to use
functools.partial
in order to obtain an updated (specific) version of the method:Note that with this approach you can only pass the corresponding argument by keyword, since if you provided it by position, this would create a conflict in
partial
.Another approach is to define and set the method in
__init__
:This allows also passing the argument by position, however the method resolution order becomes less apparent (which can affect the IDE inspection for example, but I suppose there are IDE specific workarounds for that).
Another approach would be to create a custom type for these kind of "instance attribute defaults" together with a special decorator that performs the corresponding
getattr
argument filling:您无法在方法定义中访问 self 。我的解决方法是这样的 -
You can't access self in the method definition. My workaround is this -
如果您希望它们充当非静态方法,则需要将“self”作为第一个参数传递给任何类函数。
它指的是对象本身。您无法将“self”作为默认参数传递,因为它的位置已固定为第一个参数。
在您的情况下,不要使用“formatting=self.format”,而是使用“formatting=None”,然后从代码中分配值,如下所示:
[编辑]
注意:不要使用“format”作为变量名,因为它是内置函数在Python中
"self" need to be pass as the first argument to any class functions if you want them to behave as non-static methods.
it refers to the object itself. You could not pass "self" as default argument as it's position is fix as first argument.
In your case instead of "formatting=self.format" use "formatting=None" and then assign value from code as below:
[EDIT]
Note : do not use "format" as variable name, 'cause it is built-in function in python
您可以使用“默认”字典并使用 eval() 创建类的新实例,而不是创建涵盖默认争论的 if-then 列表:
我将其放在实例化另一个类的每个类的开头类作为默认参数。它避免了 python 在编译时评估默认值...我想要一种更干净的 pythonic 方法,但是 lo'。
Instead of creating a list of if-thens that span your default arguements, one can make use of a 'defaults' dictionary and create new instances of a class by using eval():
I throw this at the beginning of every class that instantiates another class as a default argument. It avoids python evaluating the default at compile... I would love a cleaner pythonic approach, but lo'.