So, on top of other problems, you sometimes have programming functions which arnt the same thing as maths functions. Generally speaking, an struct that has functions (which is basically what an object is), is where the function always has a starting context.
Historically before objects, you would have to mkae a function that took the A and B, so you would make a function called addthing(A, B)
, where now, we can make a function on the thign called add, so you can do A.add(B)
. Ok.. these are functions on the object
But objects can also have properties. Now some programmers will tell you you shouldnt have public things, you should use getters and setters, and then C# does something awesome to make that better: but I like public properties, so I can imagine making a 'class' (which is the definition of an object) being representing a coordinate or a vector, so i can define it to have an X and a Y, so these arn't functions but properties.
Wierd bit 1) But we want to do things sometimes a bit implicitly. like doo vector = vector_a + vector_b
that would be awesome right? Well, you can! objects inherit basic Objects, but the default __add__
function on the object doesnt know how to add nother one together, so I can implement that on my object. Theres actually tons of these default functions which are called... effectively the compile rewrites anything like x = y + z
into x = y.__add__(z)
. What else can you override? __str__
is whats called when you convert it to a string (like print(mycoord)
gets converted (effectivly) into print(str(mycoord))
which in turn is print(mycoord.__str__())
. Theres also a ton of things like comparison, meaning your objects can be sorted by lists and other cool things...
wierd bit 2) ok sometimes you want a property to actually be a function. WHAAAAAAT? We often call these 'getters and setters'. They look like a property or attribute, but they're actually a function... so..
# in a class...
@property
def x(self):
"""I'm the 'x' property."""
return self._x
# sometime later...
print(myobject.x) # <-- effectivly calls myobject.x()
now this means you can do things on the setter where you might validate the input, control how its set, maybe force it to be a particular type (not quite inline with the zen of python, but sometimes very useful).
Hope that helps!