Объект класса может вызывать метод только в том случае, если атрибут объекта находится в диапазоне - PullRequest
2 голосов
/ 26 мая 2020

Я хочу сделать свой код более сложным, и это проблема, с которой я сталкиваюсь

class Person:

    def __init__(self, age):
        self.age = age

    def drives(self):
        if self.age >= 18:
            # Do more things which driving entitles
            print("you can drive")

    def studies(self):
        if self.age <= 25:
            # Do more student stuffs
            print("Good luck with your education")

bob = Person(14)
bob.drives()
bob.studies()

jim = Person(35)
jim.drives()
jim.studies()

Мне не нравятся проверки, как только я ввожу метод, увеличивая разметку. Я знаю о декораторах, они лучше всего здесь? И как мне их использовать в этом случае? Я бы хотел, чтобы он выглядел так:

class Person:

    def __init__(self, age):
        self.age = age

    @check_if_person_age_is_greater_than_17
    def drives(self):
        # Do more things which driving entitles
        print("you can drive")

    @check_if_person_age_is_less_than_26
    def studies(self):
        # Do more student stuffs
        print("Good luck with your education")

bob = Person(14)
bob.drives() # either this method cannot be accessed or returns nothing, since bob is 14
bob.studies() # this should work normally

jim = Person(35)
jim.drives() # this should work normally
jim.studies() # either this method cannot be accessed or returns nothing, since jim is 35

Прошу прощения, если мой вопрос не является кратким или не заслуживающим внимания.

1 Ответ

2 голосов
/ 29 мая 2020

Так вот что я смог придумать. Это довольно сильно очищает код, но может сделать его немного трудным для понимания. Вы также можете превратить декоратор в classmethod или staticmethod, если это ваше требование.

from functools import wraps


def prerequisite(age_limit=18, _func=None):
  def _wrapper_function(func):
    @wraps(func)
    def _inner_function(*args, **kwargs):
        if args[0].age >= age_limit:
          return func(*args, **kwargs)
        else:
          raise ValueError("You can't {func_name} at the age of {age}".format(func_name=func.__name__, age=args[0].age))
    return _inner_function
  if _func is None:
      return _wrapper_function
  else:
      return _wrapper_function(_func)

class Person(object):
    def __init__(self, age):
      self.age = age

    @prerequisite(age_limit=16)
    def drive(self):
      # Do more drive stuffs
      print("You are eligible to apply for a license to drive. Please drive responsibly.")

    @prerequisite(age_limit=21)
    def drink(self, drink_name):
      # Do more drink stuffs
      # Passing an argument just to show that arguments can also be passed like this.
      print("You can legally drink. Alcohol is dangerous to health, drink cautiously. Your favorite drink is {drink_name}".format(drink_name=drink_name))

    @prerequisite()
    def fly(self):
      # Do more fly stuffs
      # This is an example for how default args for decorator works
      print("You are eligible to apply for a license to fly.")

bob = Person(19)

bob.drive() # works
bob.fly() # works
bob.drink("Beer") # This will throw an exception
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...