Python 对象属性的可变类型默认值的迭代赋值
我的目标是为几个对象属性设置可变类型(列表)的默认值。根据讨论,我在Python 对象属性的可变类型默认值的迭代赋值,python,python-3.x,Python,Python 3.x,我的目标是为几个对象属性设置可变类型(列表)的默认值。根据讨论,我在\uuu init\uuu的参数中将这些属性的默认值设置为None,然后在\uu init\uu中为它们指定值[],如果它们采用默认值。这是一个代表: class Wat(object): def __init__(self, arg1=None, arg2=None, arg3=None): for arg in arg1, arg2, arg3: if arg == None:
\uuu init\uuu
的参数中将这些属性的默认值设置为None
,然后在\uu init\uu
中为它们指定值[]
,如果它们采用默认值。这是一个代表:
class Wat(object):
def __init__(self, arg1=None, arg2=None, arg3=None):
for arg in arg1, arg2, arg3:
if arg == None:
arg = []
self.arg1 = arg1
self.arg2 = arg2
self.arg3 = arg3
def give(self, thing):
self.arg1.append(thing)
self.arg2.append(thing)
self.arg3.append(thing)
wat = Wat()
wat.give(5)
但是,这会引发以下异常:
AttributeError:'NoneType'对象没有属性“append”
我看不出wat.arg1
、wat.arg2
和wat.arg3
在调用wat.give(5)
时如何仍然具有类型None
——它们应该被重新分配到\uu init\uuuu
中的[/code>。这一定与我对作业的编码方式有关,因为这是有效的:
class Wat(object):
def __init__(self, arg1=None, arg2=None, arg3=None):
if arg1 == None:
arg1 = []
if arg2 == None:
arg2 = []
if arg3 == None:
arg3 = []
self.arg1 = arg1
self.arg2 = arg2
self.arg3 = arg3
def give(self, thing):
self.arg1.append(thing)
self.arg2.append(thing)
self.arg3.append(thing)
wat = Wat()
wat.give(5)
在我看来,这两种语法在功能上是等价的,但你可以想象,随着以这种方式分配的参数数量的增加,后一种语法变得非常乏味,并且在美学上令人不快
前一种语法有什么问题?我怎样才能修好它?谢谢
编辑:你们中的一些人已经发现了这个问题,但我仍然没有一个令人满意的解决方案@roippi提出了一种一次分配一个变量的有效方法,但假设我有100个变量。如何以最少的代码行完成此任务?这就是循环的最初目的。谢谢各位。这是因为您将空列表分配给循环变量,循环变量在每次迭代时都会发生变化,即arg
与arg1
不是同一个变量,但它们在迭代开始时共享相同的引用。这是因为您将空列表分配给循环变量,在每次迭代中发生变化的变量,即arg
与arg1
不是同一变量,但它们在迭代开始时共享相同的引用
for arg in arg1, arg2, arg3:
if arg == None:
arg = []
在这个循环中,您正在创建对由arg1
、arg2
、arg3
指向的对象的新引用,并在对照None
检查它们的值后,将这些变量(arg
)分配给新对象,因此旧对象仍然保持不变。因此,它大致相当于:
>>> lis = [1, 2, 3]
>>> x = lis[0] #now `x` points to lis[0]
>>> x = [] #now `x` points to a different object, this won't affect lis[0]
>>> lis
[1, 2, 3]
>>> x = lis[1]
>>> x = []
>>> lis
[1, 2, 3]
...
请注意,最好使用arg is None
而不是arg==None
在这个循环中,您正在创建对由arg1
、arg2
、arg3
指向的对象的新引用,并在对照None
检查它们的值后,将这些变量(arg
)分配给新对象,因此旧对象仍然保持不变。因此,它大致相当于:
>>> lis = [1, 2, 3]
>>> x = lis[0] #now `x` points to lis[0]
>>> x = [] #now `x` points to a different object, this won't affect lis[0]
>>> lis
[1, 2, 3]
>>> x = lis[1]
>>> x = []
>>> lis
[1, 2, 3]
...
请注意,最好使用arg is None
而不是arg==None
如何
def default(x, fn):
return fn() if x is None else x
class Wat(object):
def __init__(self, arg1=None, arg2=None, arg3=None):
self.arg1 = default(arg1, list)
self.arg2 = default(arg2, list)
self.arg3 = default(arg3, list)
怎么样
def default(x, fn):
return fn() if x is None else x
class Wat(object):
def __init__(self, arg1=None, arg2=None, arg3=None):
self.arg1 = default(arg1, list)
self.arg2 = default(arg2, list)
self.arg3 = default(arg3, list)
如果所有变量都具有相同的行为,则可以使用setattr
在循环中设置属性,并使用locals()
访问值。我使用inspect
获取所有变量名称,您可以硬编码它们,或计算它们,或以任何合理的平均值获取它们:
import inspect
class Wat(object):
def __init__(self, arg1=None, arg2=None, arg3=None):
arg_spec, _v, _k, _d = inspect.getargspec(self.__init__)
for k in arg_spec[1:]:
value = locals()[k]
value = [] if value is None else value
setattr(self, k, value)
def give(self, thing):
self.arg1.append(thing)
self.arg2.append(thing)
self.arg3.append(thing)
>>> wat = Wat(arg2=[1,2])
>>> wat.give(5)
>>> wat2 = Wat()
>>> wat2.give(6)
>>> wat.__dict__
{'arg1': [5], 'arg2': [1, 2, 5], 'arg3': [5]}
>>> wat2.__dict__
{'arg1': [6], 'arg2': [6], 'arg3': [6]}
如果所有变量都具有相同的行为,则可以使用setattr
在循环中设置属性,并使用locals()
访问值。我使用inspect
获取所有变量名称,您可以硬编码它们,或计算它们,或以任何合理的平均值获取它们:
import inspect
class Wat(object):
def __init__(self, arg1=None, arg2=None, arg3=None):
arg_spec, _v, _k, _d = inspect.getargspec(self.__init__)
for k in arg_spec[1:]:
value = locals()[k]
value = [] if value is None else value
setattr(self, k, value)
def give(self, thing):
self.arg1.append(thing)
self.arg2.append(thing)
self.arg3.append(thing)
>>> wat = Wat(arg2=[1,2])
>>> wat.give(5)
>>> wat2 = Wat()
>>> wat2.give(6)
>>> wat.__dict__
{'arg1': [5], 'arg2': [1, 2, 5], 'arg3': [5]}
>>> wat2.__dict__
{'arg1': [6], 'arg2': [6], 'arg3': [6]}
编辑:你们中的一些人已经发现了这个问题,但我仍然不知道
有一个令人满意的解决方案@roippi提出了一种有效的方法
一次分配一个变量,但假设我有100个
变量。如何以最少的代码行完成此任务?
这就是循环的最初目的。谢谢各位
每当有人问这个问题时,他们不可避免地使用了错误的数据结构
例如,您可以使用**kwargs
方法捕获传递给Wat
对象的所有关键字参数。你可以从那里用它们做你想做的事,把kwargs
当作正常的dict
class Wat(object):
def __init__(self, **kwargs):
self.arg1 = kwargs.get('arg1', [])
self.arg2 = kwargs.get('arg2', [])
self.arg3 = kwargs.get('arg3', [])
或
或者它们的某种组合:
class Wat(object):
def __init__(self, **kwargs):
self.kwdict = kwargs
self.kwdict['arg1'] = self.kwdict.get('arg1',[])
self.kwdict['arg2'] = self.kwdict.get('arg2',[])
self.kwdict['arg3'] = self.kwdict.get('arg3',[])
您似乎根本不关心参数名,所以可以使用*args
:
class Wat(object):
def __init__(self, *args):
self.args = list(args)
while len(self.args) < 3:
self.args.append([])
class Wat(对象):
定义初始化(self,*args):
self.args=列表(args)
而len(self.args)<3:
self.args.append([])
等等
编辑:你们中的一些人已经发现了这个问题,但我仍然不知道
有一个令人满意的解决方案@roippi提出了一种有效的方法
一次分配一个变量,但假设我有100个
变量。如何以最少的代码行完成此任务?
这就是循环的最初目的。谢谢各位
每当有人问这个问题时,他们不可避免地使用了错误的数据结构
例如,您可以使用**kwargs
方法捕获传递给Wat
对象的所有关键字参数。你可以从那里用它们做你想做的事,把kwargs
当作正常的dict
class Wat(object):
def __init__(self, **kwargs):
self.arg1 = kwargs.get('arg1', [])
self.arg2 = kwargs.get('arg2', [])
self.arg3 = kwargs.get('arg3', [])
或
或者它们的某种组合:
class Wat(object):
def __init__(self, **kwargs):
self.kwdict = kwargs
self.kwdict['arg1'] = self.kwdict.get('arg1',[])
self.kwdict['arg2'] = self.kwdict.get('arg2',[])
self.kwdict['arg3'] = self.kwdict.get('arg3',[])
您似乎根本不关心参数名,所以可以使用*args
:
class Wat(object):
def __init__(self, *args):
self.args = list(args)
while len(self.args) < 3:
self.args.append([])
class Wat(对象):
定义初始化(self,*args):
self.args=列表(args)
而len(self.args)<3:
self.args.append([])
等.
如果Ag1 ToRe[[]/COD>等,你可以只做<代码> Self.ARG1= ARG1等。跳过中间步骤。@ RoIPPI,考虑<代码>如果ALG1没有其他[]/Cord>,否则条件不相同。@ KROOLK如果你的类已经定义了多个伪值的行为,当然。否则,我认为这个区别是没有意义的。“RoPIPI,在另一种情况下,不会<代码> Self.Ag1= ARG1或[]/Cord>更简单吗?)你可以这么做