类中的Python条件语句



根据通过cli参数传入的输入实现类属性更改的最佳方法是什么?

我写的东西工作得很好,但是感觉过于混乱和糟糕的设计。有更好的办法吗?

下面的例子有四个不同的输入,但是随着程序变大,这会变得非常混乱。

下面是一些简短的示例代码;

class Example(object):
def __init__(self, var1):
self.var1 = var1
self.var2 = None
self.var3 = None
self.var4 = None
if var1 == 'foo':
self.var2 = 'foo2'
self.var3 = 'foo3'
self.var4 = 'foo4'
elif var1 == 'bar':
self.var2 = 'bar2'
self.var3 = 'bar3'
self.var4 = 'bar4'
elif var1 == 'foobar':
self.var2 = 'foobar2'
self.var3 = 'foobar3'
self.var4 = 'foobar4'
elif var1 == 'barfoo':
self.var2 = 'barfoo2'
self.var3 = 'barfoo3'
self.var4 = 'barfoo4'

def main()
parser = argparse.ArgumentParser()
parser.add_argument('input')
args = parser.parse_args()
example = Example(args.input)
print(example.var2) # returns 'foo2'

带参数调用的示例;

python main.py foo

一种方法是将__init__保持为" dumb"尽可能为每种"样式"定义单独的类方法。对象,并将选择正确的类方法调用的负担推给调用者。

class Example:
def __init__(self, var1, var2, var3, var4):
self.var1 = var1
self.var2 = var2
self.var3 = var3
self.var4 = var4
@classmethod
def foo(cls):
return cls('foo', 'foo2', 'foo3', 'foo4')
@classmethod
def bar(cls):
return cls('bar', 'bar2', 'bar3', 'bar4')
# etc
# Instead of Example('foo')
e = Example.foo()

您在这里唯一失去的是将未知值传递给Example并获得正确初始化值的能力,例如

x = "..."  # Assumed to be foo, bar, foobar, or barfoo
e = Example(x)

然而,调用者总是可以使用隐藏在Element.__init__中的任何方法来为var2等选择值,以选择所有的类方法。例如,

x = "foo"
e = getattr(Example, x)()  # e = Example.foo()

正如评论中建议的那样,有很多方法可以清除这个问题。对于您示例的大小和规模,我会这样做:

class Example:
_DEPENDENT_VALS = {
'foo': ('foo2', 'foo3', 'foo4'),
'bar': ('bar2', 'bar3', 'bar4'),
'foobar': ('foobar2', 'foobar3', 'foobar4'),
'barfoo': ('barfoo2', 'barfoo3', 'barfoo4')
}
def __init__(self, var1):
self.var1 = var1
self.var2 = None
self.var3 = None
self.var4 = None
if var1 in Example._DEPENDENT_VALS:
self.var2, self.var3, self.var4 = Example._DEPENDENT_VALS[var1]

这个方法可能并不总是合适的,这取决于你要设置的值的数量和类型,但这是一种方法。

定义一个dict映射前缀到三个修饰符的tuple,然后使用它来初始化它们:

class Example:
_var_suffixes = {'foo': ('1', '2', '3'),
'bar': ('1', '2', '3'),
'foobar': ('1', '2', '3'),
'barfoo': ('1', '2', '3'),
}
def __init__(self, var1):
self.var1 = var1
self.var2 = None
self.var3 = None
self.var4 = None
if var1 in self._var_suffixes:
suf2, suf3, suf4 = self._var_suffixes[var1]
self.var2 = var1 + suf2
self.var3 = var1 + suf3
self.var4 = var1 + suf4

可选地,将var2var4存储为list可能更有意义(特别是如果后缀的数量随键而变化),在这种情况下,您可以这样做,这甚至更简单:

class Example:
_var_suffixes = {'foo': ('1', '2'),
'bar': ('1', '2', '3'),
'foobar': ('1', '2', '3', '4'),
'barfoo': ('1', '2', '3', '4', '5'),
}
def __init__(self, var1):
self.var1 = var1
self.varlist = []
for suf in self._var_suffixes.get(var1, ()):
self.varlist.append(var1 + suf)
# Optional property for access by name
@property
def var2(self):
try:
return self.varlist[0]
except IndexError:
return None
ls=['foo','bar','foobar','barfoo'] #adds the list of prefixes 
if self.var1 in ls:
self.var2= f'{self.var1}2'
self.var3= f'{self.var1}3'
self.var4= f'{self.var1}4'

类体只是Python代码。它有特定的作用域规则,但情况并非如此。这意味着您可以有条件地创建函数:

class C:
if some_condition:
def optional_method(self):
pass

或从其他地方获取方法:

import some_module
class D:
method_name = some_module.function_that_accepts_self

不知道最好的选择,但假设实际值是'foo1' 'foo2',但其他东西或更复杂,我会去更新自我。dict

两种方法(我认为第二种更清楚)

class A():
def __init__(self,var1):
self.var1 = var1
fooDict = {'var2':'foo2','var3':'foo3','var4':'foo4'}
foovarDict = {'var2':'foovar2','var3':'foovar3','var4':'foovar4'}
if var1 == 'foo':
self.__dict__ = {**self.__dict__,**fooDict}
elif var1 == 'foovar':
self.__dict__ = {**self.__dict__,**foovarDict}

def getVars(self):
print(self.var1)
print(self.var2)
print(self.var3)
print(self.var4)

a = A('foo')
a.getVars()
#ouputs
#foo
#foo2
#foo3
#foo4
b = A('foovar')
b.getVars()
#outputs
#foovar
#foovar2
#foovar3
#foovar4

第二种方式:

class A():
def __init__(self,var1):
self.var1 = var1
fooDict = {'var2':'foo2','var3':'foo3','var4':'foo4'}
foovarDict = {'var2':'foovar2','var3':'foovar3','var4':'foovar4'}
if var1 == 'foo':
self.__dict__.update(fooDict)
elif var1 == 'foovar':
self.__dict__.update(foovarDict)
def getVars(self):
print(self.var1)
print(self.var2)
print(self.var3)
print(self.var4)
a = A('foo')
a.getVars()

b = A('foovar')
b.getVars()

具有相同输出