Python3 - 澄清对同一 属性 的多重验证
Python3 - Clarification about multiple verifications on the same property
我想对 Python 中的同一个 属性 进行不同的验证,但我不确定正确的方法是什么。例如,在下面的代码中,我想验证我的对象的名字和姓氏(以大写字母开头,长度超过 2 个符号)。对于姓氏 属性,我将所有检查合并为一个 setter。在这种情况下,我的代码不会同时捕获这两个异常。如果我像在名字 setter 中那样拆分它们,我无法一直将其设为 运行。我的问题是什么是正确的实现方式?谢谢。
class Person:
def __init__(self, first_name, last_name):
self.first_name = first_name
self.last_name = last_name
@property
def last_name(self):
return self.__last_name
@last_name.setter
def last_name(self, value):
if len(value) > 2:
self.__last_name = value
else:
raise Exception("Last name: more than 2 symbs needed")
for letter in value:
if letter == letter.upper():
self.__last_name = value
break
else:
raise Exception('Last name: has to start with upper case')
@property
def first_name(self):
return self.__first_name
@first_name.setter
def first_name(self, value):
for letter in value:
if letter == letter.upper():
self.__first_name = value
break
else:
raise Exception('First name: has to start with upper case')
@first_name.setter
def first_name(self,value):
if len(value) > 2:
self.__first_name = value
else:
raise Exception("First name: more than 2 symbs needed")
Jack = Person('Ja', 'sparrow')
print(Jack.first_name)
print(Jack.last_name)
您可以简单地做一个合乎逻辑的 and
来检查这两个条件。
这里有一个姓氏的例子
class Person:
def __init__(self, first_name, last_name):
self.first_name = first_name
self.last_name = last_name
@property
def last_name(self):
return self.__last_name
@staticmethod
def _first_letter_is_upper(val):
return val[0].isupper()
@last_name.setter
def last_name(self, value):
if len(value) > 2 and Person._first_letter_is_upper(value):
self.__last_name = value
else:
raise Exception("Last name: more than 2 symbs needed")
我已经稍微清理了您的代码并进行了一些更改以使其正常工作。此外,我建议您使用 raise ValueError()
而不是 Exception
,因为这实际上是 first_name
和 last_name
.
的值错误
通过调整您的代码并相应地打印错误消息,可以在一个值中捕获这两个错误。但是,您不能期望在 first_name
和 last_name
中都捕获错误,因为一旦第一个异常发生,代码就会停止执行,因此无法捕获和显示下一个异常。这仅仅是因为 python 是一种解释型语言,它会在第一次出现错误时停止执行。
这是我的代码版本。
给self.first_name
赋值,实际上会调用first_name()
方法@property
.
self.last_name
.
也是如此
这确保即使在 __init__()
中也验证值
@property.setter
方法将值设置为名为 _property 的变量; _first_name
和 _last_name
.
在变量前加下划线 (_) 表明该变量不应公开使用,而是类似于代码的内部变量。
_first_name
和 _last_name
保存对象的实际值,而 @property
方法只是充当用户访问(获取和设置)这些对象的一种前端值。由于这些是方法,因此可以在此处轻松完成验证。
class Person:
def __init__(self, first_name='John', last_name='Doe'):
self.first_name = first_name
self.last_name = last_name
def __repr__(self):
return f'{self.__class__.__name__}({self.first_name} {self.last_name})'
@property
def last_name(self):
return self._last_name
@last_name.setter
def last_name(self, value):
msg = ''
if len(value) <= 2:
msg = 'Last name: more than 2 symbols needed'
if not value[0].isupper():
if not msg:
msg = 'Last name: has to start with upper case'
else:
msg += ', has to start with upper case'
if msg:
raise ValueError(msg)
else:
self._last_name = value
@property
def first_name(self):
return self._first_name
@first_name.setter
def first_name(self, value):
msg = ''
if len(value) <= 2:
msg = 'First name: more than 2 symbols needed'
if not value[0].isupper():
if not msg:
msg = 'First name: has to start with upper case'
else:
msg += ', has to start with upper case'
if msg:
raise ValueError(msg)
else:
self._first_name = value
这是一个有效 Person
对象的示例。
>>> p = Person('Jack', 'Sparrow')
>>> p
Person(Jack Sparrow)
这些是在尝试创建具有无效值的对象时导致的异常。
>>> p = Person('ja', 'Sparrow')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "per.py", line 3, in __init__
self.first_name = first_name
File "per.py", line 47, in first_name
raise ValueError(msg)
ValueError: First name: more than 2 symbols needed, has to start with upper case
>>> p = Person('Jack', 'sparrow')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "per.py", line 4, in __init__
self.last_name = last_name
File "per.py", line 26, in last_name
raise ValueError(msg)
ValueError: Last name: has to start with upper case
如果 first_name
和 last_name
均无效,则仅引发 first_name
的 Exception
,因为这是代码中首先分配的值。一旦 Exception
出现,执行就会停止,因此不再捕获值为 last_name
的错误。
>>> p = Person('jack', 'Sp')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "per.py", line 3, in __init__
self.first_name = first_name
File "per.py", line 47, in first_name
raise ValueError(msg)
ValueError: First name: has to start with upper case
我想对 Python 中的同一个 属性 进行不同的验证,但我不确定正确的方法是什么。例如,在下面的代码中,我想验证我的对象的名字和姓氏(以大写字母开头,长度超过 2 个符号)。对于姓氏 属性,我将所有检查合并为一个 setter。在这种情况下,我的代码不会同时捕获这两个异常。如果我像在名字 setter 中那样拆分它们,我无法一直将其设为 运行。我的问题是什么是正确的实现方式?谢谢。
class Person:
def __init__(self, first_name, last_name):
self.first_name = first_name
self.last_name = last_name
@property
def last_name(self):
return self.__last_name
@last_name.setter
def last_name(self, value):
if len(value) > 2:
self.__last_name = value
else:
raise Exception("Last name: more than 2 symbs needed")
for letter in value:
if letter == letter.upper():
self.__last_name = value
break
else:
raise Exception('Last name: has to start with upper case')
@property
def first_name(self):
return self.__first_name
@first_name.setter
def first_name(self, value):
for letter in value:
if letter == letter.upper():
self.__first_name = value
break
else:
raise Exception('First name: has to start with upper case')
@first_name.setter
def first_name(self,value):
if len(value) > 2:
self.__first_name = value
else:
raise Exception("First name: more than 2 symbs needed")
Jack = Person('Ja', 'sparrow')
print(Jack.first_name)
print(Jack.last_name)
您可以简单地做一个合乎逻辑的 and
来检查这两个条件。
这里有一个姓氏的例子
class Person:
def __init__(self, first_name, last_name):
self.first_name = first_name
self.last_name = last_name
@property
def last_name(self):
return self.__last_name
@staticmethod
def _first_letter_is_upper(val):
return val[0].isupper()
@last_name.setter
def last_name(self, value):
if len(value) > 2 and Person._first_letter_is_upper(value):
self.__last_name = value
else:
raise Exception("Last name: more than 2 symbs needed")
我已经稍微清理了您的代码并进行了一些更改以使其正常工作。此外,我建议您使用 raise ValueError()
而不是 Exception
,因为这实际上是 first_name
和 last_name
.
通过调整您的代码并相应地打印错误消息,可以在一个值中捕获这两个错误。但是,您不能期望在 first_name
和 last_name
中都捕获错误,因为一旦第一个异常发生,代码就会停止执行,因此无法捕获和显示下一个异常。这仅仅是因为 python 是一种解释型语言,它会在第一次出现错误时停止执行。
这是我的代码版本。
给self.first_name
赋值,实际上会调用first_name()
方法@property
.
self.last_name
.
这确保即使在 __init__()
@property.setter
方法将值设置为名为 _property 的变量; _first_name
和 _last_name
.
在变量前加下划线 (_) 表明该变量不应公开使用,而是类似于代码的内部变量。
_first_name
和 _last_name
保存对象的实际值,而 @property
方法只是充当用户访问(获取和设置)这些对象的一种前端值。由于这些是方法,因此可以在此处轻松完成验证。
class Person:
def __init__(self, first_name='John', last_name='Doe'):
self.first_name = first_name
self.last_name = last_name
def __repr__(self):
return f'{self.__class__.__name__}({self.first_name} {self.last_name})'
@property
def last_name(self):
return self._last_name
@last_name.setter
def last_name(self, value):
msg = ''
if len(value) <= 2:
msg = 'Last name: more than 2 symbols needed'
if not value[0].isupper():
if not msg:
msg = 'Last name: has to start with upper case'
else:
msg += ', has to start with upper case'
if msg:
raise ValueError(msg)
else:
self._last_name = value
@property
def first_name(self):
return self._first_name
@first_name.setter
def first_name(self, value):
msg = ''
if len(value) <= 2:
msg = 'First name: more than 2 symbols needed'
if not value[0].isupper():
if not msg:
msg = 'First name: has to start with upper case'
else:
msg += ', has to start with upper case'
if msg:
raise ValueError(msg)
else:
self._first_name = value
这是一个有效 Person
对象的示例。
>>> p = Person('Jack', 'Sparrow')
>>> p
Person(Jack Sparrow)
这些是在尝试创建具有无效值的对象时导致的异常。
>>> p = Person('ja', 'Sparrow')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "per.py", line 3, in __init__
self.first_name = first_name
File "per.py", line 47, in first_name
raise ValueError(msg)
ValueError: First name: more than 2 symbols needed, has to start with upper case
>>> p = Person('Jack', 'sparrow')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "per.py", line 4, in __init__
self.last_name = last_name
File "per.py", line 26, in last_name
raise ValueError(msg)
ValueError: Last name: has to start with upper case
如果 first_name
和 last_name
均无效,则仅引发 first_name
的 Exception
,因为这是代码中首先分配的值。一旦 Exception
出现,执行就会停止,因此不再捕获值为 last_name
的错误。
>>> p = Person('jack', 'Sp')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "per.py", line 3, in __init__
self.first_name = first_name
File "per.py", line 47, in first_name
raise ValueError(msg)
ValueError: First name: has to start with upper case