2015-04-21 4 views
0

Я попадаю в серьезный ООП с Python и сталкиваюсь с некоторыми проблемами. У меня есть класс с инициализатором, три частные переменные и набор и получение методов для каждой переменной.Метод класса для создания нового экземпляра

Кроме того, у него есть метод ввода, который позволяет пользователю вводить значение для переменных при их вызове, вместо того, чтобы требовать вызова в основной функции, передающей значение методу набора классов, 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'  

Есть прочь способ иметь метод класса, используемый в моей главной функции для инстанцирования нового экземпляра, который использует мою идею ввода и проверки пользователя в простом и элегантной манере?

Для справки, минимальный образец класса:

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

Я хотел бы сделать это с свойствами (заменой вещей для безграничны get s и set s, смотрите, например, Python @property versus getters and setters), и оставить только 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 

При использовании:

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

Обратите внимание, что:

  1. Абстрагируясь вне проверки имен для Relative._valid_name позволяет легко проверить и фамилии с (вы также можете добавить среднее имя и легко сделать то же самое).
  2. Использование @property означает, что пользователь не может установить неправильное имя в любой точке, не заставляя их вызывать определенный метод для получения/установки значений.
  3. Я использовал частно-на-конвенции одним подчеркиванием имя внутренней переменной, а не имя-подогнаны дважды подчеркнуть один - смотри, например, the style guide.
Смежные вопросы