Python-返回之前验证电话号码

时间:2019-02-27 23:23:32

标签: python regex

考虑到我正在使用的数据源非常脏,并且可能在“电话号码”字段中包含以下内容;

  • 空(新标准)
  • !关闭!
  • 无人

我正在批量导入,并希望确保甚至不打扰这些。因此,我正在筛选一个类以格式化数字,但我也想验证一下,如果不是数字,则将其丢弃。

class PhoneNumber:
        def __init__( self, number_raw ):
                number = re.sub('[^0-9]', '', number_raw)
                self.area_code= number[ 0:3 ]
                self.exchange = number[ 3:6 ]
                self.line = number[ 6:13 ]

        def __str__( self ):
                return "({0}) {1}-{2}".format( self.area_code, self.exchange, self.line )

需要考虑的几件事:

  • 我无法修改实际数据源
  • 我无法在参加本课程之前进行验证

我认为我可以做这样的事情,如果它不是有效的数字,只需使用if语句传递False,但是我觉得这可能很草率。

有什么更好的方法来验证它仅仅是数字输入,而如果输入一个字符串,则将其扔掉并返回None


潜在的解决方案1:

class PhoneNumber:
        def __init__( self, number_raw ):
                validation = re.match('[^0-9]', '', number_raw)
                if validation is False:
                    return None
                else:
                    number = re.sub('[^0-9]', '', number_raw)
                    self.area_code= number[ 0:3 ]
                    self.exchange = number[ 3:6 ]
                    self.line = number[ 6:13 ]
                    self.full_number = number

        def __str__( self ):
                return "({0}) {1}-{2}".format( self.area_code, self.exchange, self.line )

潜在解决方案2:

class PhoneNumber:
        def __init__( self, number_raw ):
            number = re.sub('[^0-9]', '', number_raw)
            self.area_code = number[ 0:3 ]
            self.exchange = number[ 3:6 ]
            self.line = number[ 6:13 ]
            self.og_number = number_raw

        def __str__( self ):
                validation = re.match('[^0-9]', '', self.og_number)
                if validation is False:
                    return None
                return "({0}) {1}-{2}".format( self.area_code, self.exchange, self.line )

2 个答案:

答案 0 :(得分:1)

没有理由实例化所有字段都设置为None的对象。 我会像这样对__init__做一些检查:

class PhoneNumber:
    def __init__(self, number_raw):
        number = int(number_raw)  # do not catch exception here, catch it on instantiation
        number_str = str(number)  # parse to str for slicing

        self.areaCode = number_str[0:3]  # note no space around slicing indexes
        self.exchange = number_str[3:6]
        self.line = number_str[6:13]

此外,值得注意的是将使用类似PEP-8的变量,因此请使用 area_code而不是areaCode

第二种方式(使用类方法)

如果由于某些原因需要返回None,则可能会发现使用类方法进行实例化非常有用,例如:

class PhoneNumber:
    def __init__(self, number_raw):
        self.areaCode = number_raw[0:3] 
        self.exchange = number_raw[3:6]
        self.line = number_raw[6:13]

    @classmethod
    def instantiate_with_checks(cls, number_raw):
        try:
            int(number_raw)
        except ValueError:
            return None
        # after ensuring that provided variable is valid
        return cls(number_raw)

实例化新的PhoneNumber对象,如下所示: PhoneNumber.instantiate_with_checks(number_raw)

第三种方式(使用__new__

class PhoneNumber:
    def __init__( self, number_raw ):
        self.area_code = number[0:3]
        self.exchange = number[3:6]
        self.line = number[6:13]

    @classmethod
    def is_number_valid(cls, number_raw):
        try:
            int(number_raw)
        except ValueError:
            return False
        return True

    def __new__(cls, number_raw):
        if cls.is_number_valid(number_raw):
            return super().__new__(cls)

答案 1 :(得分:1)

也许只是在 init 中进行格式化,然后就是否有有效数字做出决定?

class FormattedPhoneNumber(object):
  def __init__(self, number):
    try:
      as_number = int(number)
    except (TypeError, ValueError):
      self._formatted = None
    else:
      # you have a number, do whatever formatting you need to do
      area_code = number[ 0:3 ]
      exchange = number[ 3:6 ]
      line = number[ 6:13 ]
      self._formatted = "({0}) {1}-{2}".format(area_code,exchange,line)

  def __str__(self):
    return self._formatted