we know that :
str.format('{:+>10}', 'sometext')
will return :
'++sometext'
or :
'{:+>10}'.format('sometext') will return '++sometext'
my question, is there away to override format method of instance of a class.... i have try this:
class A:
def __format__(self, spec):
return spec.format(self)
then instantiate it :
a = A()
a.__format__('{:+>20}')
returning '+>20' how could this happen...
thanks before
In def __format__(self,spec):, spec is the format string itself. If you want to format the class using that spec, you need to specify it as a format to the content of the class instance in some way, such as:
class Value:
def __init__(self,value):
self.value = value
def __format__(self,fmt): # fmt='03' from below.
return f'Value({self.value:{fmt}})' # f'Value({self.value:03})' is evaluated.
v = Value(5)
print(f'{v:03}') # Python 3.6+
print('{:04}'.format(v)) # Python <3.6
Output:
Value(005)
Value(0005)
You could create a class like this which takes in an initial int value as the length. I tested in Python 3 and this works.
class Padded:
def __init__(self, length: int=10, pad='+'):
self.value = '{{:{}>{}}}'.format(pad, length)
def format(self, value):
return self.value.__format__(value)
a=Padded(20)
print(a.__format__('Sometext'))
#++++++++++++Sometext
Can override format this way (refered from python cookbook)
_formats = {
'ymd' : '{d.year}-{d.month}-{d.day}',
'mdy' : '{d.month}-{d.day}-{d.year}'
}
class Date:
def __init__(self,year,month,day):
self.year = year
self.month = month
self.day = day
def __format__(self,code):
fmt = _formats[code]
return fmt.format(d=self) #passed self as instance to d (Note using this d in _formats to get the attribute)
d = Date(2021,8,23)
#format method can be called from either these 2 ways
print(d.__format__('ymd'))
print(format(d,'mdy'))
#output
2021-8-23
8-23-2021
Related
I'm looking for a way to return float when class instantiated, like this :
class SMA:
"""
Simple Moving Average
fomula :
sma = (a1+a2+a3+....) / n
"""
def __init__(self,data_feed,time_period=None):
self.data_feed = data_feed
if not time_period:
self.time_period = len(self.data_feed)
else:
self.time_period = time_period
self.sma = sum(self.data_feed) / self.time_period
def __repr__(self):
return repr(self.sma)
>>> b = SMA(data_feed=[1,2,3,4],time_period=4)
>>> print(type(b))
... float
but there is something wrong because 'b' has SMA type, not float
b is the object of the class SMA, that is why it returns its class type.
to return a float value create a function
class SMA:
def __init__(self,data_feed,time_period=None):
self.data_feed = data_feed
if not time_period:
self.time_period = len(self.data_feed)
else:
self.time_period = time_period
def get_value(self):
return sum(self.data_feed) / self.time_period
b = SMA(data_feed=[1,2,3,4],time_period=4)
type(b.get_value())
__repr__ returns a printable representation of the object.
Yours SMA() is constructor for SMA class, thus b variable being its objects.
For this type of operation i recommend reading about magic methods, dunder methods.
You may try overiding str(self).
Something like:
def __str__(self):
return str(self.sma)
I want to create monad that is able to handle mathematical errors gracefully. I created something like:
from enum import Enum
class Monad(Enum):
Safe = 1
Fail = 2
class DivisionMonad:
def __init__(self, value=None, type=Monad.Safe):
self.value = value
self.type = type
def __truediv__(self, val):
if self.type == Monad.Fail:
return DivisionMonad(type=Monad.Fail)
try:
return DivisionMonad(self.value / val)
except:
return DivisionMonad(type=Monad.Fail)
def __repr__(self):
return f'< {self.value} >'
d = DivisionMonad(1)
d = d / 3
print(d.value)
print(d.type)
d = d / 0
print(d.value)
print(d.type)
But I believe this could be simpler by making the class use different methods based on the state of the Monad. Is there a way to create conditional execution of methods based on an instance attribute other than if/else statements?
Just a simple class definition withh subclasses to show inheritance
import datetime
class LibaryItem: #The base class definition
def __init__(self, t, a, i): # initialiser method
self.__Title = t
self.__Author_Artist = a
self.__ItemID = i
self.__OnLoan = False
self.DueDate = datetime.date.today()
def GetTitle(self):
return(self.__Title)
# All other Get methods go here
def Borrowing(self):
self.__OnLoan = True
self.__DueDate = self.__DueDate + datetime.timedelta(weeks = 3)
def Returning(self):
self.OnLoan = False
def PrintDetails(self):
print(self.__Title, '; ', self.__Author_Artist,'; ',end='') # end='' Appends a space instead of a newline
print(self.__ItemID, '; ', self.__OnLoan,'; ', self.__DueDate)
class Book(LibaryItem):# A subclass definition
def __init__(self, t, a, i): # Initialiser method
LibaryItem.__init__(self, t, a, i)
# This statement calls the constructor for the base class
self.__IsRequested = False
self.__RequestBy = 0
def GetIsRequested(self):
return(self.__IsRequested)
class CD(LibaryItem):
def __init__(self, t, a, i): # Initialiser method
LibaryItem.__init__(self, t, a, i)
self.__Genre = ""
def GetGenre(self):
return(self.__Genre)
def SetGenre(self, g):
self.__Genre = g
Instantiating a subclass
ThisBook = Book('Title', 'Author', 'ItemID')
ThisCD = CD('Title', 'Author', 'ItemID')
This is my problem here I don't understand why the ThisBook the object's attribute doesn't change from False its default value to True.
# Using A method
print(ThisBook.GetIsRequested())
ThisBook.IsRequested = True
print(ThisBook.GetIsRequested())
Thank you a reason to why this doesn't work would be helpful
You probably meant to do
ThisBook.__IsRequested = True
which you can't do because of name mangling. You could write another setter.
But before you dive too deeply into writing a lot of getters and setters you should be aware that the pythonic way is to not use them. Or, if additional logic is required, to use the #property decorator.
class LibaryItem:
def __init__(self, title, author, itemid): # initialiser method
self.title = title
self.author = author
self.itemid = itemid
self._onloan = False
self.duedate = datetime.date.today()
#property
def onloan(self):
return self._onloan
#onloan.setter
def onloan(self, value):
if value:
self.duedate += datetime.timedelta(weeks = 3)
self._onloan = value
def __str__(self):
return "%s; %s; %s; %s; %s" % (self.title, self.author, self.itemid, self.onloan, self.duedate)
class Book(LibaryItem):
def __init__(self, title, author, itemid):
LibaryItem.__init__(self, title, author, itemid)
self.requested = False
self.requestby = 0
and then
ThisBook = Book('Title', 'Author', 'ItemID')
print(ThisBook.requested)
ThisBook.requested = True
ThisBook.onloan = True
print(ThisBook.duedate)
You can't access a field with 2 underscores prefix like that (see What is the meaning of a single- and a double-underscore before an object name?).
You need to write a proper setter:
def SetIsRequested(self, val):
self.__IsRequested = val
What you are experiencing is the typical silliness of dynamic languages. A field on class can be set w/o being declared and the interpreter can't help you by pointing out that you've just created a new field called "IsRequested" in your class. Saves you some typing but costs you in ability of your interpreter and IDE to prevent you from messing up.
Being tired manually implementing a string representation for my classes, I was wondering if there is a pythonic way to do that automatically.
I would like to have an output that covers all the attributes of the class and the class name. Here is an example:
class Foo(object):
attribute_1 = None
attribute_2 = None
def __init__(self, value_1, value_2):
self.attribute_1 = value_1
self.attribute_2 = value_2
Resulting in:
bar = Foo("baz", "ping")
print(str(bar)) # desired: Foo(attribute_1=baz, attribute_2=ping)
This question came to mind after using Project Lombok #ToString in some Java projects.
You can iterate instance attributes using vars, dir, ...:
def auto_str(cls):
def __str__(self):
return '%s(%s)' % (
type(self).__name__,
', '.join('%s=%s' % item for item in vars(self).items())
)
cls.__str__ = __str__
return cls
#auto_str
class Foo(object):
def __init__(self, value_1, value_2):
self.attribute_1 = value_1
self.attribute_2 = value_2
Applied:
>>> str(Foo('bar', 'ping'))
'Foo(attribute_2=ping, attribute_1=bar)'
wrote this while falsetru answerred.
Its the same idea, mine is very beginner friendly in terms of reading it, his is much nicer implemented imho
class stringMe(object):
def __str__(self):
attributes = dir(self)
res = self.__class__.__name__ + "("
first = True
for attr in attributes:
if attr.startswith("__") and attr.endswith("__"):
continue
if(first):
first = False
else:
res += ", "
res += attr + " = " + str( getattr(self, attr))
res += ")"
return res
class Foo(stringMe):
attribute_1 = None
attribute_2 = None
def __init__(self, value_1, value_2):
self.attribute_1 = value_1
self.attribute_2 = value_2
bar = Foo("baz", "ping")
print(str(bar)) # desired: Foo(attribute_1=baz, attribute_2=ping)
You can use #dataclass, which automatically generates __init__(), __repr__(), __str__(), and more. You just need to add a #dataclass decorator to your class and add type annotations to the members. You can even remove your __init__() implementation then.
from dataclasses import dataclass
#dataclass
class Foo(object):
attribute_1 : str
attribute_2 : str
bar = Foo("baz", "ping")
print(str(bar)) # Prints: Foo(attribute_1='baz', attribute_2='ping')
Say I have a Graph class and a Vertex class, defined as below
Graph.py
class Graph:
def __init__(self):
self.adjacencyList = {}
def __str__(self):
return str(self.adjacencyList)
def addVetex(self,key,value):
if Vertex(key,value) not in self.adjacencyList:
self.adjacencyList[Vertex(key,value)] = []
Vertex.py
class Vertex:
def __init__(self,key,value):
self.key = key
self.value = value
def __str__(self):
return "Key: ",str(self.key)," Value: ",str(self,value)
def __hash__(self):
return self.key
if I do this:
G = Graph()
G.addVetex(1,None)
G.addVetex(2,None)
G.addVetex(1,3)
print G
It print out {<Vertex.Vertex instance at 0x110295b90>: [], <Vertex.Vertex instance at 0x110295bd8>: []} But I am expecting something like {"Key:1 Value:None":[]...}
My question is what I am doing wrong? When a diction got print out, why it does not try to call the str function of its keys/values?
Thanks.
I believe the method you want to implement to get the string you want with your current code is Vertex.__repr__, which is what the python dictionary uses to get string representations of keys.
Here's a related stackoverflow answer that sheds some light on the difference between __repr__ and __str__
Joe's answer is correct, here is the tested version of the code:
def __repr__(self):
return "Key: "+str(self.key)+" Value: "+str(self.value)
to be implemented in Vertex. Also important is that a string is given back, not a tuple as in the question.
This will do it. Note the addition of the repr method (and a little cleanup of the str method).
class Vertex:
def __init__(self,key,value):
self.key = key
self.value = value
def __str__(self):
return "{Key: "+str(self.key)+" Value: "+str(self.value)+"}"
def __hash__(self):
return self.key
def __repr__(self):
return str(self)
You might consider subclassing a dict, though, for your vertex class. You get all the benefits of a dict but can add methods to suit your needs. The simplest version of this would look like:
class Vertex(dict):
pass
You can do smth like:
class Graph(object):
def __str__(self):
return ", ".join("Key: " + str(i.key) + " Value: " + str(i.value) for i in self.adjacencyList)