(Python) How to prevent methods from being accessed from the value of some attribute

Asked

Viewed 149 times

0

It may not have been very clear about the title, but I wanted it only to be possible to use a method on an object if one or more of its attributes are in a certain way. For example: A TV class that has several methods, to increase, decrease, change channel, turn on, turn off. As the code below shows (in this case I removed all methods and attributes that do not help in understanding doubt):

I removed everything from the code that helped in the understanding of doubt

'''python
class Tv:
  def __self__(self, ligado=False, volume=0):#apenas define os atributos
    self.ligado = ligado
    self.volume = volume

  def altera_volume(self, novo_volume):#ele so faz mudar o valor do atributo "volume"
    self.volume = novo_volume

  def botao_on(self):#ou seja, esta meio que precionando aquele botaozinho de ligar a tv
    if self.ligado == False:#ou seja se a tv estiver desligada, ele vai ligar ela. ou seja "ligado" sera verdadeiro
      self.ligado == True
    else:#ou seja, se a tv estiver ligada o atributo ligado será falso
      self.ligado == False

#Nada do que esta escrito dentro dos metodos "altera_volume" e "botao_on" importa, a unica coisa que importa é que "altera_volume" só
#pode ser usado se o atributo "ligado" for verdadeiro, ou seja olha o que aconteceria abaixo

televisao = Tv()#ou seja televisao é uma Tv desligada com volume 0
televisao.alterar_volume(100)#Aqui esta o problema, como é possivel alterar o volume com a tv desligada?

#Tem alguma forma de proibir o uso do metodo "alterar_volume" até que o atributo "ligado" tenha o valor que eu quero?
'''

3 answers

1

Good afternoon. Crazy Dog, unfortunately I think there is no way to do a single magical thing that will prevent you from replicating the "condition" in those 50 or 100 methods. Use Property and do if in the methods you think you need.

class Tv(object):

    def __init__(self, ligado = False, volume = 0):
        self._ligado = ligado
        self._volume = volume

    def altera_volume(self, novo_volume):
        if self.ligado:
            self._volume = novo_volume

    @property
    def ligado(self):
        return self._ligado

    @ligado.setter
    def ligado(self, novo_estado):
        self._ligado = novo_estado

this is the famous python "get and set". If you use Property, you can change the volume without the "altera_volume" method, but instead simply use a self.volume = volume_desired. Check out the property.

Abç.

1

I don’t quite understand, but I think you want to prevent direct access to class attributes. If this is the case you will have to name the attributes with dunderscore or underline twice before the variable name, example:self.volume = volume para self.__volume = volume. I hope I’ve helped.

  • 1

    Actually I wanted it to be possible to use the "altera_volume" method only if the attribute "turned on" had a true value. I could even put an IF to check this, but if they had many methods (like 50 or 100) it would be difficult to put an IF for each of them. Dai wondered if there’s any more practical way to do it

  • 1

    Voce can put the if in the volume alters method and call it from the others. In volume change you check if this connected then if it is applied the volume change.

  • 1

    In def botao_on you return the state self on.: def botao_on(self):#ou seja, esta meio que precionando aquele botaozinho de ligar a tv
 if self.ligado == False:#ou seja se a tv estiver desligada, ele vai ligar ela. ou seja "ligado" sera verdadeiro
 self.ligado == True
 else:#ou seja, se a tv estiver ligada o atributo ligado será falso
 self.ligado == False return self.ligado

  • 1

    In this case would you need to put an IF on all methods to verify this? because if it had several methods, like "muda_canal", "poem_mudo", "restarts"... I would need to check in each method. or even if there were many more methods.

  • 1

    If you have to check yes, but the difference is that vc will return the value of the state so that everyone sees with Return self.on, but it could also nest with the if case on and thus perform the other functions. In the case of the connected tv the volume and other functions would be activated automatically or would have a command ?

  • 1

    Assuming this program was run, then it would enter interactive mode. I could instantiate another object, but if the linked attribute is with False value I would still be able to use its methods. How could you do a check. The problem is that there could be many methods and having to create a check for each of the methods would be complicated. But the methods would not be activated automatically, only if you write. Actually I don’t even know how to automatically activate

Show 1 more comment

1

This is a good case where we use exceptions. Exceptions are when something unforeseen happens, they come from logic errors or access to unavailable resources.

Whenever an exception occurs, the program’s execution stack is stopped until some processing is done, otherwise the program itself is stopped by casting the exception on the console.

You can read more about exceptions in python here.

By analyzing your TV class, we could make an exception if any action is taken and the TV is off. This exception would be similar to the following code:

class TvDesligadaException(Exception):
  def __init__(self, message):
     self.message = message

  def __str__(self):
   return repr(self.message)

Soon, in the tv class, if the method to increase volume is called with the tv off, you can launch the exception warning that such an operation is not possible.

class Tv:
  def __init__(self, ligado=False, volume=0):
    self.ligado = ligado
    self.volume = volume

  def altera_volume(self, novo_volume):
    if(self.ligado == False):
      raise TvDesligadaException('Não é possível aumentar o volume com a tv desligada!')

    self.volume = novo_volume

  def botao_on(self):
    if(self.ligado == False):
      self.ligado = True
    else:
      self.ligado == False

So when we try to turn up the volume without turning on the TV first:

televisao = Tv()
televisao.altera_volume(100)

Our exception is cast on the console:

Traceback (most recent call last):
  File "main.py", line 26, in <module>
    televisao.altera_volume(100)
  File "main.py", line 15, in altera_volume
    raise TvDesligadaException('Não é possível aumentar o volume com a tv desligada!')
__main__.TvDesligadaException: 'Não é possível aumentar o volume com a tv desligada!'

If the TV is turned on before, the runstack normally follows:

televisao = Tv()
televisao.botao_on()
televisao.altera_volume(100)

To avoid interrupting code execution, you can perform a treatment of the possible exception to be launched.

televisao = Tv()

try:
  televisao.altera_volume(100)
except TvDesligadaException:
  print('A TV estava desligada')
  print('Ligando a TV')
  televisao.botao_on()

  print('Aumentando o volume')
  televisao.altera_volume(100)

Note that now, if your TV is turned off when you turn up the volume, you can capture the exception and finally turn on the TV before you turn up the volume.

  • I understood, but if they had a lot of methods in the TV class, like 50 or 100 and none of them could be used until the attribute turned on was True. i would have to create an exception for each of the methods. It is not possible to do this check more generally no?

  • Yes, in each method you should cast the exception if the TV was turned off, but you would not need to create an exception for each method, just an exception thrown in each method.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.