class MyDataType:
def __init__(self, x, y):
# initialize here
self.x = x
self.y = y
# Note: This function is totally optional
def __str__(self):
"""Define this 'magic method' to enable print functionality for
this object, it should return a string."""
return f"{self.x} {self.y}"
my_dt = MyDataType(10, "Hello")
# check type
print(type(my_dt)) # <class '__main__.MyDataType'>
# access/change values using '.' operator
print(my_dt.x, my_dt.y) # 10, Hello
# or print if __str__ is defined
print(my_dt) # 10, Hello
# change values
my_dt.x = 42
my_dt.x = "THis can also become a string"
# The problem is you can't define type of data or length of
# an array(list) in Python. For such situations you can
# create your own methods for inserting where you can check
# the type of data that is fed in. But will it not be a
# Data structure? Nope?
class MyDataType:
def __init__(self, x, y):
"""__init__ is another 'magic method',
which enables usage of constructor in python, more on this later."""
# raise error if type does not match
if not isinstance(x, int) or not isinstance(y, str):
raise TypeError("x should be integer and y should be string")
# define 'x' and 'y' as private variables (using '__' prefix)
# to protect them from being altered directly
self.__x = x
self.__y = y
def insert(self, x=None, y=None):
"""To check values while inserting in our custom data type.
Here we are expecting x to be a integer and y to be a string."""
if x:
if isinstance(x, int):
self.__x = x
else:
raise TypeError("Should be a integer")
if y:
if isinstance(y, str):
self.__y = y
else:
raise TypeError("Should be a String")
# define 'x' & 'y' as methods to access their value
def x(self):
return self.__x
def y(self):
return self.__y
## Create our data type
my_dt = MyDataType(10, "Hello")
# Insert values
my_dt.insert(15, "Foo")
print(my_dt.x(), my_dt.y()) # 15 Foo
my_dt.insert(20)
my_dt.insert(y="Bar")
# Access values
print(my_dt.x(), my_dt.y()) # 20 Bar
# raising error if data type is not what we expected
my_dt.insert(y=20) # TypeError: Should be a String
# There's a even better way to create custom data-types,
# that is using descriptors. We'll get to it in Chapter 7