I have a header file which describes the format of binary data stored. This file has fields like DTYPE
for datatype, NMEMB
for number of members, NFILE
for number of files etc.
In python i am parsing the header and using class structure to easily access them later.
class Header:
def __init__(self,path:str):
self.DTYPE = foo1() #parsing DTYPE, typical value: '<f8'
self.NMEMB = foo2() #parsing NMEMB, typical value: an integer
self.NFILE = foo3() #parsing NFILE, typical value: an integer
Later in other files i can use it as
h = Header("\path\to\header.txt")
nfile = h.NFILE
The DTYPE
has further substructures.
<
for little endian, >
for big endian and =
for machine endian).f
for float, i
for integer).f8
means 8-byte float or double, f4
means 4-byte float)So to further access them, i used another class representation.
class _DTYPE:
def __init__(self,dtype:str): # input dtype = '<f8'
self.rawString = dtype # get '<f8'
self.endianness = dtype[0] # get '<'
self.character = dtype[1] # get 'f'
self.bytewidth = dtype[2] # get '8'
class Header:
def __init__(self,path:str):
self.DTYPE = _DTYPE(foo1()) # foo1() returns '<f8'
self.NMEMB = foo2()
self.NFILE = foo3()
Later i use it as
h = Header("\path\to\header.txt")
char = h.DTYPE.character # returns 'f'
width = h.DTYPE.bytewidth # returns '8'
raw = h.DTYPE.rawString # returns '<f8'
However, for better code structure i want to get the raw string with the following syntax for user.
raw = h.DTYPE # It returns reference to object. i want to get '<f8'.
But python returns the address for _DTYPE
object as expected like "<main._DTYPE object at 0x7f5742dcbe50>".
QUESTION Is it possible to wire python class in a way that if i don't use dot notation it should give me a value and if i use dot notation it should switch to class object and give me access to further subclass members?
This is possible in other languages like C#
. Also python does similar behaviours internally, as everything in python is an object. For example say in a string.
text="Some string"
a=text
b=text.upper()
Here i can use just text
to get the value it holds (not reference to/address of some str
object) and i can also use dot notation to access members of the str
class instanced as text
.
Is there any magic methods for this purpose? If not is it probable that they add this feature - "Give a magic method to return something instead of class address when not using dot."
Appreciate your help. Thanks for your time :)
EDIT 1:
The suggested magic functions like __str__
or __repr__
only works for print()
function. How to get that to a variable for further processing or what if i would like to return a integer when not using dot.
EDIT 2:
for clarification, I want the user to only type syntax h.DTYPE
to get the raw string as <f8
(first goal). Or if user wants, user can access further processed valued by using dot notation as h.DTYPE.character
(second goal). The implementation i mentioned to use another class solved the second goal at the cost of first goal. The former syntax now returns address instead of raw text.
I'm going to paraphrase your question. If this is not what you seek, let me know.
Problem:
In some cases I would like to get an instance field value back when I reference the instance. I recognize that many time I want to get the address of the instance so I can reference members of the instance or copy it or what have you. Specifically, in certain situations, I would like:
raw = h.DTYPE
To set
raw
to the value of a selected instance memberrawString
. However, it is also critical that I can still reference instance members like:
raw = h.DTYPE.rawString
Solution:
The way I would likely proceed is by overriding __call__()
. This will allow you to do "something" if your instance variable is "called" as if were a method like:
raw = h.DTYPE()
Here is a proof of concept:
class _Dtype:
def __init__(self,dtype:str): # input dtype = '<f8'
self.rawString = dtype # get '<f8'
self.endianness = dtype[0] # get '<'
self.character = dtype[1] # get 'f'
self.bytewidth = dtype[2] # get '8'
def __call__(self):
return self.rawString
class Header:
def __init__(self,path:str):
self.DTYPE = _Dtype("<f8")
self.NMEMB = "foo"
self.NFILE = "bar"
header = Header("")
test = header.DTYPE() ## <--- Calling your instance
test2 = header.DTYPE.rawString ## <--- Referencing your instance
print(test, test2)
This will set test
and test2
to "<f8"
and then print them giving you:
<f8 <f8