# Object-Oriented Programming

## Classes and Instances

* Class: A bundle of data and functionality. This can be copied and modified to accomplish a wide variety of programming tasks.
    
    * A blueprint on how to build an object
        
    * Class names begin with capital letters
        
        * classes with multiple words should be UpperCamelCase
            
* Instance: a specific working copy of a class. Also referred to as an object. it is an individual object produced from the class.
    

```python
class NewDog:    #This is the class we created
    pass

fido = NewDog()     #fido and snoopy are individual instances
snoopy = NewDog()    #of the NewDog class
```

## Building Your Own Instance Methods/Functions

* If you place a function within the body of a class, that function becomes a specific method for the instances of that class
    
* It is convention to create each class inside its own file in python
    
* ```python
    class Dog:
        def bark(self):
            print("Woof!")
    
    fido = Dog()  #The instance is created
    fido.bark()    #To call the function, use dot notation 
    #Woof!
    ```
    

## Understanding **(\_\_init\_\_)**

* everytime we initialize a new object, the python interpreter calls a magic method called **init**.
    
    * The magic methods are special methods that are not meant to be called by developers but are invoked by different cues and operators that act on the object.
        
    * It is invoked when you initialize a class
        
    * You can overwrite **init** to change an object's behavior
        
    * It can be modified to take more arguments to customize the behavior of unique objects
        
    * ```python
        class Dog:
            def __init__(self, name):
                print(f"{name} is born")
        
            def bark(self):
                print("Woof!")
        
        fido = Dog()  
        #Fido is born   This happens automatically
        fido.bark()
        #Woof!
        ```
        
* Understanding Self
    
    * self is a reference to the initialized object. It is used to make the instance more unique
        
* ```python
    class Dog:
        def __init__(self, name):
            self.name = name
    
        def bark(self):
            print("Woof!")
    
    fido = Dog("Fido")
    fido.name
    #Fido
    ```
    

## Attributes and Properties

* Attribute: Variables that belong to an object
    
* Class Attributes: set outside the scope of any methods
    
* Instance Attributes: varies from 1 instance to the next
    
* You can set/change/add/and retrieve attributes suing dot notation
    
* Pyhton also has a few built-in functions to manipulate attributes
    
    * getattr(): retrieves the value of an attribute
        
    * setattrs(): changes the value of an attribute
        
    * hasattr(): checks for the presence of the attribute
        
    * delattr(): removes an attribute from a class or object
        
* Properties: Used when we need to make sure an attribute meets a certain set of criteria. These are controlled by methods
