For the following code I would like to use a structure in order to not have to give 2 values for each element min and max and also I would like to have a container if exists to can give one value and the other one to remain None. For instance power to have only min element. So for power to have a container with 2 elements (for min and max) and same for temperature. How is that possible in python ? please help, thanks!
def result_final(
power_min,
power_max,
temperature_min,
temperature_max
) -> str:
def _result_min(value) -> str:
return "<min>" "<value>" + str(value) + "</value>" + "</min>"
def _result_max(value) -> str:
return "<max>" "<value>" + str(value) + "</value>" +" </max>"
def _measure_result(unit_id, min_value, max_value) -> str:
return (
"<measure_result>"
"<unit-id>" + str(unit_id) + "</unit-id>"
"" + _result_min(min_value) + ""
"" + _result_max(max_value) + ""
"</measure_result>"
)
def _stats(object, min_value, max_value) -> str:
return (
"<stats>"
"<object>" + object + "</object>"
"" + _measure_result(0, min_value, max_value) + ""
"" + _measure_result(1, min_value, max_value) + ""
"</stats>"
)
content = (
'<result-stats>'
"" + _stats("POWER", power_min, power_max) + ""
"" + _stats("TEMPERATURE", temperature_min, temperature_max) + ""
"</result-stats>"
)
return content
x = result_final(power_min = 12, power_max = 125, temperature_min = 12, temperature_max = 12)
print(x)
I'd suggest just using tuples for each min/max pair:
from typing import Optional, Tuple
Stats = Tuple[Optional[int], Optional[int]] # min, max
def result_final(power: Stats, temperature: Stats) -> str:
def _result_min(value: Optional[int]) -> str:
return "" if value is None else f"<min><value>{value}</value></min>"
def _result_max(value: Optional[int]) -> str:
return "" if value is None else f"<max><value>{value}</value></max>"
def _measure_result(unit_id: int, value: Stats) -> str:
min_value, max_value = value
return (
"<measure_result>"
f"<unit-id>{unit_id}</unit-id>"
f"{_result_min(min_value)}"
f"{_result_max(max_value)}"
"</measure_result>"
)
def _stats(obj: str, value: Stats) -> str:
return (
"<stats>"
f"<object>{object}</object>"
f"{_measure_result(0, value)}"
f"{_measure_result(1, value)}"
"</stats>"
)
return (
"<result-stats>"
f"{_stats('POWER', power)}"
f"{_stats('TEMPERATURE', temperature)}"
"</result-stats>"
)
print(result_final((12, 125), (12, 12)))
I suggest you take a look at Python dataclasses.
from dataclasses import dataclass
#dataclass
class MyContainer:
power_min: int = None
power_max: int = None
temperature_min: int = None
temperature_max: int = None
The dataclass wrapper provides a convenient way to define a class that just stores some data. dataclasses is in the standard library (i.e., you do not need to install anything).
The class I defined, by default, uses None for all attributes. Or you can specify values for the attributes you need.
a_container = MyContainer(power_max=5, temperature_min=3)
I also suggest to choose a better name than MyContainer: I used that because I did not know what you were trying to achieve!
You can also decide to define two separate classes for TemperatureExtremes and PowerExtremes, if that makes more sense for you!
Related
I've defined the following dataclass:
"""This module declares the SubtitleItem dataclass."""
import re
from dataclasses import dataclass
from time_utils import Timestamp
#dataclass
class SubtitleItem:
"""Class for storing all the information for
a subtitle item."""
index: int
start_time: Timestamp
end_time: Timestamp
text: str
#staticmethod
def load_from_text_item(text_item: str) -> "SubtitleItem":
"""Create new subtitle item from their .srt file text.
Example, if your .srt file contains the following subtitle item:
```
3
00:00:05,847 --> 00:00:06,916
The robot.
```
This function will return:
```
SubtitleItem(
index=3,
start_time=Timestamp(seconds=5, milliseconds=847),
end_time=Timestamp(seconds=6, milliseconds=916),
text='The robot.')
```
Args:
text_item (str): The .srt text for a subtitle item.
Returns:
SubtitleItem: A corresponding SubtitleItem.
"""
# Build regex
index_re = r"\d+"
timestamp = lambda prefix: rf"(?P<{prefix}_hours>\d\d):" + \
rf"(?P<{prefix}_minutes>\d\d):" + \
rf"(?P<{prefix}_seconds>\d\d)," + \
rf"(?P<{prefix}_milliseconds>\d\d\d)"
start_timestamp_re = timestamp("start")
end_timestamp_re = timestamp("end")
text_re = r".+"
complete_re = f"^(?P<index>{index_re})\n"
complete_re += f"{start_timestamp_re} --> {end_timestamp_re}\n"
complete_re += f"(?P<text>{text_re})$"
regex = re.compile(complete_re)
# Match and extract groups
match = regex.match(text_item)
if match is None:
raise ValueError(f"Index item invalid format:\n'{text_item}'")
groups = match.groupdict()
# Extract values
index = int(groups['index'])
group_items = filter(lambda kv: kv[0].startswith("start_"), groups.items())
args = { k[len("start_"):]: int(v) for k, v in group_items }
start = Timestamp(**args)
group_items = filter(lambda kv: kv[0].startswith("end_"), groups.items())
args = { k[len("end_"):]: int(v) for k, v in group_items }
end = Timestamp(**args)
text = groups['text']
if start >= end:
raise ValueError(
f"Start timestamp must be later than end timestamp: start={start}, end={end}")
return SubtitleItem(index, start, end, text)
#staticmethod
def _format_timestamp(t: Timestamp) -> str:
"""Format a timestamp in the .srt format.
Args:
t (Timestamp): The timestamp to convert.
Returns:
str: The textual representation for the .srt format.
"""
return f"{t.get_hours()}:{t.get_minutes()}:{t.get_seconds()},{t.get_milliseconds()}"
def __str__(self):
res = f"{self.index}\n"
res += f"{SubtitleItem._format_timestamp(self.start_time)}"
res += " --> "
res += f"{SubtitleItem._format_timestamp(self.end_time)}\n"
res += self.text
return res
... which I use in the following test:
import unittest
from src.subtitle_item import SubtitleItem
from src.time_utils import Timestamp
class SubtitleItemTest(unittest.TestCase):
def testLoadFromText(self):
text = "21\n01:02:03,004 --> 05:06:07,008\nTest subtitle."
res = SubtitleItem.load_from_text_item(text)
exp = SubtitleItem(
21, Timestamp(hours=1, minutes=2, seconds=3, milliseconds=4),
Timestamp(hours=5, minutes=6, seconds=7, milliseconds=8),
"Test subtitle."
)
self.assertEqual(res, exp)
This test fails, but I don't understand why.
I've checked with the debugger: exp and res have exactly the same fields. The Timestamp class is another separate dataclass. I've checked equality per field manually in the debugger, all fields are identical:
>>> exp == res
False
>>> exp.index == res.index
True
>>> exp.start_time == res.start_time
True
>>> exp.end_time == res.end_time
True
>>> exp.text == res.text
True
Furthermore, asdict() on each object returns identical dictionaries:
>>> dataclasses.asdict(exp) == dataclasses.asdict(res)
True
Is there something I'm misunderstanding regarding the implementation of the equality operator with dataclasses?
Thanks.
EDIT: my time_utils module, sorry for not including that earlier
"""
This module declares the Delta and Timestamp classes.
"""
from dataclasses import dataclass
#dataclass(frozen=True)
class _TimeBase:
hours: int = 0
minutes: int = 0
seconds: int = 0
milliseconds: int = 0
def __post_init__(self):
BOUNDS_H = range(0, 100)
BOUNDS_M = range(0, 60)
BOUNDS_S = range(0, 60)
BOUNDS_MS = range(0, 1000)
if self.hours not in BOUNDS_H:
raise ValueError(
f"{self.hours=} not in [{BOUNDS_H.start, BOUNDS_H.stop})")
if self.minutes not in BOUNDS_M:
raise ValueError(
f"{self.minutes=} not in [{BOUNDS_M.start, BOUNDS_M.stop})")
if self.seconds not in BOUNDS_S:
raise ValueError(
f"{self.seconds=} not in [{BOUNDS_S.start, BOUNDS_S.stop})")
if self.milliseconds not in BOUNDS_MS:
raise ValueError(
f"{self.milliseconds=} not in [{BOUNDS_MS.start, BOUNDS_MS.stop})")
def _to_ms(self):
return self.milliseconds + 1000 * (self.seconds + 60 * (self.minutes + 60 * self.hours))
#dataclass(frozen=True)
class Delta(_TimeBase):
"""A time difference, with milliseconds accuracy.
Must be less than 100h long."""
sign: int = 1
def __post_init__(self):
if self.sign not in (1, -1):
raise ValueError(
f"{self.sign=} should either be 1 or -1")
super().__post_init__()
def __add__(self, other: "Delta") -> "Delta":
self_ms = self.sign * self._to_ms()
other_ms = other.sign * other._to_ms()
ms_sum = self_ms + other_ms
sign = -1 if ms_sum < 0 else 1
ms_sum = abs(ms_sum)
ms_n, s_rem = ms_sum % 1000, ms_sum // 1000
s_n, m_rem = s_rem % 60, s_rem // 60
m_n, h_n = m_rem % 60, m_rem // 60
return Delta(hours=h_n, minutes=m_n, seconds=s_n, milliseconds=ms_n, sign=sign)
#dataclass(frozen=True)
class Timestamp(_TimeBase):
"""A timestamp with milliseconds accuracy. Must be
less than 100h long."""
def __add__(self, other: Delta) -> "Timestamp":
ms_sum = self._to_ms() + other.sign * other._to_ms()
ms_n, s_rem = ms_sum % 1000, ms_sum // 1000
s_n, m_rem = s_rem % 60, s_rem // 60
m_n, h_n = m_rem % 60, m_rem // 60
return Timestamp(hours=h_n, minutes=m_n, seconds=s_n, milliseconds=ms_n)
def __ge__(self, other: "Timestamp") -> bool:
return self._to_ms() >= other._to_ms()
class Timestamp:
def __init__( self, hours=0, minutes=0, seconds=0, milliseconds=0 ):
self.ms = ((hours*60+minutes)*60+seconds)*1000+milliseconds
def get_hours(self):
return self.ms // (60*60*1000)
def get_minutes(self):
return (self.ms // (60*1000)) % 60
def get_seconds(self):
return (self.ms // 1000) % 60
def get_milliseconds(self):
return self.ms % 1000
def __add__(self,other):
return Timestamp(milliseconds=self.ms + self.other)
def __eq__(self,other):
return self.ms == other.ms
def __lt__(self,other):
return self.ms < other.ms
def __le__(self,other):
return self.ms <= other.ms
... your code ...
text = "21\n01:02:03,004 --> 05:06:07,008\nTest subtitle."
res = SubtitleItem.load_from_text_item(text)
exp = SubtitleItem(
21, Timestamp(hours=1, minutes=2, seconds=3, milliseconds=4),
Timestamp(hours=5, minutes=6, seconds=7, milliseconds=8),
"Test subtitle."
)
print(res)
print(exp)
print(res==exp)
Produces:
21
1:2:3,4 --> 5:6:7,8
Test subtitle.
21
1:2:3,4 --> 5:6:7,8
Test subtitle.
True
with no assert exception.
Okay, I think I found what's going wrong here.
First, I made a mistake when I reported the issue before: in the unit test, exp.start_time != res.start_time and exp.end_time != res.end_time. Sorry about that. That narrows down the issue to comparison of timestamps.
My sources are in project/src/, the test that fails is in project/tests/. To make source modules accessible to the test, I had to add the source directory to PYTHONPATH:
$ PYTHONPATH=src/ python -m unittest discover -s tests/ -v
In the unit test, even though res.start_time and end.start_time do have the same fields, they do not have the same type:
>>> print(type(res.start_time), type(exp.start_time))
<class 'time_utils.Timestamp'> <class 'src.time_utils.Timestamp'>
I've added a new post with a minimally reproducible example, and more details about the file structure here: Minimally reproducible example.
I am trying to design a spreadsheet app. I have been able to come up with a class for my Index which is typically the point consisting of row, col. I want to be able to assign a value to the point. The challenge is I am unable to update the value for that cell.
This is what I tried so far
models.py
class Index(NamedTuple):
row: int
"""The row (y-coordinate)"""
col: int
"""The column (x-coordinate)"""
val: str = None
#property
def column_label(self):
nreps = (self.col // 26) + 1
char = chr(ord("A") + self.col % 26)
return nreps * char
#property
def row_label(self):
return str(self.row + 1)
def __str__(self):
if self.val:
return f"{self.val}"
return f"{self.column_label}{self.row_label}"
app.py
class App:
def set(self, index, raw):
"""index (Index): the cell to update
raw (str): the raw string
"""
index._replace(val=raw)
Tried the above, but the value for that cell even after assigning it in the set() is still None. What is the best approach to assign a value for that index ?
I might be missing something but cant you just do
index.val = raw
instead of
index._replace(val=raw)
Again, I am not sure if I understand correctly but is a working example with just your index class:
class Index():
row: int
"""The row (y-coordinate)"""
col: int
"""The column (x-coordinate)"""
val: str = None
#property
def column_label(self):
nreps = (self.col // 26) + 1
char = chr(ord("A") + self.col % 26)
return nreps * char
#property
def row_label(self):
return str(self.row + 1)
def __str__(self):
if self.val:
return f"{self.val}"
return f"{self.column_label}{self.row_label}"
d = Index()
d.val = 2
print(d.val)
d.val = 100
print(d.val)
output
2
100
I'd like to say my English is second language and sorry for any inconvenience to read or understand my post.
I will explain what kind of code I produced first,
So I created my class function using the code below
class Histogram:
def __init__(self, range , max_mark):
self.__range = range
self.__max_mark = max_mark
self.__occurrence_list = [0] * self.__range
def get_range(self):
return self.__range
def set_range(self, value):
self.__range = value
def get_max_mark(self):
return self.__max_mark
def set_max_mark(self, value):
self.__max_mark = value
def get_occurrence_list(self):
return self.__occurrence_list
def append_marks(self, value):
if value > self.__max_mark:
return 'value should be bigger than max mark'
else:
new = self.__occurrence_list[value] += 1
And What I want to do is printing a new strings by using the list which I got from the code below.
For example,
If I put
a1 = Histogram(10, 9)
a1.append_marks(8)
print(a1.get_occurrence_list())
the result is
[0, 0, 0, 0, 0, 0, 0, 0, 1, 0]
Now, I want to create a string which shows index number and how many numbers they have.
For example,
the given list shows 0 in each index but not in index 8
So I would like to create..
0: 0
1: 0
2: 0
...
8: 1
9: 0
Something like this.
So now I have a question,
But if I introduce new function which I would say 'get_string()' and using two parameters, which would be 'self' and other value.
How can I recall the list I've got from the last to the new function?
What would be the code after
def get_string(self, other):
If I want to create something like the string above?
Your object's property will be available in your new method. Code below should print your list as you described.
for index, item in self.__occurrence_list.enumerate():
print (str(index) + ':' + str(item))
You may need to revisit the Method, append_marks(self, value). Ideally that Method should have read:
def append_marks(self, value):
if value > self.__max_mark:
return 'value should be bigger than max mark'
else:
# YOU SHOULDN'T DO new = self.__occurrence_list[value] += 1
# RATHER JUST DO: self.__occurrence_list[value] += 1
self.__occurrence_list[value] += 1
# new = self.__occurrence_list[value] += 1 #<= WITHOUT new =...
The get_string() Method could be implemented thus:
def get_string(self):
outString = ""
if self.__occurrence_list:
for key, val in enumerate(self.__occurrence_list):
outString += str(key) + ":" + str(val) + "\n"
return outString
Thus your Class could look something like this:
class Histogram:
def __init__(self, range , max_mark):
self.__range = range
self.__max_mark = max_mark
self.__occurrence_list = [0] * self.__range
def get_range(self):
return self.__range
def set_range(self, value):
self.__range = value
def get_max_mark(self):
return self.__max_mark
def set_max_mark(self, value):
self.__max_mark = value
def get_occurrence_list(self):
return self.__occurrence_list
def append_marks(self, value):
if value > self.__max_mark:
return 'value should be bigger than max mark'
else:
self.__occurrence_list[value] += 1
def get_string(self):
outString = ""
if self.__occurrence_list:
for key, val in enumerate(self.__occurrence_list):
outString += str(key) + ":" + str(val) + "\n"
return outString
a1 = Histogram(10, 9)
a1.append_marks(8)
a1.append_marks(8)
a1.append_marks(8)
a1.append_marks(8)
a1.append_marks(8)
a1.append_marks(8)
print(a1.get_occurrence_list())
print(a1.get_string())
class Unit:
def init(self, _chassisId, _unitNo, _interface):
self.chassisId = _chassisId
self.unitNo = _unitNo
self.interface = _interface
def getInterface(self):
return self.interface
#staticmethod
def parse(elem):
unitList = elem.find(UNIT+LIST)
chassisList = []
for unit in unitList.findall(UNIT):
try:
unitNumber = unit.find(UNIT_NUMBER).text
interface = unit.find(INTERFACE)
interface = ""
chassisIdElem = unit.find(CHASSIS_ID)
chassisId = ""
if chassisIdElem is not None:
chassisId = unit.find(CHASSIS_ID).text
elif unit.find(BURNED_IN_MAC) is not None:
chassisId = unit.find(BURNED_IN_MAC).text
chassisId = chassisId.replace(".", "").replace(":", "").upper()
chassis = Unit(chassisId, interface, unitNumber)
chassisList.append(chassis)
except Exception as e:
print "Unit details not found", e
return chassisList
def getChassisId(self):
return self.chassisId
def __str__(self):
str = "\n"
str += "\nUnit Details:- "
len = str.__len__();
str += "\n"
for i in range(1,len-1):
str += "-"
str += "\nUnit: " + self.unitNo
str += "\nChassis Id: " + self.chassisId
str += "\nInterfaces: " + self.interfaces
return str
def __add__(self, other):
return str(self) + other
def __radd__(self, other):
return other + str(self)
class Interface:
def init(self, _linkState, _interfaceName):
self.linkState = _linkState
self.interfaceName = _interfaceName
#staticmethod
def parse(elem):
prefix = Device.getPrefix(elem.tag)
interfaceList = elem.find(INTERFACE + LIST)
interfaceNameTag = eval(prefix + "_INTERFACE_NAME")
linkStateTag = eval(prefix + "_LINK_STATE")
interfaces = []
for interface in interfaceList.findall(INTERFACE):
try:
interfaceName = interface.find(interfaceNameTag).text
linkStateElem = interface.find(LINK_STATE)
linkState = ""
if linkStateElem is not None:
linkState = interface.find(LINK_STATE).text
elif interface.find(LINE_PROTOCOL) is not None:
linkState = interface.find(LINE_PROTOCOL).text
interface = Interface(linkState, Name)
interfaces.append(interface)
except Exception as e:
print "Interface details not found", e
return interfaces
def getLinkState(self):
return self.linkState
def getInterfaceName(self):
return self.interfaceName
def __str__(self):
str = "\n"
str += "\nInterface Details:- "
len = str.__len__();
str += "\n"
for i in range(1,len-1):
str += "-"
str += "\nLink State: " + self.linkState
str += "\nInterface Name: " + self.interfaceName
return str
def __add__(self, other):
return str(self) + other
def __radd__(self, other):
return other + str(self)
You haven't shown us the call to getInterfaceName() that causes the error, which makes it harder to help you.
However, I'll guess that the call looks something like this:
something = Interface.getInterfaceName()
You can't do it that way. You must create an instance of Interface, and then call its .getInterfaceName() method:
myInterface = Interface()
something = myInterface.getInterfaceName()
import math
EMPTY = '-'
def is_between(value, min_value, max_value):
""" (number, number, number) -> bool
Precondition: min_value <= max_value
Return True if and only if value is between min_value and max_value,
or equal to one or both of them.
>>> is_between(1.0, 0.0, 2)
True
>>> is_between(0, 1, 2)
False
"""
return value >= min_value and value <= max_value
# Students are to complete the body of this function, and then put their
# solutions for the other required functions below this function.
def game_board_full(cells):
""" (str) -> bool
Return True if no EMPTY in cells and else False
>>> game_board_full ("xxox")
True
>>> game_board_full ("xx-o")
False
"""
return "-" not in cells
def get_board_size (cells):
""" (str) -> int
Return the square root of the length of the cells
>>>get_board_size ("xxox")
2
>>>get_board_size ("xoxoxoxox")
3
"""
sqrt_cell= len(cells) ** 0.5
return int(sqrt_cell)
def make_empty_board (size):
""" (int) -> str
Precondition: size>=1 and size<=9
Return a string for storing information with the size
>>>make_empty_board (2)
"----"
>>>make_empty_board (3)
"---------"
"""
return "-" *size ** 2
def get_position (row_index,col_index,size):
""" (int,int,int) -> int
Precondition:size >=col_index and size >= row_index
Return the str_index of the cell with row_index,col_index and size
>>>get_position (2,2,4)
5
>>>get_position (3,4,5)
13
"""
str_index = (row_index - 1) * size + col_index - 1
return str_index
def make_move( symbol,row_index,col_index,game_board):
"""(str,int,int,str) -> str
Return the resultant game board with symbol,row_index,col_index and game_board
>>>make_move("o",1,1,"----")
"o---"
>>>make_move("x"2,3,"---------")
"-----x---"
"""
length=len(game_board)
size=len(cells) ** 0.5
str_index = (row_index - 1) * size + col_index - 1
return "-"*(str_index-1)+symbol+"-"*(length-str_index)
def extract_line (cells,direction,cells_num):
""" (str,str,int) -> str
Return the characters of a specified row with cells, direction and cells_num
>>>extract_line ("xoxoxoxox","across",2)
"oxo"
>>>extract_line ("xoxo","up_diagonal","-")
"xo"
"""
num=cells_num
s=cells
size= get_board_size (cells)
if direction=="across":
return s[(num-1)* size : num*size]
elif direction=="down":
return s[num-1:size **2:size]
elif direction=="up_diagonal":
return s[(size-1)*size:size-2:1-size]
elif direction=="down_diagonal":
return s[0:size*2:size+1]
NameError: name 'cells' is not defined
I don't know how to define cells because it is a parameter.
You have NO cells parameter in
def make_move( symbol,row_index,col_index,game_board):
Next time read the error message carefully so you know in which code line you have a problem.
I find that you have referred to the variable cells in your make_move function without declaration, maybe you should define it in the arguments list.
By the way, you MUST put up all your traceback or it's difficult for all of us to find out the problem.