What is the utility of the expression “int(a[-1])” in Python? - python

i have found this code but i do not understand the meaning of this int(ean8[-1]).
from odoo.tests import common
class TestBarcodeNomenclature(common.TransactionCase):
def test_ean8_checksum(self):
barcode_nomenclature = self.env['barcode.nomenclature']
ean8 = "87111125"
checksum = barcode_nomenclature.ean8_checksum(ean8)
self.assertEqual(checksum, int(ean8[-1]))
checksum = barcode_nomenclature.ean8_checksum("8711112")
self.assertEqual(checksum, -1)
checksum = barcode_nomenclature.ean8_checksum("871111256")
self.assertEqual(checksum, -1)

The expression int(ean8[-1]) takes the last character [-1] of the string ean8 and converts it into an integer to allow further operations, that most require an integer (instead of a string) to be executed.
This is due to the fact that the barcode is present in form of a string, or a sequence of characters. Thats because you can retrieve the last character of a string via index call [-1]. The -1 takes the last element of the list.

Related

Transliterate sentence written in 2 different scripts to a single script

I am able to convert an Hindi script written in English back to Hindi
import codecs,string
from indic_transliteration import sanscript
from indic_transliteration.sanscript import SchemeMap, SCHEMES, transliterate
def is_hindi(character):
maxchar = max(character)
if u'\u0900' <= maxchar <= u'\u097f':
return character
else:
print(transliterate(character, sanscript.ITRANS, sanscript.DEVANAGARI)
character = 'bakrya'
is_hindi(character)
Output:
बक्र्य
But If I try to do something like this, I don't get any conversions
character = 'Bakrya विकणे आहे'
is_hindi(character)
Output:
Bakrya विकणे आहे
Expected Output:
बक्र्य विकणे आहे
I also tried the library Polyglot but I am getting similar results with it.
Preface: I know nothing of devanagari, so you will have to bear with me.
First, consider your function. It can return two things, character or None (print just outputs something, it doesn't actually return a value). That makes your first output example originate from the print function, not Python evaluating your last statement.
Then, when you consider your second test string, it will see that there's some Devanagari text and just return the string back. What you have to do, if this transliteration works as I think it does, is to apply this function to every word in your text.
I modified your function to:
def is_hindi(character):
maxchar = max(character)
if u'\u0900' <= maxchar <= u'\u097f':
return character
else:
return transliterate(character, sanscript.ITRANS, sanscript.DEVANAGARI)
and modified your call to
' '.join(map(is_hindi, character.split()))
Let me explain, from right to left. First, I split your test string into the separate words with .split(). Then, I map (i.e., apply the function to every element) the new is_hindi function to this new list. Last, I join the separate words with a space to return your converted string.
Output:
'बक्र्य विकणे आहे'
If I may suggest, I would place this splitting/mapping functionality into another function, to make things easier to apply.
Edit: I had to modify your test string from 'Bakrya विकणे आहे' to 'bakrya विकणे आहे' because B wasn't being converted. This can be fixed in a generic text with character.lower().

Python: Using bool() to select which vars are TRUE, then use those values to call function

First question ever! I've built a GUI which asks user to input 2 of possible 5 values. Each pair of values (10 possible pairs) get used to run 10 different solution functions named Case_n to which all five values (both zero and non-zero) are passed.
The problem I'm having is getting the bool() results stripped down to 2 digit without brackets, etc and then placed into a variable used to create the name of the function to call.
I've run the logic, with TRUE values added to a list, then converted the list to a string so I could strip it down to just the numerals, saved the 2 digit string and added it to the Case_n name. Now, when I try to use the name to call the function, I get an error that a string is not callable. Please help . . .
s = 5 #vars. For this example, I've pre-loaded 2 of them
a = 15
l = 0
r = 0
e_deg = 0
ve = 0
case = []
if bool(s):
case.append(1)
if bool(a):
case.append(2)
if bool(l):
case.append(3)
if bool(r):
case.append(4)
if bool(e_deg):
case.append(5)
nm = str(case) # placeholder to convert case to string
case_num = nm[1] + nm[4] # this returns 12 as a string
# create case_num var, using the string
Case = "Case_" + case_num
print("Case = ",Case) # Should be Case_12
def Case_12(s,a,l,r,e_deg,ve):
print("Case_12 running")
Case(s,a,l,r,e_deg,ve) ```
You could just use eval(Case) but I advise against it as you are processing user input and it could be a security risk.
An easy way would be to build the following dict :
my_dict = {"Case_1": Case_1, ..., "Case_12" : Case_12}
And then, instead of calling Case, you would do
my_dict[Case](s,a,l,r,e_deg,ve)
You could also create a function :
def choose_case(my_case_as_str):
my_case_dict = {"Case_1": Case_1, ..., "Case_12": Case_12}
return my_case_dict[my_case_as_str]
And then call
choose_case(Case)(s,a,l,r,e_deg,ve)
By the way, you probably don't want your function and variable names to start with an uppercase letter. You also probably want to use a safer way to get user input (for example use Template str)

Storing and retrieving a single byte i2c address with strings

I am trying to store an i2c address, 0x3c, to a string to be stored in a text file that is later read. When reading the text file however, I cannot read the data from the string in the correct way, such that
value = string_read(text_file)
print(value == 0x3c)
would return true. How can I read a single byte stored in a string:
'0x3c'
into value so that the above code would return true?
See: https://stackoverflow.com/a/209550/9606335. Specifically, in your example, if you know your string is only "0x3c", then you can convert it to a numerical value by value = int("0x3c", 0). Now your expression should behave as you expect:
>>> print(int("0x3c", 0) == 0x3c)
True

Replace multiple characters in a string using a set of rules

Rules in applyRules is going to be asked to users, but it does not work what it should work which is [“character1:substitution”, “character2:substitution”]
When user put ['b:c','c:d'], it prints c,c. However, it should print d when char is b
The function takes a single character and a set of rules as a list.
And this is what I wrote so far
def applyRules(char, rules):
for rule_list in (rule.split(':') for rule in rules):
char = char.replace(rule_list[0], rule_list[1])
return char
What should I add to make it work appropriately?
If you have multiple rules, this becomes cumbersome. As long as your replacements are done on single characters, you can make this easy with str.translate. That, however, doesn't solve the problem of chained replacements, so you'll have to make use of a while loop that runs until there are no more changes.
def applyRules(string, rules):
mapping = str.maketrans(dict(x.split(':') for x in rules))
while True:
new = string.translate(mapping)
if string == new:
break
string = new
return new
In [1308]: applyRules('bbbbb', ['b:c', 'c:d'])
Out[1308]: 'ddddd'
Single Character Replacement
For replacement involving a single character, the solution simplifies. You could use a dictionary with get:
def applyRules(char, rules):
mapping = dict(x.split(':') for x in rules)
while True:
new = mapping.get(char, char)
if char == new:
break
char = new
return new
This should be much simpler.
You need to apply each and every rule and also, preserve the new string at the same time since strings are immutable in python. You can use translate of str class. Following code works
def applyRules(char, rules):
modified = char
for rule in rules:
r = rule.split(':')
table = str.maketrans({r[0]:r[1]})
modified = modified.translate(table)
return modified
print(applyRules('bbbbb',['b:c','c:d'])) #prints 'ddddd'
print(applyRules('abdecbc',['b:c','c:d'])) #prints 'addeddd'

TypeError: 'str' object does not support item assignment (Python)

So this is what I'm trying to do:
input: ABCDEFG
Desired output:
***DEFG
A***EFG
AB***FG
ABC***G
ABCD***
and this is the code I wrote:
def loop(input):
output = input
for index in range(0, len(input)-3): #column length
output[index:index +2] = '***'
output[:index] = input[:index]
output[index+4:] = input[index+4:]
print output + '\n'
But I get the error: TypeError: 'str' object does not support item assignment
You cannot modify the contents of a string, you can only create a new string with the changes. So instead of the function above you'd want something like this
def loop(input):
for index in range(0, len(input)-3): #column length
output = input[:index] + '***' + input[index+4:]
print output
Strings are immutable. You can not change the characters in a string, but have to create a new string. If you want to use item assignment, you can transform it into a list, manipulate the list, then join it back to a string.
def loop(s):
for index in range(0, len(s) - 2):
output = list(s) # create list from string
output[index:index+3] = list('***') # replace sublist
print(''.join(output)) # join list to string and print
Or, just create a new string from slices of the old string combined with '***':
output = s[:index] + "***" + s[index+3:] # create new string directly
print(output) # print string
Also note that there seemed to be a few off-by-one errors in your code, and you should not use input as a variable name, as it shadows the builtin function of the same name.
In Python, strings are immutable - once they're created they can't be changed. That means that unlike a list you cannot assign to an index to change the string.
string = "Hello World"
string[0] # => "H" - getting is OK
string[0] = "J" # !!! ERROR !!! Can't assign to the string
In your case, I would make output a list: output = list(input) and then turn it back into a string when you're finished: return "".join(output)
In python you can't assign values to specific indexes in a string array, you instead will probably want to you concatenation. Something like:
for index in range(0, len(input)-3):
output = input[:index]
output += "***"
output += input[index+4:]
You're going to want to watch the bounds though. Right now at the end of the loop index+4 will be too large and cause an error.
strings are immutable so don't support assignment like a list, you could use str.join concatenating slices of your string together creating a new string each iteration:
def loop(inp):
return "\n".join([inp[:i]+"***"+inp[i+3:] for i in range(len(inp)-2)])
inp[:i] will get the first slice which for the first iteration will be an empty string then moving another character across your string each iteration, the inp[i+3:] will get a slice starting from the current index i plus three indexes over also moving across the string one char at a time, you then just need to concat both slices to your *** string.
In [3]: print(loop("ABCDEFG"))
***DEFG
A***EFG
AB***FG
ABC***G
ABCD***

Categories