可能重复:
Python中的"最小惊讶":可变默认参数
我今天下午写了一些代码,偶然发现了代码中的一个错误.我注意到我的一个新创建的对象的默认值是从另一个对象转移的!例如:
class One(object):
def __init__(self, my_list=[]):
self.my_list = my_list
one1 = One()
print(one1.my_list)
[] # empty list, what you'd expect.
one1.my_list.append('hi')
print(one1.my_list)
['hi'] # list with the new value in it, what you'd expect.
one2 = One()
print(one2.my_list)
['hi'] # Hey! It saved the variable from the other One!
Run Code Online (Sandbox Code Playgroud)
所以我知道这可以通过这样解决:
class One(object):
def __init__(self, my_list=None):
self.my_list = my_list if my_list is not None else []
Run Code Online (Sandbox Code Playgroud)
我想知道的是......为什么?为什么Python类是结构化的,以便在类的实例中保存默认值?
提前致谢!
如果未将明确值传递给方法,我想用一些默认值初始化方法的参数 - 如下所示:
class Example
def __init__(self, data = self.default_data()):
self.data = data
def default_data():
# ....
return something
Run Code Online (Sandbox Code Playgroud)
我收到了错误:
NameError: name 'self' is not defined
Run Code Online (Sandbox Code Playgroud)
我该如何解决?
设置JSONField为具有新列表的默认值的最佳方法是什么django?
有一个模型,其中一个字段是项目列表.在没有设置项目的情况下,模型应该有一个空列表.
from django.models import Model
class MyModel(Model):
the_list_field = JSONField(default=[])
Run Code Online (Sandbox Code Playgroud)
这是最好的方法吗?它应该转换为使用list吗?
谢谢!
在查看Think Complexity中的一些代码时,我注意到他们的Graph类为自己分配值.我已经从该类中复制了一些重要的行,并编写了一个示例类,ObjectChild但这种行为失败了.
class Graph(dict):
def __init__(self, vs=[], es=[]):
for v in vs:
self.add_vertex(v)
for e in es:
self.add_edge(e)
def add_edge(self, e):
v, w = e
self[v][w] = e
self[w][v] = e
def add_vertex(self, v):
self[v] = {}
class ObjectChild(object):
def __init__(self, name):
self['name'] = name
Run Code Online (Sandbox Code Playgroud)
我确定不同的内置类型都有自己的使用方式,但我不确定这是否应该尝试构建到我的类中.有可能,怎么样?这是我不应该打扰的东西,而是依靠简单的构图,例如self.l = [1, 2, 3]?在内置类型之外应该避免吗?
我问,因为我被告知"你几乎不应该继承内置的python集合"; 建议我犹豫是否要限制自己.
为了澄清,我知道它ObjectChild不会"起作用",我可以很容易地使它 "工作",但我很好奇这些内置类型的内部工作方式使它们的界面与一个孩子不同object.
这似乎喜欢的事,很可能已被问过,但搜索的一个小时左右的时间没有结果。将默认列表参数传递给数据类看起来很有希望,但这并不是我想要的。
这是问题所在:当尝试将可变值分配给class属性时,会出现错误:
@dataclass
class Foo:
bar: list = []
# ValueError: mutable default <class 'list'> for field a is not allowed: use default_factory
Run Code Online (Sandbox Code Playgroud)
我从错误消息中收集了应该使用以下内容的信息:
@dataclass
class Foo:
bar: list = field(default_factory=list)
Run Code Online (Sandbox Code Playgroud)
但是为什么不允许可变的默认值?是否要强制避免可变的默认参数问题?
我想编写一个Python函数来改变其中一个参数(这是一个列表,即可变).像这样的东西:
def change(array):
array.append(4)
change(array)
Run Code Online (Sandbox Code Playgroud)
我更熟悉传递值而不是Python的设置(无论你决定调用它).所以我通常会写这样的函数:
def change(array):
array.append(4)
return array
array = change(array)
Run Code Online (Sandbox Code Playgroud)
这是我的困惑.由于我可以改变参数,第二种方法似乎是多余的.但第一个感觉不对.此外,我的特定功能将有几个参数,其中只有一个会改变.第二种方法清楚地说明了哪个参数正在改变(因为它被赋值给变量).第一种方法没有给出任何指示.有会议吗?哪个更好'?谢谢.
非常快速简单的家庭作业问题.我运行正常,但我认为有更好的
方法.一种更加Pythonic的方式.
这是我的代码递归递减列表的每个元素1.
l = range(30)
def recurseDecrMap(l, x = []):
if len(l) == 0:
return []
else:
x.append(l[0] -1)
recurseDecrMap(l[1:], x)
return x
Run Code Online (Sandbox Code Playgroud)
所以感谢任何输入.我正在努力学习做更好的递归.无法
掌握它的诀窍.
可能重复:
python中最不惊讶:可变的默认参数
我想了解python __init__构造函数的行为和含义.看起来当有一个可选参数并且您尝试将现有对象设置为新对象时,将保留并复制现有对象的可选值.
看一个例子:
在下面的代码中,我试图创建一个带有节点和可能有很多子节点的树结构.在第一个类中NodeBad,构造函数有两个参数,值和任何可能的子节点.第二类NodeGood仅将节点的值作为参数.两者都有一个addchild将子节点添加到节点的方法.
使用NodeGood类创建树时,它按预期工作.但是,当与NodeBad班级做同样的事情时,似乎只能添加一次孩子!
下面的代码将产生以下输出:
Good Tree
1
2
3
[< 3 >]
Bad Tree
1
2
2
[< 2 >, < 3 >]
Run Code Online (Sandbox Code Playgroud)
Que Pasa?
这是一个例子:
#!/usr/bin/python
class NodeBad:
def __init__(self, value, c=[]):
self.value = value
self.children = c
def addchild(self, node):
self.children.append(node)
def __str__(self):
return '< %s >' % self.value
def __repr__(self):
return '< %s >' % self.value
class NodeGood:
def __init__(self, value):
self.value …Run Code Online (Sandbox Code Playgroud) 假设我在python中有这两段代码:
1 --------------------------
import numpy as np
x = np.array([1,2,3,4])
y = x
x = x + np.array([1,1,1,1])
print y
2 --------------------------
import numpy as np
x = np.array([1,2,3,4])
y = x
x += np.array([1,1,1,1])
print y
Run Code Online (Sandbox Code Playgroud)
我认为y两个例子中的结果都是相同的,因为y指出x并x成为(2,3,4,5),但事实并非如此
结果是(1,2,3,4) for 1和(2,3,4,5) for 2.
经过一些研究,我发现在第一个例子中
#-First example---------------------------------------
x = np.array([1,2,3,4]) # create x --> [1,2,3,4]
y = x # made y point to x …Run Code Online (Sandbox Code Playgroud) 我想通过命令行使用这种参数调用python脚本(列表可以是任何大小,例如3):
python test.py --option1 ["o11", "o12", "o13"] --option2 ["o21", "o22", "o23"]
Run Code Online (Sandbox Code Playgroud)
使用点击.从文档中,我们无法在任何地方声明我们可以使用列表作为@ click.option的参数
当我尝试这样做时:
#!/usr/bin/env python
import click
@click.command(context_settings=dict(help_option_names=['-h', '--help']))
@click.option('--option', default=[])
def do_stuff(option):
return
# do stuff
if __name__ == '__main__':
do_stuff()
Run Code Online (Sandbox Code Playgroud)
在我的test.py,通过从命令行调用它:
python test.py --option ["some option", "some option 2"]
Run Code Online (Sandbox Code Playgroud)
我收到一个错误:
错误:得到意外的额外参数(某些选项2))
我不能真正使用可变参数,因为每个命令只允许1个可变参数(http://click.pocoo.org/5/arguments/#variadic-arguments)
因此,如果有人能指出我正确的方向(最好使用点击),我将非常感激.
python ×10
command-line ×1
constructor ×1
django ×1
in-place ×1
inheritance ×1
mutable ×1
parameters ×1
performance ×1
python-3.x ×1
python-click ×1
recursion ×1
reference ×1