创建新实例的类方法

时间:2015-04-21 10:57:58

标签: validation class python-3.x methods instantiation

我正在使用Python进行一些严肃的OOP并遇到一些问题。 我有一个带有初始化程序的类,三个私有变量以及每个变量的set和get方法。

此外,它有一个输入方法,允许用户在调用变量时为变量输入值,而不是在main函数中要求input调用将值传递给类集方法。这样我就可以立即验证特定于数据要求的方法中的用户条目:

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

使用这些输入法,我有另一种方法,用它来创建一个新的类实例(只是等待,我已经知道你在想什么):

@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'       

是否有办法在我的main函数中使用类方法来实例化一个新的实例,该实例以简单而优雅的方式使用我的用户输入和验证的想法?

供参考,该类的最小样本:

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

1 个答案:

答案 0 :(得分:1)

我会使用属性(Pythonic替换无尽的getset来执行此操作,请参阅例如Python @property versus getters and setters),并仅保留{ {1}}到一个类方法。这是一个最小的例子:

input

使用中:

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

请注意:

  1. 将名称验证抽象为>>> 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' ,可以很容易地使用相同的规则验证名字和姓氏(您也可以添加一个中间名,并轻松地使其相同)。
  2. 使用Relative._valid_name表示用户无法在任何时候设置错误的名称,而无需强制他们调用特定的方法来获取/设置值。
  3. 我为内部变量使用了私有的单下划线名称,而不是名称错误的双下划线名称 - 请参阅例如the style guide