Class 创建新实例的方法
Class method to create new instance
我正在与 Python 进行一些严肃的 OOP 并且 运行 遇到了一些问题。
我有一个 class,带有一个初始化程序、三个私有变量以及每个变量的设置和获取方法。
此外,它有一个输入法,允许用户在调用变量时为变量输入一个值,而不需要在主函数中调用 input
将值传递给 class 设置方法。这样我就可以立即在特定于数据要求的方法中验证用户输入:
def input_first_name(self):
done = 0
while done == 0:
print("Input First Name:",end='')
first_name = input()
if first_name.isalpha():
self.__first_name = first_name
done = 1
else:
print("Invalid Entry. Please use alphabetic characters only.")
使用这些输入法,我有另一种方法使用它们创建一个新的 class 实例(等等,我已经知道你在想什么):
@classmethod
def new(cls):
cls.input_first_name(cls)
cls.input_last_name(cls)
cls.input_birthday(cls)
return cls
所以我知道使用这个,我不会实际实例化一个新实例。但是,使用这些方法不会立即引发任何错误。但是,当我使用 get 方法引用我新创建的实例时,这就是我遇到麻烦的地方,我知道这与未实例化有关。
new_relative = Relative.new()
print(new_relative.get_first_name())
结果:
TypeError: get_first_name() missing 1 required positional argument: 'self'
有没有办法在我的主要函数中使用 class 方法来实例化一个新实例,该实例以简单而优雅的方式采用我的用户输入和验证想法?
作为参考,class:
的最小样本
class Relative:
__first_name = ""
__last_name = ""
__birthday = 0
def __init__(self, first_name,last_name,birthday):
self.__first_name = first_name
self.__last_name = last_name
self.__birthday = birthday
def get_first_name(self):
return self.__first_name
我会用 properties 来做到这一点(无尽的 get
s 和 set
s 的 Pythonic 替代品,参见 Python @property versus getters and setters),只将 input
留给 class 方法。这是一个最小的例子:
class Relative:
def __init__(self, first_name=None):
self.first_name = first_name
@staticmethod
def _valid_name(name):
return name is None or name.isalpha()
# this will choke if name isn't None or a string - maybe add more rules?
@property
def first_name(self):
return self._first_name
@first_name.setter
def first_name(self, new_name):
if not self._valid_name(new_name):
raise ValueError('Invalid first name: {!r}'.format(new_name))
self._first_name = new_name
@classmethod
def from_input(cls):
relative = cls()
while True:
# you could alternatively use cls._valid_name directly here
try:
relative.first_name = input('Enter first name: ')
except ValueError:
print('Please try again.')
else:
break
return relative
正在使用:
>>> uncle_bob = Relative.from_input()
Enter first name: 123
Please try again.
Enter first name: *
Please try again.
Enter first name: Robert
>>> uncle_bob.first_name
'Robert'
>>> uncle_bob.first_name = '123'
Traceback (most recent call last):
File "<pyshell#14>", line 1, in <module>
uncle_bob.first_name = '123'
File "<pyshell#11>", line 17, in first_name
raise ValueError('Invalid first name: {!r}'.format(new_name))
ValueError: Invalid first name: '123'
注意:
- 将名称验证抽象为
Relative._valid_name
可以很容易地使用相同的规则验证名字和姓氏(您也可以添加一个中间名,并且很容易使它也相同)。
- 使用
@property
意味着用户在任何时候都不能设置不正确的名称,而不会强制他们调用特定方法来获得 get/set 值。
- 我为内部变量使用了 private-by-convention 单下划线名称,而不是 name-mangled 双- 下划线一 - 参见例如the style guide.
我正在与 Python 进行一些严肃的 OOP 并且 运行 遇到了一些问题。 我有一个 class,带有一个初始化程序、三个私有变量以及每个变量的设置和获取方法。
此外,它有一个输入法,允许用户在调用变量时为变量输入一个值,而不需要在主函数中调用 input
将值传递给 class 设置方法。这样我就可以立即在特定于数据要求的方法中验证用户输入:
def input_first_name(self):
done = 0
while done == 0:
print("Input First Name:",end='')
first_name = input()
if first_name.isalpha():
self.__first_name = first_name
done = 1
else:
print("Invalid Entry. Please use alphabetic characters only.")
使用这些输入法,我有另一种方法使用它们创建一个新的 class 实例(等等,我已经知道你在想什么):
@classmethod
def new(cls):
cls.input_first_name(cls)
cls.input_last_name(cls)
cls.input_birthday(cls)
return cls
所以我知道使用这个,我不会实际实例化一个新实例。但是,使用这些方法不会立即引发任何错误。但是,当我使用 get 方法引用我新创建的实例时,这就是我遇到麻烦的地方,我知道这与未实例化有关。
new_relative = Relative.new()
print(new_relative.get_first_name())
结果:
TypeError: get_first_name() missing 1 required positional argument: 'self'
有没有办法在我的主要函数中使用 class 方法来实例化一个新实例,该实例以简单而优雅的方式采用我的用户输入和验证想法?
作为参考,class:
的最小样本class Relative:
__first_name = ""
__last_name = ""
__birthday = 0
def __init__(self, first_name,last_name,birthday):
self.__first_name = first_name
self.__last_name = last_name
self.__birthday = birthday
def get_first_name(self):
return self.__first_name
我会用 properties 来做到这一点(无尽的 get
s 和 set
s 的 Pythonic 替代品,参见 Python @property versus getters and setters),只将 input
留给 class 方法。这是一个最小的例子:
class Relative:
def __init__(self, first_name=None):
self.first_name = first_name
@staticmethod
def _valid_name(name):
return name is None or name.isalpha()
# this will choke if name isn't None or a string - maybe add more rules?
@property
def first_name(self):
return self._first_name
@first_name.setter
def first_name(self, new_name):
if not self._valid_name(new_name):
raise ValueError('Invalid first name: {!r}'.format(new_name))
self._first_name = new_name
@classmethod
def from_input(cls):
relative = cls()
while True:
# you could alternatively use cls._valid_name directly here
try:
relative.first_name = input('Enter first name: ')
except ValueError:
print('Please try again.')
else:
break
return relative
正在使用:
>>> uncle_bob = Relative.from_input()
Enter first name: 123
Please try again.
Enter first name: *
Please try again.
Enter first name: Robert
>>> uncle_bob.first_name
'Robert'
>>> uncle_bob.first_name = '123'
Traceback (most recent call last):
File "<pyshell#14>", line 1, in <module>
uncle_bob.first_name = '123'
File "<pyshell#11>", line 17, in first_name
raise ValueError('Invalid first name: {!r}'.format(new_name))
ValueError: Invalid first name: '123'
注意:
- 将名称验证抽象为
Relative._valid_name
可以很容易地使用相同的规则验证名字和姓氏(您也可以添加一个中间名,并且很容易使它也相同)。 - 使用
@property
意味着用户在任何时候都不能设置不正确的名称,而不会强制他们调用特定方法来获得 get/set 值。 - 我为内部变量使用了 private-by-convention 单下划线名称,而不是 name-mangled 双- 下划线一 - 参见例如the style guide.