Python-返回前验证电话号码

Python-返回前验证电话号码,python,regex,Python,Regex,考虑到我使用的数据源非常脏,在“电话号码”字段中可能包含以下内容: 空(新标准) !!关闭 没有 我正在做一个大批量导入,我想确定的是,我甚至不必为这些东西操心。所以我在过滤一个类来格式化数字,但是我也想验证,如果不是数字,就把它扔掉 class PhoneNumber: def __init__( self, number_raw ): number = re.sub('[^0-9]', '', number_raw)

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

  • 空(新标准)
  • !!关闭
  • 没有
我正在做一个大批量导入,我想确定的是,我甚至不必为这些东西操心。所以我在过滤一个类来格式化数字,但是我也想验证,如果不是数字,就把它扔掉

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 )
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 )
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)
潜在解决方案2:

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 )
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 )
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)

没有理由实例化所有字段都设置为“无”的对象。 我会对
\uuuu init\uuuu
进行一些检查,如下所示:

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\u code
而不是
areaCode

第二种方法(使用classmethod)

如果出于某些原因需要返回
None
,您可能会发现使用classmethod进行实例化非常有用,如下所示:

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。使用\u检查(数字\u原始)实例化\u

第三种方式(使用
\uuuu new\uuu
):

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 )
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 )
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)

也许只需在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

当你说你想“扔掉它”时,你是想对结果数字使用None,还是想跳过整个记录?如果手机与模式不匹配,可能会在
\uuuuuuuu init\uuuuuuu
上引发异常。然后简单地在
电话号码
实例化中捕捉它。你能试着将它转换为int吗?在
上捕捉它将是一个错误。如果无效,是否要将每个字段设置为
None
areaCode
exchange
)?请不要这样做。如果无效,则没有理由实例化的
PhoneNumber
。我会坚持我的第一条评论。@Codespend添加了一个答案,你可以看一下。你介意在我的编辑中看一看我的潜在解决方案吗&与你的策略相比,这似乎更有效&为什么?你在那里实例化无用的对象。在
\uuuu init\uuuu
中返回
None
根本不起任何作用,事实上这是一种默认行为。关于PEP8,另一件需要提及的事情是,空格不会直接放在括号之后或之前。是的,这是有意义的,但是如果我理解正确,并且
电话号码
电话号码
类的实例化,那么电话号码将永远不会是
。您可以使用
\u新的
方法或
类方法
来实现这一点。我将很快更新我的答案。也许用
int(number)
而不是
作为\u number=int(number)
会更好?Int版本是不必要的。