Strange logic with bool - python

I can't understand one thing with logic in python. Here is the code:
maxCounter = 1500
localCounter = 0
while True:
print str(localCounter) + ' >= ' + str(maxCounter)
print localCounter >= maxCounter
if localCounter >= maxCounter:
break
localCounter += 30
And the result output:
...
1440 >= 1500
False
1470 >= 1500
False
1500 >= 1500
False
1530 >= 1500
False
1560 >= 1500
False
...
And I have infinity cycle there. Why?
topPos = someClass.get_element_pos('element')
scrolledHeight = 0
while True:
print str(scrolledHeight) + ' >= ' + str(topPos)
print scrolledHeight >= topPos
if scrolledHeight >= topPos:
print 'break'
break
someClass.run_javascript("window.scrollBy(0, 30)")
scrolledHeight += 30
print scrolledHeight
time.sleep(0.1)

To fix your code try this:
topPos = int(someClass.get_element_pos('element'))
Why?
When I copy and paste your original code I get this:
...
1440 >= 1500
False
1470 >= 1500
False
1500 >= 1500
True
One small change that I can find to make to your code that reproduces the behaviour you are seeing is to change the first line to this:
maxCounter = '1500' # string instead of integer
After making this change I can also see the output you get:
1410 >= 1500
False
1440 >= 1500
False
1470 >= 1500
False
1500 >= 1500
False
1530 >= 1500
False
etc..

The problem seems to be at this line:
topPos = someClass.get_element_pos('element')
This is likely to assign a string to topPos, instead of a numeric variable. You need to convert this string to a numeric variable so you can do a numeric comparison against it.
topPos = int(someClass.get_element_pos('element'))
Otherwise, e.g. in CPython implementation of v2.7, any int is always going to compare less than any string.
Related questions
How does Python compare string and int?

Related

in Python does 'or not' has 'not' precencence or 'or' precedence?

first time asking for help here.
I going through Kaggle' Python exercises and on Booleans section there is this example:
prepared_for_weather = have_umbrella or rain_level < 5 and have_hood or not rain_level > 0 and is_workday
They say that to make the code more readable it helps using parenthesis this way:
prepared_for_weather = have_umbrella or (rain_level < 5 and have_hood) or not (rain_level > 0 and is_workday)
I am confused about why (considering that the order of operator's precendence in not, and, or) at the end of the expression the and after rain_level > 0 had higher precendence than the not before it.
Is it because the not should be considerate as 'or not' so having less precence than the and?
I hope this is clear enough, thanks!
Having read on Python's documentation that the oerder of precedence is not, and, or I expected the not just before rain_level > 0 to have higher precendence than the and after it.
As stated in the docs, not x has precedence over and
The suggested expression with braces "for readability" is not equivalent to first one, e.g.
have_umbrella = False
have_hood = False
is_workday = False
rain_level = 3
# first
prepared_for_weather = have_umbrella or rain_level < 5 and have_hood or not rain_level > 0 and is_workday
print(prepared_for_weather)
# Kaggle's
prepared_for_weather = have_umbrella or (rain_level < 5 and have_hood) or not (rain_level > 0 and is_workday)
print(prepared_for_weather)
# mine from comments
prepared_for_weather = have_umbrella or rain_level < 5 and have_hood or ((not rain_level > 0) and is_workday)
print(prepared_for_weather)
output
False
True
False

How to filter with different lengths

So I’m trying to get the data from my server and the mvmt number consists of 3 characters and 4 digits (EX: CVG5694) but its datatype is a string so I have to use the cast query and just get the last 4 digits. This gives me a column of integers that has the last 4 digits. However there are trucks that I need to get but it has a different format as having 1 character (the letter x), and 5 digits (ex: X12051). This is a problem because I'm trying to filter out numbers less than 5000. And because I get the last 4 digits it filters out the ones with 1 character and 5 digits (EX: x12051 becomes 2051 in the movement column and gets filtered. Do you know how I could get trucks with numbers such as X12051 in my filter?
Below is some of my code:
SQL_Query = pd.read_sql_query('''SELECT[MVMT_DT],
[MVMT_NUMBER],
CAST(RIGHT(MVMT_NUMBER,4) as int) as movement,
[MVMT_TYPE],
[OPERATOR],
[EQUIPMENT],
[ORIG],
[DEST],
[MVMT_STATUS],
CASE WHEN [GROSS_WEIGHT_(KG)] < 0 THEN 0 ELSE [GROSS_WEIGHT_(KG)] END AS [GROSS_WEIGHT_(KG)],
CASE WHEN [NET_WEIGHT_(KG)]< 0 THEN 0 ELSE [NET_WEIGHT_(KG)] END AS [NET_WEIGHT_(KG)],
CASE WHEN [NMBR_ULDS] < 0 THEN 0 ELSE [NMBR_ULDS] END AS [NMBR_ULDS],
CASE WHEN [NMBR_POS] < 0 THEN 0 ELSE [NMBR_POS] END AS [NMBR_POS]
FROM PATH
WHERE [F-T-O] = 'T'
AND ORIG IN ('CVG', 'CVG CRN', 'MIA', 'MIA GTW', 'LAX', 'LAX GTW', 'JFK', 'JFK GTW', 'ORD', 'ORD GTW')
AND MVMT_TYPE IN ('O/XL', 'O/XL/AH', 'T/XL', 'T/XL/AH', 'CL/AH', 'O/AH', 'T/AH')
AND [MVMT_NUMBER] NOT LIKE '%AMZ%'
AND [MVMT_NUMBER] NOT LIKE '%A0%'
AND [MVMT_NUMBER] NOT LIKE '%K0%'
AND [MVMT_NUMBER] NOT LIKE '%A1%'
AND [MVMT_NUMBER] NOT LIKE '%K1%'
--AND RIGHT([MVMT_NUMBER], 4) <= 5000
AND MVMT_DT = '2021-12-06' --DATEADD(DAY, -2, GETDATE()) AND DATEADD(DAY, -1, GETDATE())''',conn_)
CXL_Filter = ['O/XL', 'O/XL/AH', 'T/XL', 'T/XL/AH']
Ad_Hoc_Filter = ['CL/AH', 'O/AH', 'T/AH']
CXL_CVG = SQL_Query[SQL_Query.MVMT_TYPE.isin(CXL_Filter) & (SQL_Query['ORIG'] == 'CVG') & (SQL_Query['movement'] >= 5000)]
CXL_CVG_CRN = SQL_Query[SQL_Query.MVMT_TYPE.isin(CXL_Filter) & (SQL_Query['ORIG'] == 'CVG CRN') & (SQL_Query['movement'] >= 5000)]
Ad_Hoc_CVG = SQL_Query[SQL_Query.MVMT_TYPE.isin(Ad_Hoc_Filter) & (SQL_Query['ORIG'] == 'CVG') & (SQL_Query['movement'] >= 5000)]
Ad_Hoc_CVG_CRN = SQL_Query[SQL_Query.MVMT_TYPE.isin(Ad_Hoc_Filter) & (SQL_Query['ORIG'] == 'CVG CRN') & (SQL_Query['movement'] >= 5000)]```
You can get the whole number from MVMT_NUMBER
...
CAST(RIGHT([MVMT_NUMBER], PATINDEX('%[0-9][^0-9]%', REVERSE([MVMT_NUMBER])+' ')) as INT) as movement,
...
Test
select
MVMT_NUMBER
, CAST(RIGHT([MVMT_NUMBER], PATINDEX('%[0-9][^0-9]%', REVERSE([MVMT_NUMBER])+' ')) as INT) as movement
from (VALUES ('ABC5444'),('X12345'),('ABCD'),('1234')) val([MVMT_NUMBER])
MVMT_NUMBER
movement
ABC5444
5444
X12345
12345
ABCD
0
1234
1234

function tests haven't gone as expected(part of AoC day4)

I wrote a function that checks if data is correct.
Requirements are as follows:
byr-(Birth Year) - four digits; at least 1920 and at most 2002.
iyr (Issue Year) - four digits; at least 2010 and at most 2020.
eyr (Expiration Year) - four digits; at least 2020 and at most 2030.
def check_byr_iyr_eyr(line):
statement = True
if line[:3] == "byr":
if (len(line[line.index(':')+1:]) != 4 or
1920 > int(line[line.index(':')+1:]) > 2002 ):
statement = False
elif line[:3] == "iyr":
if (len(line[line.index(':')+1:]) != 4 or
2010 > int(line[line.index(':')+1:]) > 2020 ):
statement = False
elif line[:3] == "eyr":
if (len(line[line.index(':')+1:]) != 4 or
2020 > int(line[line.index(':')+1:]) > 2030 ):
statement = False
return statement
list = ['byr:1919', 'iyr:2010', 'eyr:2021', 'iyr:2019', 'iyr:1933',
'byr:1946', 'iyr:1919', 'eyr:2005']
for i in list:
print(check_byr_iyr_eyr(i))
'''
expected result:
False
True
True
True
False
True
False
False
'''
and results of checking provided samples should be like in that multi-line comment "expected results", but unfortunately a result is always True.
I don't know what I'am doing wrong - conditions seems good to me...
Consider this line:
1920 > val > 2002
It is the same result as:
val < 1920 and val > 2002
It means that val is both less than 1920, and greater than 2002, which can never be true.
An elegant solution, using too many if statements is not DRY (don't repeat yourself):
def check_byr_iyr_eyr(line):
# split the string on the colon to get the two parts
prefix, year = line.split(':')
# getting around python's lack of case statements with a dictionary
cases = {
'byr': {'min': 1920, 'max': 2002},
'iyr': {'min': 2010, 'max': 2020},
'eyr': {'min': 2020, 'max': 2030},
}
# get the corresponding min and max and check if the year is inclusively between them
# (note the <= instead of <)
return cases[prefix]['min'] <= int(year) <= cases[prefix]['max']
data = ['byr:1919', 'iyr:2010', 'eyr:2021', 'iyr:2019', 'iyr:1933',
'byr:1946', 'iyr:1919', 'eyr:2005']
for i in data:
print(check_byr_iyr_eyr(i))
Output:
False
True
True
True
False
True
False
False
There are two problems with your function:
Instead of doing complicated string slicing to check what type it is, just do string in line. It's much simpler and readable.
The expression 5 > x > 7, as wim mentioned, is equivalent to an and statement. Since x cannot be both smaller than 5 and greater than 7, this is never True. Do x > 7 or x < 5 instead.
Below is the corrected code which has the correct output:
def check_byr_iyr_eyr(line):
statement = True
if "byr" in line:
if (len(line[line.index(':')+1:]) != 4 or
int(line[line.index(':')+1:]) > 2002 or
int(line[line.index(':')+1:]) < 1920):
statement = False
elif "iyr" in line:
if (len(line[line.index(':')+1:]) != 4 or
int(line[line.index(':')+1:]) > 2020 or
int(line[line.index(':')+1:]) < 2010):
statement = False
elif "eyr" in line:
if (len(line[line.index(':')+1:]) != 4 or
int(line[line.index(':')+1:]) > 2030 or
int(line[line.index(':')+1:]) < 2020):
statement = False
return statement
list = ['byr:1919', 'iyr:2010', 'eyr:2021', 'iyr:2019', 'iyr:1933',
'byr:1946', 'iyr:1919', 'eyr:2005']
for i in list:
print(check_byr_iyr_eyr(i))
'''
expected result:
False
True
True
True
False
True
False
False
'''
Check out Tenacious B's answer for a much more elegant solution!

Iterating through arrays with given limits (python)

I have measurements from three different elements. (tin, copper, lead)
They get evaluated differently as the have different limits.
For example i have the lead, tin and copper content in a stone mixture as my measurements and the certain limits which return different things.
measurement_lead = 150
measurement_tin = 1
measurement_copper = 1002
limits_lead = [0.5, 10, 50, 100]
limits_tin = [0.7, 14, 990, 11000]
limits_copper = [5, 60, 61, 98880]
Now i have to check if one (or more) of my measurements are above the highest limit, if yes "do something", if no i have to check if one is above the second highest and under the highest limit - and so on, until the condition if the measurement is smaller than the smallest of the limits
Hope it's any clear. Trying to write it in python :)
Edit: There are always 4 limits and the amount can't vary. These are given limits for each element. The measurements can be equal to a limit. It should always check bigger or equal to.
tried this:
measurement_lead = 201
measurement_copper = 10
measurement_tin = 2008
e_mat = 2000
b_mat = 900
pw = 20
t_mat = 1
limits_lead = [t_mat, pw, b_mat, e_mat]
e_mat = 45
b_mat = 43
pw = 34
t_mat = 2
limits_copper = [t_mat, pw, b_mat, e_mat]
e_mat = 10
b_mat = 5
pw = 2
t_mat = 0.5
limits_tin = [t_mat, pw, b_mat, e_mat]
for i in limits_lead:
if i >= e_mat:
print("measurement is higher then e_mat")
elif e_mat >= i >= b_mat:
print("measurement is between e_mat and b_mat")
elif b_mat >= i >= pw:
print("measurement is between b_mat and pw")
elif pw >= i >= t_mat:
print("measurement is between pw and t_mat")
elif t_mat >= i >= rw:
print("measurement is between t_mat and rw")
elif i >= rw:
print("measurement is lower then rw")
Now it somehow needs to check if one measurements is higher the e_mat (with its given limits, every element has different limits), if no: if one measurements is between e_mat and b_mat and so on.
Your question needs some clarification:
Are the limits list always in ascending order? assumption: no
Are there always just 4? assumption: no
What happens if the measurement is equal to a value in your limits? assumption: is never equal
I made some assumptions and wrote a function for you to find out which range your measurement falls in so that you can "do_something":
def find_out_position(limits_element, measurement_element):
limits_element = sorted(limits_element)
limits_element.append(measurement_element)
index = sorted(limits_element).index(measurement_element)
if index == 0:
print ("measurement is lower than lowest")
elif index == len(limits_element)-1:
print ("measurement is higher than highest")
else:
print ("measurement is between {} and {}".format(limits_element[index-1], limits_element[index+1]))
I assumed it doesn't matter if all three measurements meet the limit as long as one does. If that is the case, try this:
if measurement_lead >= limits_lead[3] or measurement_tin >= limits_tin[3] or measurement_copper >= limits_copper[3]:
#do something because 1 or more meets the highest requirement
exit
elif measurement_lead >= limits_lead[2] or measurement_tin >= limits_tin[2] or measurement_copper >= limits_copper[2]:
#do something because 1 or more is between the second highest and highest
exit
elif measurement_lead >= limits_lead[1] or measurement_tin >= limits_tin[1] or measurement_copper >= limits_copper[1]:
#do something because 1 or more is between the third highest and second highest
exit
else:
#do something because 1 or more is between the lowest and third highest
exit
Idk what your do sth is but make sure you end the loop after 'doing something' so that the next elif block only executes if none of the three conditions are met in the previous block. Let me know if that makes sense. :)

Write a loop using python

I need to print value with some size using condition.
size, url
1 https://api-glb-ams.smoot.apple.com/user_guid?
3257 https://init.itunes.apple.com/WebObjects/MZInit.woa/wa/signSapSetupCert
0 http://engine.rbc.medialand.ru/code?
35 http://www.google-analytics.com/collect?
0 http://engine.rbc.medialand.ru/test?
0 http://engine.rbc.medialand.ru/code?
I get it in loop and I try to get all url, where size more than 43.
if not size:
continue
elif size[0] < 43:
continue
else:
print size[0], url
If condition works, but elif doesn't. It print all size and url
In Python 2, which you are using, strings can be compared to integers. Strings always compare as being larger than integers.
>>> '35' < 43
False
To solve this, wrap the string in an int() call:
>>> int('35') < 43
True
For your program:
elif int(size[0]) < 43:

Categories