[英]Python conditional statement within a Class
What is the best way to achieve having class attributes that change, based on input that has been passed in via a cli argument?根据通过 cli 参数传入的输入,实现类属性发生变化的最佳方法是什么?
What I've written works perfectly fine, however feels overly messy and bad design.我写的东西非常好,但是感觉过于凌乱和糟糕的设计。 Is there a better way to go about this?有没有更好的方法来解决这个问题?
The example below has four different inputs, however as this program grows larger this would become very messy.下面的例子有四个不同的输入,但是随着这个程序变大,这将变得非常混乱。
Here's some short example code;这是一些简短的示例代码;
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'
Example of calling with an argument;带参数调用的示例;
python main.py foo
There are many ways to clean this up, as suggested in the comments.正如评论中所建议的,有很多方法可以清理它。 For something of the size and scale of your example, I would do something like this:对于你的例子的大小和规模,我会做这样的事情:
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]
This method might not always be appropriate depending on the number and type of values you're setting but it's one way to go about it.根据您设置的值的数量和类型,此方法可能并不总是合适的,但这是一种方法。
` ls=['foo','bar','foobar','barfoo'] #add the list of prefixes ` ls=['foo','bar','foobar','barfoo'] #添加前缀列表
if self.var1 in ls:如果 ls 中的 self.var1:
self.var2= f'{self.var1}2'
self.var3= f'{self.var1}3'
self.var4= f'{self.var1}4'
` `
Define a dict
mapping prefixes to a tuple
of the three modifiers, then use it to initialize them:定义一个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
Optionally, this may make more sense to store var2
through var4
as a list
(especially if the number of suffixes is variable by key), in which case you'd do something like this, which is even simpler:或者,将var2
到var4
存储为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
The class body is just Python code.类主体只是 Python 代码。 It has specific scope rules, but anything goes otherwise.它有特定的范围规则,但除此之外什么都没有。 This means you can create functions conditionally:这意味着您可以有条件地创建函数:
class C: if some_condition: def optional_method(self): pass or pull methods from elsewhere: C类:if some_condition:def optional_method(self):从别处传递或拉取方法:
import some_module导入 some_module
class D: method_name = some_module.function_that_accepts_self etc. D 类:method_name = some_module.function_that_accepts_self 等。
One approach is to keep __init__
as "dumb" as possible, define separate class methods for each "style" of object, and push the burden of selecting the right class method to call to the caller.一种方法是尽可能保持__init__
为“哑”,为每个“样式”对象定义单独的类方法,并将选择正确的类方法调用的负担推给调用者。
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()
The only thing you lose here is the ability to pass an unknown value to Example
and get a properly initialized value back, for example,您在这里唯一失去的是将未知值传递给Example
并获得正确初始化值的能力,例如,
x = "..." # Assumed to be foo, bar, foobar, or barfoo
e = Example(x)
However, the caller can always use whatever method you might have hidden in side Element.__init__
to pick the values for var2
et al.但是,调用者始终可以使用您可能隐藏在侧Element.__init__
任何方法来选择var2
等的值。 to pick which class method to all.选择所有的类方法。 For example,例如,
x = "foo"
e = getattr(Example, x)() # e = Example.foo()
Don't know if the best option but assuming that actual values aren 'foo1' 'foo2'
but something else or more complex I would go for updating the self.不知道是否是最好的选择,但假设实际值是'foo1' 'foo2'
但其他或更复杂的东西我会去更新 self. dict字典
Two ways (I think the seccond is more clear)两种方式(我觉得第二种更清楚)
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
Second way:第二种方式:
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()
with same outputs具有相同的输出
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.