# An usual class is a subclass of object class Human(object): # Defining class variables species = "H. Sapiens" def __init__(self, first_name, last_name): # Assign instance variables (also called attributes): self.__internal = "secret" # Private attribute (externally accessed via: human._Human_internal) self.first_name = first_name # Public attribute (externally accessed via human.first_name) self.last_name = last_name # Since last_name has not a getter/setter below # here the "=" will be dealing directly with # the instance variable # Define public instance method. # Instance method is any method that has "self" as its first argument. def say(self, speech): print(self.__build_say(speech)) # Define private instance method def __build_say(self, speech): return "{} is saying \"{}\"".format(self.full_name, speech) # Define class methods. # The class itself is passed as the first argument so # class variable can be called for instance @classmethod def get_species(cls): return cls.species # Define static methods. # This kind of method has no references for classes or instances. @staticmethod def something(): return "somthing" # Define a property for an instance variable. # It works as getter method. @property def first_name(self): return self._first_name # Define a setter method for the Human's first name. # This way when setting its value via "=", it will be using # this method rather than operating directly on the instance variable. @first_name.setter def first_name(self, name): self._first_name = name # Allow the first_name property to be deleted @first_name.deleter def first_name(self): del self._first_name # Define a virtual property (not backed by an instance variable). # This way human.full_name will be called rather than human.full_name(). @property def full_name(self): return "{0} {1}".format(self.first_name, self.last_name) # Define a setter for full_name so some logic can be applied # to the instance variables first_name and last_name. @full_name.setter def full_name(self, full_name): if not full_name: self.first_name = "" self.last_name = "" elif isinstance(full_name, str): names = full_name.split() self.first_name = names[0] self.last_name = " ".join(names[1:]) def __str__(self): return "First name: {}; Last name: {}".format(self.first_name, self.last_name) # Define a class (Developer) as subclass of other (Human) class Developer(Human): # Override the superclass method extending its behavior: def __init__(self, first_name, last_name, tech_skills=[]): # Human.__init__(self, first_name, last_name) super(Developer, self).__init__(first_name, last_name) self.tech_skills = tech_skills # Override the superclass method extending its behavior: def __str__(self): human_str = super(Developer, self).__str__() dev_str = ', '.join(self.tech_skills) return "{}; Tech skill: {}".format(human_str, dev_str) # Calling class methods: print(Human.get_species()) # Calling static methods: print(Human.something()) # Test constructor: human = Human(first_name="Tiago", last_name="Guedes") print(human.first_name) print(human.last_name) print("---") # Test virtual setter: human.full_name = "Foo Bar" print(human.first_name) print(human.last_name) print(human.full_name) print("---") # Test virtual setter(2): human.full_name = "" print(human.first_name) print(human.last_name) print(human.full_name) print("---") human.full_name = "Tiago Guedes" # Test public instance method: human.say("Travel the world they said!") # Test private instance method: print(human._Human__build_say("Travel the world they said! (private)")) # Test private attribute: print(human._Human__internal) print("---") # Test deleting a property print("After deleting human.first_name, let's try to call it again:") try: del human.first_name human.first_name except AttributeError as e: print("Error raised: {}".format(e)) print("---") print("Instatiating a developer:") human = Human(first_name="Tiago", last_name="Guedes") dev = Developer(first_name="Tiago", last_name="Guedes", tech_skills=["Ruby", "Elixir", "Python"]) print(dev.tech_skills) print(dev.first_name) print(dev.last_name) print(dev.full_name) print(human) print(dev) print("---") # Debugger: # import code; code.interact(local=dict(globals(), **locals()))