【问题标题】:In Practice, Should all the objects of a class be made to have same number of attributes?在实践中,一个类的所有对象是否应该具有相同数量的属性?
【发布时间】:2014-07-04 14:56:54
【问题描述】:

哪种编码方式更好?

以下示例(用python编写):

class sampleClass:
   def __init__( self, filter ):   #filter is a string
      self.indexed = False #no
      filterTokens = filter.split()
      if ( filterTokens[0].isdigit ):
         self.indexed = True #yes
      else:
         return
      self.action = filterTokens[1]
      self.protocol = filterTokens[2]
      self.validity = True #valid
      if ( self.protocol == 'ip' )
         #something
      elif ( self.protocol == 'tcp' )
         #someOtherThing
      else:
         self.validity = False #Invalid

现在,如果 filter 中的第一个 token 不是数字,则该类的对象将只有一个属性 - indexed

上面的类可能有数百个属性。在这种情况下,这是一种更好的编码实践 -

为所有对象具有相同数量的属性。 (即在构造函数的顶部定义所有属性,给它们一些默认值或其他)

或者

另一种方式(如上面的示例)

例如。

filter = '10 permit ip 10.10.10.0/28 20.20.20.0/28'
obj = sampleClass(filter)

【问题讨论】:

  • 你为什么使用01而不是TrueFalse?整个filter 只是布尔属性的一系列标志吗?你有所有属性的默认值吗?是否有一些依赖于他人?您什么时候访问这些属性?
  • @jonrsharpe 过滤器是一个信息字符串。基于哪些属性被初始化。并非所有属性都相互依赖。如果我没有所有属性的默认值,它们可以只是 "n/a" 或类似的东西。
  • 您能否提供几个稍微不那么简单的filter 示例以及应该如何处理?
  • 你为什么要做那个初始化。只需存储过滤器字符串。为什么它还是一个字符串?
  • @TonyHopkinson 因为 filter 中的信息是以后使用的,不是字符串,而是分段。我不在乎字符串是否没有被索引,它只会在字符串被索引时困扰我。按原样存储字符串将导致以后的操作复杂化。我寻求关于更可取的编码风格的意见。

标签: python class coding-style


【解决方案1】:

唯一真正的区别在于使用你的类的代码。任何这样的代码看起来都可能是这样的:

if sample_instance.indexed and sample_instance.valid: # 'valid' reads better
    protocol = sample_instance.protocol

因此,在.indexed == False 的情况下,.valid.protocol 是否存在或具有任何特定值并不重要。

如果您希望调用代码返回一个属性(即使只是None),无论如何,您始终可以为任何未直接解析的属性实现__getattr__return None


不过,我建议将字符串解析移出__init__;考虑使用一个类方法来代替。此外,您在同一方法中混合了不同的逻辑位。比较:

class SampleClass(object):

    PROTOCOLS = {'ip': do_this_to_ip, 
                 'tcp': but_this_to_tcp}

    def __init__(self, indexed=False, action=None, protocol=None):
        self.indexed = indexed
        self.action = action
        self.protocol = protocol

    @property
    def valid(self):
        return self.protocol in self.PROTOCOLS 

    @classmethod
    def from_string(cls, filter_): # avoid shadowing the built-in
        filter_ = filter_.split()
        if not filter_[0].isdigit():
            return cls()
        return cls(True, filter_[1], filter_[2])

会这样使用:

>>> sample = SampleClass.from_string("10 permit ip")
>>> sample.valid
True
>>> sample.protocol
'ip'
>>> sample2 = SampleClass.from_string("foo bar")
>>> sample2.valid
False

最后,您应该考虑的一个更广泛的问题是:如果实例彼此如此不同,它们真的应该是同一个类吗?

【讨论】:

    猜你喜欢
    • 2023-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-27
    • 2017-02-27
    • 2023-03-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多