__init__ question


#1

Ok I want to make sure I am understanding this correctly. I think I am but there wasn’t a whole ton of explanation going on here so I am mentally trying to figure this out. Exhausting… lol

So in the code below, in order for my to create a new object, basically I have to give it a name, and age, but NOT is alive, and one can’t be created without those 2 attributes.

So to create any new object you need all the required attributes under the __init__ and all the new functions that you can call on are basically optional?



class Animal(object):
  """Makes cute animals."""
  is_alive = True
  def __init__(self, name, age):
    self.name = name
    self.age = age



#2

That is correct. When invoking an instance, there must be exactly two arguments (in this case, to match the named parameters). self is the context object into which is written the current instance. As for is_alive, we will need a class method to change that setting.


#3

Can you explain this more:

As for is_alive, we will need a class method to change that setting.

So by default every new object initiative “is_alive” e.g true?

Also - how do I specify the characteristics of name and age. What if I only want the input of age to be an int for instance of 2 characters.


#4

‘… every new object instance…’

Initially, all new objects will have that attribute set to True. We don’t actually need a class method to the change it.

>>> parrot = Animal('Polly', 6)
>>> parrot.is_alive
True
>>> parrot.is_alive = False
>>> parrot.is_alive
False
>>> 

This will not affect other instances, only this one.

In Python we do not declare types, since the interpreter handles that when parsing the data. If it is numeric, the type is cast based on the subclass, int, float, etc. Same applies to other data types. It will be up to our program to validate inputs according to desired types.


#5

Sorry that was a bad way of asking my question.
In the code below:

class Animal(object):
  """Makes cute animals."""
  is_alive = True
  def __init__(self, name, age):
    self.name = name
    self.age = age

I want to ensure age is an int, not a string. How do I make sure the input (if its not me who input it) is in fact an int not a string. Right now, I know what the program wants to do, but for an unknown user, someone could theoretically initiative a new object like:

name = Animal(SDSDSD,ASASA) which obviously is not correct but it would accept it.


#6

There are a number of ways to check if an input matches the required type. One approach is to cast the inputs to the desired type…

class Animal(object):
  """Makes cute animals."""
  is_alive = True
  def __init__(self, name, age):
    self.name = str(name)
    self.age = int(age)

Pretty much anything can be cast to string so the first assignment is not likely to raise any errors, but not everything can be cast to int so that is where an exception might be thrown.

It will take some reading and experimenting to see what we can do inside the __init__() method. We need some kind of exception handling or validation.

exception hnadling in init method python

Still have to test this, but here goes…

class Animal(object):
  """Makes cute animals."""
  is_alive = True
  def __init__(self, name, age):
    self.name = str(name)
    try:
      self.age = int(age)
    except ValueError:
      self.age = None

With a little refining…

>>> class Animal(object):
  """Makes cute animals."""
  is_alive = True

  def set_age(name):
    try:
      return int(input("Enter the age of {}: ".format(name)))
    except ValueError:
      return Animal.set_age(name)

  def __init__(self, name, age):
    self.name = str(name)
    try:
      self.age = int(age)
    except ValueError:
      self.age = Animal.set_age(self.name)

  def __repr__(self):
    return "Animal name: {}\n\
 Animal age: {}".format(self.name, self.age)
>>> dog = Animal('Snoopy', 'six')
Enter the age of Snoopy: 6
>>> cat = Animal('Tom', 'five')
Enter the age of Tom: 'five'
Enter the age of Tom: 5
>>> dog
Animal name: Snoopy
 Animal age: 6
>>> cat
Animal name: Tom
 Animal age: 5
>>> 

#7

Now that some groundwork has been layed let’s explore this example in closer detail. Immediately we see that both arguments are seen by the interpreter as identifiers. That would raise an exception right off the bat. Fatal error, unless of course those variables actually did exist. That is how Python will deal with that particular input.

It will take the advice of someone with expertise beyond what we’ve touched on here to solve the problem of undefined identifier exceptions. I suspect we would need some sort of base exception handling to catch the initial call. Not something I’m familiar with so bear with the guessing. So far we seem to be on the right path, as exception handling goes. It’s a slow journey.

Take for example what happens if an instance invokes a class method…

>>> dog.set_age()
Enter the age of Animal name: Snoopy
 Animal age: 6: 5
5
>>> dog
Animal name: Snoopy
 Animal age: 6
>>> 

Clearly there is still more work to be done. No harm, no foul, at least.

It’s clear that name took on a meaning from an outer scope since there is not a name parameter, and that name is in the context of the dog object. Again, Being littIe more than a handyman, I will defer to anyone wiser than me in regard to this level of architecture.


#8

In the Animal class, we have defined is_alive as a class variable by assigning it a value outside all the methods. That variable is shared by all instances of Animal.

One technique, among several, for accessing it is to refer to it as Animal.is_alive. This can be done in a local or global context, even if no instances of the class have been created.

If we change the value of the class variable is_alive, it is changed for all instances, since there is only one copy of it.

We can create an instance variable with the same name. If, within some method, self refers to the current instance, this will either create an is_alive instance variable or change its value if it already exists …

    self.is_alive = False

You can even have a local variable by the same name, either by using it as the name of a method parameter, or performing an assignment within a method without dot notation, as follows …

    is_alive = False

Be careful with the above. If you have several variables with the same name, it is easy to make mistakes, resulting in buggy code.

Validating the values of arguments passed to functions or methods is a good practice, and @mtf has demonstrated a good way of doing it with a ValueError. In fact, once you have verified that an argument has a valid type, you can check for acceptable values of that type and raise a ValueError if an unacceptable value has been passed. For example, in some situations, you may want to reject negative numbers even if an argument is of the correct type. An Animal cannot have a negative number of legs.

See the following for lots of Python 3 documentation on this topic …


#9

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.