【问题标题】:Python conditional statement within a Class类中的 Python 条件语句
【发布时间】:2021-12-09 07:32:42
【问题描述】:

根据通过 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

【问题讨论】:

  • 为什么不只做self.var2 = self.var1 + "2" 和其他人一样?还有,你为什么要从__init___返回self
  • 您可以使用字典来列出每个可能的var1 的所有值。
  • 您可以创建 Example、FooExample、BarExample 的子类……它们定义了自己的值,并且 if 使用特定方法将返回这些类之一
  • @ddejohn 我猜这些是示例,而不是文字值,因此串联不起作用。
  • 在这种情况下,我建议提供一个更具代表性的示例,因为很难说出您到底想做什么。可能有更好的方法,但目前很难辨别您的最终目标。

标签: python python-3.x oop


【解决方案1】:

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

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

或从其他地方提取方法:

import some_module

class D:
    method_name = some_module.function_that_accepts_self

【讨论】:

    【解决方案2】:
    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'
    

    【讨论】:

    • OP 指出后缀不能预测只是 2/3/4;这取决于密钥,因此您不能只对其进行硬编码。
    【解决方案3】:

    一种方法是让__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()
    

    您在这里唯一失去的是将未知值传递给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()
    

    【讨论】:

      【解决方案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 可能更有意义(尤其是如果后缀的数量可以通过键更改),在这种情况下,您可以执行以下操作,即更简单:

      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
      

      【讨论】:

        【解决方案5】:

        如 cmets 中所建议的,有很多方法可以清除它。对于你的例子的大小和规模,我会做这样的事情:

        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]
        

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

        【讨论】:

          【解决方案6】:

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

          输出相同

          【讨论】:

            猜你喜欢
            • 2015-03-04
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-12-08
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多