Python 可选参数

发布于 2024-08-08 07:40:36 字数 545 浏览 6 评论 0原文

伙计们,我最近刚开始使用 python,对可选参数感到困惑,假设我有这样的程序:

class B:
   pass

class A:
    def __init__(self, builds = B()):
        self.builds = builds

如果我创建 A 两次

b = A()
c = A()

并打印他们的构建,

print b.builds
print c.builds

我发现他们使用完全相同的对象,

<__main__.B instance at 0x68ee0>
<__main__.B instance at 0x68ee0>

但这不是我想要的,因为如果 b 更改了构建的某些内部状态,则 c 对象中的状态也会发生更改。

是否可以使用此可选参数语法每次重新创建此可选参数?

Guys, I just started python recently and get confused with the optional parameters, say I have the program like this:

class B:
   pass

class A:
    def __init__(self, builds = B()):
        self.builds = builds

If I create A twice

b = A()
c = A()

and print their builds

print b.builds
print c.builds

I found they are using the exactly same object,

<__main__.B instance at 0x68ee0>
<__main__.B instance at 0x68ee0>

But it is not what I want, since if b changed some internal state of builds, the one in c object will also be changed.

Is it possible to recreate this optional parameters each time by using this optional parameters syntax?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

无语# 2024-08-15 07:40:36

您需要了解默认值如何工作才能有效地使用它们。

函数是对象。因此,它们具有属性。所以,如果我创建这个函数:

>>> def f(x, y=[]):
        y.append(x)
        return y

我已经创建了一个对象。以下是它的属性:

>>> dir(f)
['__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__',   
'__dict__', '__doc__', '__format__', '__get__', '__getattribute__', '__globals__',    
'__hash__', '__init__', '__module__', '__name__', '__new__', '__reduce__', 
'__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 
'func_closure', 'func_code', 'func_defaults', 'func_dict', 'func_doc', 'func_globals', 
'func_name']

其中之一是 func_defaults。听起来很有希望,里面有什么?

>>> f.func_defaults
([],)

这是一个包含函数默认值的元组。如果默认值是一个对象,则该元组包含该对象的实例。

如果您认为 f 将一个项目添加到列表中,如果未提供列表,则返回仅包含该项目的列表,这会导致一些相当违反直觉的行为:

>>> f(1)
[1]
>>> f(2)
[1, 2]

但如果您知道默认值是存储在函数属性之一的对象实例,它就不那么违反直觉了:

>>> x = f(3)
>>> y = f(4)
>>> x == y
True
>>> x
[1, 2, 3, 4]
>>> x.append(5)
>>> f(6)
[1, 2, 3, 4, 5, 6]

知道这一点,很明显,如果您希望函数参数的默认值是一个新列表(或任何新对象),您不能简单地在 func_defaults 中存储该对象的实例。每次调用该函数时,您都必须创建一个新函数:

>>>def g(x, y=None):
       if y==None:
           y = []
       y.append(x)
       return y

You need to understand how default values work in order to use them effectively.

Functions are objects. As such, they have attributes. So, if I create this function:

>>> def f(x, y=[]):
        y.append(x)
        return y

I've created an object. Here are its attributes:

>>> dir(f)
['__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__',   
'__dict__', '__doc__', '__format__', '__get__', '__getattribute__', '__globals__',    
'__hash__', '__init__', '__module__', '__name__', '__new__', '__reduce__', 
'__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 
'func_closure', 'func_code', 'func_defaults', 'func_dict', 'func_doc', 'func_globals', 
'func_name']

One of them is func_defaults. That sounds promising, what's in there?

>>> f.func_defaults
([],)

That's a tuple that contains the function's default values. If a default value is an object, the tuple contains an instance of that object.

This leads to some fairly counterintuitive behavior if you're thinking that f adds an item to a list, returning a list containing only that item if no list is provided:

>>> f(1)
[1]
>>> f(2)
[1, 2]

But if you know that the default value is an object instance that's stored in one of the function's attributes, it's much less counterintuitive:

>>> x = f(3)
>>> y = f(4)
>>> x == y
True
>>> x
[1, 2, 3, 4]
>>> x.append(5)
>>> f(6)
[1, 2, 3, 4, 5, 6]

Knowing this, it's clear that if you want a default value of a function's parameter to be a new list (or any new object), you can't simply stash an instance of the object in func_defaults. You have to create a new one every time the function is called:

>>>def g(x, y=None):
       if y==None:
           y = []
       y.append(x)
       return y
能怎样 2024-08-15 07:40:36

您需要执行以下操作:

class A:
    def __init__(self, builds=None):
        if builds is None:
            builds = B()
        self.builds = builds

这是一个非常广泛的错误,使用可变参数作为默认参数。 SO上可能有很多骗子。

you need to do the following:

class A:
    def __init__(self, builds=None):
        if builds is None:
            builds = B()
        self.builds = builds

it's a very wide-spread error, using mutable parameters as a default arguments. there are plenty of dupes probably on SO.

陪我终i 2024-08-15 07:40:36

是的;默认参数仅在定义函数时计算。

一种可能的解决方案是让参数是一个而不是一个实例,a la

def foo(blah, klass = B):
    b = klass()
    # etc

Yes; default parameters are evaluated only at the time when the function is defined.

One possible solution would be to have the parameter be a class rather than an instance, a la

def foo(blah, klass = B):
    b = klass()
    # etc
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文