I am using Behave framework
I want to implement the follwoing two steps:
my.feature
And context.ball in element 1 is between low and high
And context.cube in element 2 is not equal green and red
implement:
my.py
#then(u'context.<what to write here?> in element {element:d} is between {a} and {b}
#then(u'context.<what to write here?> in element {element:d} is not equal {a} and {b}
def then_who_relation_a_and_b(
context: Context,
element int,
a: str,
b: str,
):
????
how to implement here context.val to accept any mane?
no idea how to implement this
#then(u'context.val in element {element:d} is between {low} and {high}')
def then_val_in_element_is_between(context: Context, element: int, low: int, high: int):
assert low <= context.val[element] <= high
#then(u'context.val in element {element:d} is not equal {value1} and {value2}')
def then_val_in_element_is_not_equal(context: Context, element: int, value1: str, value2: str):
assert context.val[element] not in (value1, value2)
I just made an assumption that context.val is a list and you are trying to access the element of the list by giving the element number, you can adjust the implementation as per your requirement
UPDATE:
As an answer to the question you've asked in the comment below, you can use the | (pipe) operator to define multiple step expressions that should be handled by the same function.
Example:
#then(u'context.val in element {element:d} is between {low} and {high}'
u'| context.val in element {element:d} is not equal {value1} and {value2}')
def then_val_in_element(context: Context, element: int, low: int=None, high: int=None, value1: str=None, value2: str=None):
if low is not None and high is not None:
assert low <= context.val[element] <= high
elif value1 is not None and value2 is not None:
assert context.val[element] not in (value1, value2)
the function then_val_in_element() will handle both step expressions. The parameters low, high, value1 and value2 are optional to cater for both step expressions. Inside the function, you can use if-else statement to check which step expression is being executed and perform the necessary assert statement.
UPDATE:
You can use a regular expression in the step definition to match both "context.ball" and "context.cube" as the name of the variable. Here is an example of how you could modify the step definition:
import re
#then(u'context.(ball|cube) in element {element:d} is between {low} and {high}'
u'| context.(ball|cube) in element {element:d} is not equal {value1} and {value2}')
def then_context_val_in_element(context: Context, element: int, low: int=None, high: int=None, value1: str=None, value2: str=None):
match = re.search(r'context\.(ball|cube)', step)
val_name = match.group(1)
val = getattr(context, val_name)
if low is not None and high is not None:
assert low <= val[element] <= high
elif value1 is not None and value2 is not None:
assert val[element] not in (value1, value2)
Related
I have a dict:
ff = {("Tom Brady",45678 ): [[456.0, 4050.0], [0.32, 5.6]]}
and
f = {("Tom Brady",45678 ): [[456.0, 4050.0, -1000.0], [0.32, 5.6, 4.56]]}
I have this code:
def find_neg (client_list: dict[tuple[str, int], list[list[float]]], client: tuple[str, int]) -> int
for a in client_list[client][0]:
if a>0:
return 2
if a<0
return 1
the problem with this code is that when there is no negative value, python gives me an error telling me it cannot be NoneType. I want the code to give me an answer if there is a negative, but instead it only gives me an error.
Your current logic is:
def help_find_neg(lst: list[float]):
for element in lst:
if element > 0:
return 2
if element < 0:
return 1
# and if element == 0: go to the next element
If your lst consists only of zeros, the function will skip all of them (and return None).
This might be the reason behind your NoneType error.
You could make the list of lists (the value in your dictionaries) into one big list, and then use list comprehension to create a new list that only holds the negative numbers. If the length of this list comprehension result is bigger than 0, then you have negative numbers in any of the lists that is in the value of your dictionary.
def find_neg (client_list: dict[tuple[str, int], list[list[float]]], client: tuple[str, int]) -> int:
big_list = sum(client_list[client], [])
negatives = [i for i in big_list if i < 0]
if len(negatives) > 0:
return True
return False
(the sum is a little trick to create one list out of a list of lists).
As per comments; if you only need to know if there was a negative number (and you will never need to know what number(s) those were), you could simplify:
def find_neg (client_list: dict[tuple[str, int], list[list[float]]], client: tuple[str, int]) -> int:
big_list = sum(client_list[client], [])
for i in big_list:
if i < 0:
return True
return False
I have the following exercise:
Annotate with correct types the parameters and the return values of
the functions, as well as of the variables, in the program in the
other panel. For that, you only need to replace every occurrence of
Any, except for the very first line, by an appropriate type.
Example: The first Any in line 3, i.e., n: Any, must be replaced by
int. You can see that from the line 9.
While I understand the theory of type hints I don't get the exercise, most probably because I do not get at this point the use of Any.
Furthermore the exercise is ambiguous, it says to replace every occurrence of Any.
If this is the case would the first line be:
def get_half(n : int) -> int:
return n/2
If so it does not work.
from typing import Any #do not edit this line
def get_half(n : Any) -> Any:
return n/2
def print_half(n : Any) -> Any:
print(n/2)
y = get_half(10)
print_half(20)
def is_present(s : Any, char : Any) -> Any:
found : Any = False
l : Any = len(s)
for i in range(0, l):
if s[i] == char:
found = True
return found
print(is_present("john", "h"))
This is the correct solution thanks to your answers
This link was very useful
https://mypy-play.net/?mypy=latest&python=3.10
from typing import Any #do not edit this line
def get_half(n : int) -> float:
return n/2
def print_half(n : int) -> None:
print(n/2)
y = get_half(10)
print_half(20)
def is_present(s : str, char : str) -> bool:
found : bool = False
l : int = len(s)
for i in range(0, l):
if s[i] == char:
found = True
return found
print(is_present("john", "h"))
The first any is an int like the example said def get_half(n : int) -> Any: and the return value will differ depending if your exercise is for python 2 or 3.
Python2: def get_half(n : int) -> int:
Python3: def get_half(n : int) -> float:
The reason for this is that Python 2 always returns an int if you divide and int with an int. int/int=int And Python 3 uses "true division" and therefor returns an float. int/int=float
For more info see: https://en.wikibooks.org/wiki/Python_Programming/Operators
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
Improve this question
Is there any way I can make Python "think" that 5 > 6, or that some other arbitrary math/string equation is interpreted in a specific way?
I mainly want to take a string with a symbol and automatically make it larger than the other, so that "⇟" > "◈" evaluates to True.
I know you can assign these symbols to numbers, but if there is an easier way to do this, it could be more efficient.
This is a basic idea of what I want:
firstSymbol = input("Type in a symbol: ")
secondSymbol = input("Type in a second symbol: ")
if firstSymbol > secondSymbol:
print("firstSymbol > secondSymbol")
elif secondSymbol > firstSymbol:
print("secondSymbol > firstSymbol")
elif firstSymbol == secondSymbol:
print("Your two symbols are equal")
Since Python already has something like this programmed in, I want to change it so that I can create my own symbols that are either greater than or less than the other symbol, without the interruption of Python's automatic string comparisons.
This is fairly simple if you define your own integer class:
class BadInteger(int):
def __gt__(self, other):
return super().__lt__(other)
print(BadInteger(5) > BadInteger(6)) # prints True
The BadInteger class is based on the int class (i.e. the regular Python integer). But in this case, we reversed how a "greater than" comparison works by reimplementing the __gt__ special method ("gt" stands for "greater than"). The implementation simply calls the integer's implementation of __lt__ ("less than").
This effectively means that, when we try to compare two BadIntegers using >, it will work as if we compared two regular integers with <. If the "greater than" comparson would evaluate to True with regular integers, it will now evaluate to False with our BadInteger class, and vice-versa.
You still need to reimplement any other relevant methods, so that they work the opposite way (e.g., __ge__ for the "greater than or equal" operator (>=), __lt__ for "less than" (<), etc). But this sets the base to achieve what you want.
Edit
Since you edited your original question, here's a follow-up answer.
We can once again define a custom class in order to implement the functionality you want. Consider this:
class MySymbol:
def __init__(self, symbol, value = None):
if len(symbol) != 1:
raise ValueError('Symbol string must have length 1')
if value is None:
value = ord(symbol)
self.symbol = symbol
self.value = value
def __str__(self):
return self.symbol
def __repr__(self):
return f'MySymbol(symbol={self.symbol}, value={self.value})'
def __gt__(self, other):
self.check_instance(other=other)
return self.value > other.value
def __ge__(self, other):
self.check_instance(other=other)
return self.value >= other.value
def __eq__(self, other):
self.check_instance(other=other)
return self.value == other.value
def check_instance(self, other):
if not isinstance(other, MySymbol):
error_message = (
f"'==' not supported between instances of"
f" '{self.__class__.__name__}' and"
f" '{other.__class__.__name__}'"
)
raise TypeError(error_message)
The MySymbol class takes a symbol and an optional value as the input. You may have seen where this is going, but the symbol represents your string, and the value is a number used in comparisons.
Since we have implementations for the __gt__, __ge__ and __eq__ magic methods, our symbols "know" how to be compared to one another with the >, >= and == operators, respectively.
Additionally, Python is smart enough to re-use these implementations and simply flip the result around - so we also get <, <= and != for free.
Now this might not be exactly what you hoped for, because we still have to inform what is the specific value of each symbol we create. But this is the price to pay when creating a custom comparison - at some point in your program, you're gonna have to declare which of your custom symbols is greater than the rest, and vice-versa. Python won't ever "just know" that you're trying to compare things in an unusual fashion without you ever telling Python that you want to do so.
Quick demo:
firstSymbol = MySymbol('w', 30)
secondSymbol = MySymbol('$', 108)
firstSymbol != secondSymbol
# True
firstSymbol > secondSymbol
# False
# Note that it will use Python's default string values if we don't provide one
thirdSymbol = MySymbol('a')
fourthSymbol = MySymbol('b')
thirdSymbol > fourthSymbol # same as comparing 'a' > 'b'
# False
And following your example:
s1 = input("Type in a symbol: ")
v1_text = input("Type in its value: ")
try:
v1 = int(v1_text)
except ValueError: # use default string value
v1 = None
s2 = input("Type in a second symbol: ")
v2_text = input("Type in its value: ")
try:
v2 = int(v2_text)
except ValueError: # use default string value
v2 = None
firstSymbol = MySymbol(s1, v1)
secondSymbol = MySymbol(s2, v2)
if firstSymbol > secondSymbol:
print("firstSymbol > secondSymbol")
elif secondSymbol > firstSymbol:
print("secondSymbol > firstSymbol")
elif firstSymbol == secondSymbol:
print("Your two symbols are equal")
Example output:
Type in a symbol: !
Type in its value: 100
Type in a second symbol: #
Type in its value: 10
firstSymbol > secondSymbol
Iam trying to build a priority queue using PriorityQueue in Python, but instead of element to be considered for priority comparison, I want it to use the return value from a function after passing the element to the function , similar to sorted(mtlist,key = myfun), is there a way to achieve this,
Rather than inserting your elements directly into the queue, wrap each element in a tuple, where the first element in the tuple is the desired sorting key. Tuples are sorted by in order of their elements (i.e., first element is compared first), hence why the sorting key needs to come first.
import heapq
queue = []
my_list = [...]
for element in my_list:
heapq.heappush(queue, (my_func(element), element))
If you have a wrapper class for the elements, then you can use operator overloading.
For example, lets say you have a CustomNumber class (equivalent to your elements) where the order is determined by the modulo 16 value (the private function __f()), the you can override the comparison operators like:
class CustomNumber:
def __init__(self, value):
self.value = value
def __f(self, x):
return x % 16
def __lt__(self, obj):
"""self < obj."""
return self.__f(self.value) < self.__f(obj.value)
def __le__(self, obj):
"""self <= obj."""
return self.__f(self.value) <= self.__f(obj.value)
def __eq__(self, obj):
"""self == obj."""
return self.__f(self.value) == self.__f(obj.value)
def __ne__(self, obj):
"""self != obj."""
return self.__f(self.value) != self.__f(obj.value)
def __gt__(self, obj):
"""self > obj."""
return self.__f(self.value) > self.__f(obj.value)
def __ge__(self, obj):
"""self >= obj."""
return self.__f(self.value) >= self.__f(obj.value)
Such that the following code:
a = CustomNumber(16)
b = CustomNumber(14)
print('a < b =', a < b)
print('a <= b =', a <= b)
print('a == b =', a == b)
print('a != b =', a != b)
print('a > b =', a > b)
print('a >= b =', a >= b)
prints:
a < b = True
a <= b = True
a == b = False
a != b = True
a > b = False
a >= b = False
Here is an example of using custom sort in PriorityQueue in Python.
We use a priority-queue (heapq) find the next element to add. To make the
implementation simple we "monkey patch" the ListNode class to have a custom
less-than function using setattr. Note that, simply using the tuple trick
and pushing (node.val, node) to the priority queue will not work because
the lists have values in common.
class Solution:
def mergeKLists(self, lists: List[ListNode]) -> ListNode:
setattr(ListNode, "__lt__", lambda self, other: self.val <= other.val)
pq = []
for l in lists:
if l:
heapq.heappush(pq, l)
out = ListNode(None)
head = out
while pq:
l = heapq.heappop(pq)
head.next = l
head = head.next
if l and l.next:
heapq.heappush( pq, l.next)
return out.next
The way you wrote your question, there is no way to achieve it. According to the documentation:
The lowest valued entries are retrieved first (the lowest valued entry is the one returned by sorted(list(entries))[0]). A typical pattern for entries is a tuple in the form: (priority_number, data).
In other words, the priority is defined by running sorted on the entries, and there is no way there to define the key parameter for that sorted run.
So, you cannot set a sort function when defining the PriorityQueue. You have to use one of the other solutions provided (or write your own PriorityQueue implementation, which should not be too hard).
Edit
After checking the code, I see that the documentation is not an exact description of how it works, but a simplification.
However, it also shows how easy it would be for you to make your own implementation.
I am currently on a python 3 project in witch I work a lot with binary representation of ints, because of this, I made a classe to make the work easier for myself, but I can't make it fully work :
class EnhancedInt(int):
def __init__(self, x: Union[str, bytes, SupportsInt] = ...) -> None:
int.__init__(int(x))
def __getitem__(self, key: int) -> int:
"""Returns the digit number key from the binary representation of self (little endian)
Args:
key (int):
Returns:
int:
"""
if key > 32:
raise ValueError("int are 32 bits long, %d given is too much" % key)
if key < 0:
raise ValueError("Negative keys not supported, %d given is too low" % key)
else:
return EnhancedInt((self >> key) & 1)
def __setitem__(self, key: int, value: int) -> None:
if value != 0 and value != 1:
raise ValueError('Value must be 0 or 1')
self -= self[key]*pow(2, key)
if value:
self += pow(2, key)
So, the part that's not working : __setitem__. I understand why, changing self seems a bit brutal, but I can't find where the value is stored in an int.
For additional comprehension, here is the code calling my class :
>>> i = EnhancedInt(5)
>>> print(i[1])
0
>>> i[1] = 1
>>> print(i)
5 ????
I would like for 7 to be returned, but for now, only 5 is returned.
I found a working solution, even though it required a lot of work, compared to what I wanted to do. I did the following :
class EnhancedInt(int):
"""
Does everything a int can do, but can also be addressed bitwise (you can read, write,
add and delete a bit at given position)
Bit representation is in little endian : the lowest indexes corresponding to the least
significant bits
"""
def __init__(self, x: Union[str, bytes, SupportsInt]) -> None:
int.__init__(int(x))
self.__value__ = int(x)
def __getitem__(self, key: int) -> int:
"""Returns the digit number *key* from the binary representation of *self* (little endian)
Args:
key (int): bit number to be returned
Returns:
int: value of the bit addressed
"""
EnhancedInt._check_key_value(key)
return (self.__value__ >> key) & 1
def __setitem__(self, key: int, value: int) -> None:
"""Changes the value of the *key*th bit of *self* (little endian)
Args:
key (int): index of bit to be modified
value (int): bit value (must be 0 or 1)
"""
EnhancedInt._check_key_value(key)
if value != 0 and value != 1:
raise ValueError("Value must be 0 or 1, %d given" % value)
if (not self[key]) and value:
self.__value__ += 1 << key
return None
if self[key] and not value:
self.__value__ -= 1 << key
I also redefines all the methods used for the class int.
This method seems overkill, and has other flaws. I'd like to find a more elegant way, but meanwhile, this will to.
The complete code can be found at the following address : https://github.com/assombrance/Quantomatic/blob/master/src/data.py