import imaplib, re
import os
while(True):
conn = imaplib.IMAP4_SSL("imap.gmail.com", 993)
conn.login("xxx", "xxxx")
unreadCount = re.search("UNSEEN (\d+)", conn.status("INBOX", "(UNSEEN)")[1][0]).group(1)
print unreadCount
if unreadCount > 10:
os.system('ls')
Even when unreadCount is < 10, it runs the command 'ls'. Why?
You might want to coerce that value to an integer, as per:
unreadCount = int (re.search (blah, blah, blah).group (1))
The call to re.search is returning a string and, if you have a look at the following transcript:
>>> x = "7"
>>> if x > 10:
... print "yes"
...
yes
>>> if int(x) > 10:
... print "yes"
...
>>> x = 7
>>> if x > 10:
... print "yes"
...
>>>
you'll see why that's not such a good idea.
The reason you're seeing this (what you might call bizarre) behaviour can be gleaned from the manual at the bottom of 5.3:
CPython implementation detail: Objects of different types except numbers are ordered by their type names; objects of the same types that don’t support proper comparison are ordered by their address.
Since the type of "7" is str and the type of 10 is int, it's simply comparing the type names ("str" is always greater than "int" in an alpha order), leading to some interesting things like:
>>> "1" > 99999999999999999999999
True
>>> "1" == 1
False
That implementation detail was still in effect up until at least 2.7.2. It may have changed in the Python 3000 stream (the clause has certainly been removed from the relevant documentation section), but the documentation there still states:
Most other objects of built-in types compare unequal unless they are the same object; the choice whether one object is considered smaller or larger than another one is made arbitrarily but consistently within one execution of a program.
So it's probably not something you should rely on.
Try this:
if int(unreadCount) > 10:
os.system('ls')
You're comparing a string to an integer:
>>> '10' > 10
True
This may be shocking; whether the string is coerced to an integer or the integer is coerced to a string, in both cases the result should have been False. The truth is that neither happens, and the ordering is arbitrary. From the language reference:
Most other objects of built-in types compare unequal unless they are the same object; the choice whether one object is considered smaller or larger than another one is made arbitrarily but consistently within one execution of a program.
This will solve your problem:
unreadCount = int(re.search(...).group(1))
Related
Right now, I am zooming into a section of my code as below :
qty = int(input('enter current quantity :'))
if qty != int:
print('input is not integer')
in the above chunk, i passed '5' yet
it returns 'input is not integer'...
So i tried running the below code:
type(qty)
After running this, the output is 'str'
does anyone know what can I change so that the inputs properly gets converted?
i tried....
#notice how i removed the space between '=' and 'int'
qty =int(input('enter current quantity :'))
if qty != int:
print('input is not integer')
this time, the same message appears... HOWEVER,
type(qty)
returns that it has successfully converted to 'int'
That's not how you check the type of instance of an object.
You should use isinstance function if you care about the inheritance OR use type if you want to check specifically for a type.
Option 1:
x = 5
if isinstance(x, int):
# Do some logic here
Option 2:
x = 5
if type(x) is int: # Use "is" and not "==", since classes are singletons!
# Do some logic here
Regarding your code:
qty = int(input('enter current quantity :'))
if qty != int:
print('input is not integer')
If qty is provided by user and can be casted into an int
the condition is false, cause e.g. 5 is NOT equal class int.
If qty is left blank then an empty string is passed to the int() and ValueError: invalid literal for int() with base 10: '' is raised.
So the condition is NEVER true.
Side notes:
In python it's common to use EAFP (easier ask for forgiveness than for permission) more often than LBYL (look before you leap), so you shouldn't care what is the type, do your logic and handle possible raised errors
python uses ducktyping concept, so if it quacks like a duck and walks like a duck treat it like one (doesn't matter it it actually is a duck or not), more technically if an entity implements a particular interface you don't have to check for its type per se
for more info about type vs isinstance look here What are the differences between type() and isinstance()?
please do read about difference between "==" comparison and "is" operator
if qty != int is not how you check for the type of a variable. Instead, try:
if not isinstance(qty, int):
...
Note, however, that if the user doesn't enter an integer i.e.:
int("hello world")
Then a ValueError will be thrown, meaning the code will never reach your if statement. A better solution is to wrap the user input in a try-except statement
I came across a strange behaviour of python comparing a string with True/False.
I thought that python would print in the following:
if "Test" == True:
print("Hello1")
but it does not.
So I wrote some Test cases and I do not understand some of them.
if "Test" == True:
print("Hello1")
if "Test" == False:
print("Hello2")
#This I understand
if bool("Test") == True:
print("Hello3")
#This I understand too
if bool("") == False:
print("Hello4")
if "Test":
print("Hello5")
Output
>> Hello3
>> Hello4
>> Hello5
So I do not understand:
If Hello1 is not printed why is not Hello2 either?
Why does Hello5 get printed, is the cast to bool("Test") made implicit?
In the first two comparisons, you are checking whether the string "Test" has the same value as the object True or False. This is a value comparison.
If they have a different type, the comparison will return False. You can see this also when comparing lists, numbers etc.: [1]==1 (false), (1,)==[1] (false).
In the third and fourth comparisons, you are still doing a value comparison, but since both sides are of the same type (boolean), it will compare the values.
Hello5 is printed because it is not the null string "". You can see this by trying "Test" != None, which returns True.
While it is a comparison to None when it comes to most classes(None is Python's null value), Python's standard data types are compared to their "null" value, which are:
The empty string "" for strings,
[] for lists (similary () for tuples, {} for dictionaries),
0 for ints and floats,
just like a boolean comparison. Therefore it is not wrong to think of if expression as an implicit cast to if bool(expression).
What is going on under the hood is the evaluation of the __non-zero__(python2.x) or __bool__(python3.x) method of the class.
In the case of Hello1, Hello2 and Hello5 there is an object comparison and not boolean comparions.
That means that
the string-object "Test" is not the same as object True ("Hello1")
the string object "Test" is not the same as object False("Hello2")
but the string object "Test" is not None ("Hello5")
Still very new to python. I have refactored a piece of coe and extracted the following code to a new method. It works fine but in search of more pythonic ways I feel the IF clauses are maybe clumsy. Essentially the function may be passed either a str or a number as the variable 'second_option' As a result there is a subtle difference to the next line.
I tried a conditional assignment but it seemed to get upset over the data frame elements of this.
def create_crossover_data(self, indicator, second_option, market_data):
if type(second_option) == str:
market_data['position'] = market_data[indicator] > market_data[second_option]
else:
if type(second_option) == int or float:
market_data['position'] = market_data[indicator] > second_option
market_data['pre_position'] = market_data['position'].shift(1)
market_data.dropna(inplace=True) # dropping the NaN values
market_data['crossover'] = np.where(market_data['position'] == market_data['pre_position'], False, True)
market_data.drop(columns=['position', 'pre_position'])
Generally, in python, it is prudent to use isinstance instead of type. Type only checks that the exact type matches while isinstance checks if our object in question inherits from the given type.
Assuming your second if statement is trying to determine if the variable in question is a number you can use. This method: How can I check if my python object is a number?
Which in your case would be
else:
if isinstance(second_option,numbers.Number):
market_data['position'] = market_data[indicator] > second_option
There is a way in Python to check the type of a variable: isinstance().
Here you have a couple of options to rewrite your code:
def create_crossover_data(self, indicator, second_option, market_data):
if isinstance(second_option, str):
threshold = market_data[second_option]
if isinstance(second_option, (int, float)):
threshold = second_option
market_data['position'] = market_data[indicator] > threshold
The next one looks simpler but makes the assumption second_option can only be a number or a string, and that might not be true, so I would add some control to that:
def create_crossover_data(self, indicator, second_option, market_data):
market_data['position'] = market_data[indicator] > second_option if isinstance(second_option, (int, float)) else market_data[second_option]
Also new to this, but I see nothing except else if -> elif
I want to return a boolean depending if the address given is a correct IPv4 address or not. I am having an issue with the all() built in in python. I have looked up the documentation on it and it seems straight forward. That being said I can't get it to work for my expression. If you could explain how it works layman's terms and how I could correct my code, that would be great.
def IPv4_address(address):
lst_split_address = address.split(".")
slice_split_address = [int(num) for num in lst_split_address[1:]]
if address.count(".") != 3:
return False
elif address == "":
return False
else:
if all(slice_split_address) >= slice_split_address[0]:
return True
else:
return False
print IPv4_address("10.20.30.40")
As said in the documentation of all, it checks if every element in a list evaluates to True (basically bool(e) is True) or it is empty.
Now you have a list of integers in slice_split_address and so it'll check if every element of that list evaluates to True if you just call it like you do and any number other than 0 will evaluate to True, but an IP like 127.0.0.1 is actually valid.
So what you need is actually a list which contains True if the corresponding number is between 0 and 255 (inclusive):
is_valid = [0 <= e <= 255 for e in slice_split_address]
If you call then all(is_valid) it returns if every item in slice_split_address is between 0 and 255. Usually it'll be combined into something like all(0 <= e <= 255 for e in slice_split_address).
Now there is still one issue in your implementation because slice_split_address doesn't actually contain the first number of the IP address, so you might include it. Or do you actually want the first number to be lower or equal to the other three numbers?
Also your check all(…) >= … doesn't make sense as all() only returns True or False so comparing it with an integer doesn't really make sense.
Note that all(is_valid) will also return True to IP addresses like 0.0.0.0 so might need to adjust the range I used.
If you are using Python3, there is a built-in ipaddress module that you can use.
As for what is wrong with your code, I don't believe that the all() function does what you think it does. all() expects an iterable of Booleans, and returns True if every one of those Booleans is True.
To get that to work how you expected, you probably want something like
all(addr_piece >= slice_split_address[0] for addr_piece in slice_split_address)
Don't reinvent the wheel (unless you're happy to maintain the wheel). You can use a regex to validate ipv4 addresses. The following pattern is taken from Django:
r'(?:25[0-5]|2[0-4]\d|[0-1]?\d?\d)(?:\.(?:25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}'
If you are working already in the context of a Django project, you may prefer to just import their validator and use it directly:
from django.core.validators import validate_ipv4_address
As others have said, there are better ways to do this. And your algorithm doesn't actually validate IPv4 addresses. But here's a repaired version of your code.
def IPv4_address(address):
if address.count(".") != 3:
return False
elif address == "":
return False
else:
lst_split_address = address.split(".")
slice_split_address = [int(num) for num in lst_split_address[1:]]
head = slice_split_address[0]
return all(u >= head for u in slice_split_address)
print IPv4_address("10.20.30.40")
output
True
I've moved the lst_split_address stuff into the else block because there's no need to do it if the if / elif parts return False.
all(u >= head for u in slice_split_address)
uses a simple generator expression to check that all items in slice_split_address are >= the head item.
I am trying to break out of a for loop, but for some reason the following doesn't work as expected:
for out in dbOutPut:
case_id = out['case_id']
string = out['subject']
vectorspace = create_vector_space_model(case_id, string, tfidf_dict)
vectorspace_list.append(vectorspace)
case_id_list.append(case_id)
print len(case_id_list)
if len(case_id_list) >= kcount:
print "true"
break
It just keeps iterating untill the end of dbOutput. What am I doing wrong?
I'm guessing, based on your previous question, that kcount is a string, not an int. Note that when you compare an int with a string, (in CPython version 2) the int is always less than the string because 'int' comes before 'str' in alphabetic order:
In [12]: 100 >= '2'
Out[12]: False
If kcount is a string, then the solution is add a type to the argparse argument:
import argparse
parser=argparse.ArgumentParser()
parser.add_argument('-k', type = int, help = 'number of clusters')
args=parser.parse_args()
print(type(args.k))
print(args.k)
running
% test.py -k 2
yields
<type 'int'>
2
This confusing error would not arise in Python3. There, comparing an int and a str raises a TypeError.
Could it happen that kcount is actually a string, not an integer and, therefore, could never become less than any integer?
See string to int comparison in python question for more details.