Related article:
Transcript:
In Python, everything is an object.
Classes are objects
We have a class called Product
:
class Product:
unknown_price = "Ask for details"
def __init__(self, name, price=None):
self.name = name
self.price = price
def display_price(self):
if self.price is None:
return self.unknown_price
return f"{self.price:.2f}"
And we have a variable called duck
that points to an instance of this Product
class:
>>> duck = Product("duck")
>>> duck
<product.Product object at 0x7f3e50741fa0>
Variables point to objects, and class instances are objects.
But classes are also objects. So, we can point a variable to a class:
>>> my_class = Product
We now have a variable my_class
pointing to the Product
class:
>>> my_class
<class 'product.Product'>
And in fact, Product
is also just a variable that points to the Product
class:
>>> Product
<class 'product.Product'>
So anything that we could do with Product
, we could do with my_class
. For example, we could look-up an attribute on the Product
class by accessing either one of these two variables:
>>> my_class.unknown_price
'Ask for details'
>>> Product.unknown_price
'Ask for details'
Or we could call the my_class
variable:
>>> duck = my_class("duck")
Calling my_class
does the same thing as calling the Product
class. What do you get when you call a class? You get an instance of that class!
>>> duck
<product.Product object at 0x7f3e5076d220>
So while class instances are objects, classes are also objects. You can point variables to either class instances or classes.
Modules are objects
Modules are objects too.
So we can point variables to module objects:
>>> import math
>>> silly_math = math
We've imported the math
module and pointed the silly_math
variable to the math
module object:
>>> silly_math
<module 'math' from '/home/trey/.pyenv/versions/3.9.0/lib/python3.9/lib-dynload/math.cpython-39-x86_64-linux-gnu.so'>
And if we change the answer
attribute on silly_math
:
>>> silly_math.answer = 42
This will add a new attribute to the math
module object:
>>> silly_math.answer
42
Meaning math.answer
is now 42
also:
>>> math.answer
42
This was possible because modules are mutable objects, meaning you can add attributes to them and you can update attributes on them.
If we take math.pi
(already defined in math
module) and set it to 3
:
>>> math.pi
3.141592653589793
>>> math.pi = 3
>>> math.pi
3
math.pi
will now be 3
everywhere in our current Python process.
Note that this is a bad idea. You really shouldn't add or update attributes in other modules after you've imported them, but it's possible to do because modules are objects in Python and they're mutable objects, meaning they can be changed.
Functions are objects
Functions are even objects in Python.
We have a function called greet
:
>>> def greet(name="world"):
... """Greet a user, or the whole world."""
... print("Hello", name)
...
The one thing you normally do with a function is call it.
This function greet
can be called with one argument or with no arguments:
>>> greet()
Hello world
>>> greet("Trey")
Hello Trey
Because functions are objects, we could point another variable, f
, to our function object:
>>> f = greet
The variable f
points to the greet
function now:
>>> f
<function greet at 0x7fe7cd8619d0>
That means anything we could do with greet
, we can do with f
:
>>> f()
Hello world
Both of these variables point to the same function object.
Just like modules, classes, and class instances, functions have attributes.
There is a __defaults__
attribute that Python adds to every function. This attribute represents the default values for all arguments that that function might accept:
>>> greet.__defaults__
('world',)
That __defaults__
attribute points to a tuple that has the string world
in it, meaning if this function is called without its first argument, we'll see Hello world
:
>>> greet()
Hello world
If we wanted to be devious, we could assign the __defaults__
attribute to a different tuple:
>>> greet.__defaults__ = ('Trey',)
So if we call greet now, it's now going to say Hello Trey
, rather than Hello world
:
>>> greet()
Hello Trey
This is possible to do because functions are objects, meaning we can point other variables to them, and since they're mutable objects, we can even update the attributes that exist on functions.
Summary
In Python, everything is an object. Classes are objects, instances of classes are objects, modules are objects, and functions are objects.
Anything that you can point a variable to is an object.
from Planet Python
via read more
No comments:
Post a Comment