Python - Reflection

Hello there, future Python wizards! Today, we're going to embark on an exciting journey into the magical world of Python reflection. Don't worry if you've never heard of reflection before - by the end of this tutorial, you'll be reflecting like a pro! So, grab your wands (I mean, keyboards), and let's dive in!

Python - Reflection

What is Reflection?

Before we start, let's understand what reflection is. In programming, reflection is like having a mirror that allows a program to examine, introspect, and modify its own structure and behavior at runtime. It's like giving your code the ability to look at itself and say, "Hey, what am I made of?" Pretty cool, right?

The type() Function

Let's start with the type() function. This is like asking an object, "What are you?"

# Example 1: Using type()
x = 5
y = "Hello"
z = [1, 2, 3]

print(type(x))  # Output: <class 'int'>
print(type(y))  # Output: <class 'str'>
print(type(z))  # Output: <class 'list'>

In this example, we're asking different variables what they are. The type() function tells us that x is an integer, y is a string, and z is a list. It's like having a conversation with your variables!

The isinstance() Function

Next up is isinstance(). This function is like asking, "Are you a part of this family?"

# Example 2: Using isinstance()
x = 5
y = "Hello"

print(isinstance(x, int))    # Output: True
print(isinstance(y, str))    # Output: True
print(isinstance(x, str))    # Output: False

Here, we're checking if x is an instance of int (which it is), if y is an instance of str (which it is), and if x is an instance of str (which it isn't). It's like asking someone if they're a member of a particular club!

The issubclass() Function

Moving on to issubclass(). This is like asking, "Are you related to this family?"

# Example 3: Using issubclass()
class Animal:
    pass

class Dog(Animal):
    pass

print(issubclass(Dog, Animal))  # Output: True
print(issubclass(Animal, Dog))  # Output: False

In this example, we're checking if Dog is a subclass of Animal (which it is), and if Animal is a subclass of Dog (which it isn't). It's like asking if a poodle is a type of dog, versus asking if all dogs are poodles!

The callable() Function

Now, let's talk about callable(). This function checks if an object can be called (like a function).

# Example 4: Using callable()
def greet():
    print("Hello!")

x = 5

print(callable(greet))  # Output: True
print(callable(x))      # Output: False

Here, we're checking if greet (which is a function) is callable, and if x (which is just a number) is callable. It's like asking, "Can I use you as a function?"

The getattr() Function

getattr() is like a polite way of asking an object for one of its attributes.

# Example 5: Using getattr()
class Person:
    name = "Alice"
    age = 30

p = Person()
print(getattr(p, "name"))  # Output: Alice
print(getattr(p, "job", "Unemployed"))  # Output: Unemployed

In this example, we're asking our Person object for its name attribute, which it has. We're also asking for a job attribute, which it doesn't have, so we provide a default value of "Unemployed".

The setattr() Function

setattr() is like giving an object a new attribute or changing an existing one.

# Example 6: Using setattr()
class Car:
    color = "red"

my_car = Car()
print(my_car.color)  # Output: red

setattr(my_car, "color", "blue")
print(my_car.color)  # Output: blue

setattr(my_car, "brand", "Toyota")
print(my_car.brand)  # Output: Toyota

Here, we're changing the color of our car from red to blue, and then giving it a new brand attribute.

The hasattr() Function

hasattr() is like asking an object, "Do you have this attribute?"

# Example 7: Using hasattr()
class Book:
    title = "Python for Beginners"
    pages = 200

my_book = Book()
print(hasattr(my_book, "title"))   # Output: True
print(hasattr(my_book, "author"))  # Output: False

In this example, we're checking if our Book object has a title attribute (which it does) and an author attribute (which it doesn't).

The dir() Function

Finally, let's look at dir(). This function is like asking an object, "What can you do?"

# Example 8: Using dir()
class Dog:
    def __init__(self, name):
        self.name = name

    def bark(self):
        print("Woof!")

my_dog = Dog("Buddy")
print(dir(my_dog))

This will output a list of all attributes and methods of our Dog object, including name and bark, as well as some built-in attributes that all objects have.

Reflection Functions Summary

Here's a quick summary of all the reflection functions we've covered:

Function Purpose
type() Returns the type of an object
isinstance() Checks if an object is an instance of a specified class
issubclass() Checks if a class is a subclass of another class
callable() Checks if an object is callable (like a function)
getattr() Gets the value of an object's attribute
setattr() Sets the value of an object's attribute
hasattr() Checks if an object has a specific attribute
dir() Returns a list of an object's attributes and methods

And there you have it, folks! You've just taken your first steps into the world of Python reflection. Remember, these tools are like having a conversation with your code. They allow your programs to examine themselves and make decisions based on what they find. It's a powerful feature that can make your code more flexible and dynamic.

As you continue your Python journey, you'll find many more ways to use reflection to create smarter, more adaptable programs. Keep practicing, keep exploring, and most importantly, keep having fun with Python!

Credits: Image by storyset