Python Class 中的条件语句

Python conditional statement within a Class

根据通过 cli 参数传入的输入,实现 class 属性发生变化的最佳方法是什么?

我写的东西工作得很好,但感觉过于混乱和糟糕的设计。有没有更好的方法来解决这个问题?

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

这是一些简短的示例代码;

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

不知道是否是最佳选择,但假设实际值是 '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()

具有相同的输出

如评论中所建议的,有很多方法可以清理它。对于您示例的大小和规模,我会做这样的事情:

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]

根据您设置的值的数量和类型,此方法可能并不总是合适的,但这是一种解决方法。

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'

定义一个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 可能更有意义(特别是如果后缀的数量是按键可变的),在这种情况下你d 做这样的事情,这更简单:

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

class 主体只是 Python 代码。它有特定的范围规则,但一切都不一样。这意味着您可以有条件地创建函数:

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

或从别处拉取方法:

import some_module

class D:
    method_name = some_module.function_that_accepts_self

一种方法是让 __init__ 尽可能“愚蠢”,为对象的每个“样式”定义单独的 class 方法,并减轻选择正确 class 的负担] 调用调用方的方法。

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 等选择值。为所有人选择哪种 class 方法。例如,

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