How to make an if statement using widget option values as conditions? - python

Let's say i have a this button:
tl.config(bd=0 ,image=photo1 ,width="100",height="100",command=lambda: functionPlus(tl))
The function is :
def functionPlus(button):
global turn
if (turn==1 or turn==3 or turn==5 or turn==7 or turn==9):
button.config(image=photo2,width="100",height="100")
turn +=1
elif (turn==2 or turn==4 or turn==6 or turn==8) :
button.config(image=photo3,width="100",height="100")
turn+=1
I would like to add an 'if' in the function, that would have as condition the image of the button. For exemple :
if button.config(image=photo2 == True) :
anotherFunction()
Thanks in advance.

First, never use the expression pattern something=something else == True!
Second, take a look at this related (but not duplicate) question.
As you can see there, the cget method will return the current value for an option. As this manual page mentions, cget is analogous to widget["option"].
So, to answer your question directly, the if condition you need would be along the lines of:
if button['image']==photo2:
anotherFunction()

I'm new here and couldn't comment. I hope I'm not flaunting SO policy by resorting to answering instead.
#Tersosauros
"First, never use the expression pattern something=something else ==
True!"
Where do you see this pattern and why should it be avoided? What could replace it? (I know you're a tersosaurus but "never use X" just seems TOO terse and uninformative).
#Arwan Credoz I know you got your answer but... If you simply want to check whether the value of "turn" is a an even/odd number and is within a given range, use a bounds check followed by modulus instead (maybe this is what #Tersosauros was hinting at?).
Also, the value of "turn" will always be incremented if it's within range(0,10) so there's no need to write "turn+=1" twice. If I've understood your intentions correctly, you could probably rewrite "functionPlus" to something like this and add Tersosaurus' addition where appropriate:
def functionPlus(button):
global turn
if 0 < turn < 10:
if turn % 2 == 0:
button.config(image=photo3,width="100",height="100")
else:
button.config(image=photo2,width="100",height="100")
turn += 1

Related

How to remove only one instance of specified character in string

If I have a list of strings such as the following:
"apple.test.banana", "test.example","example.example.test".
Is there a way to return only "test.banana" and "example.test"?
I need to check and see if there are two dots, and if there are, return only the value described above.
I attempted to use:
string="apple.test.banana"
dot_count=0
for i in string:
if i==".":
dot_count=dot_count+1
if dot_count>1:
string.split(".")[1]
But this appears to only return the string "test".
Any advice would be greatly appreciated. Thank you.
You are completely right, except for the last line, which sould say '.'.join(string.split(".")[1:]).
Also, instead of the for loop, you can just use .count(): dot_count = string.count('.') (this doesn't affect anything, just makes your code easier to read)
So the program becomes:
string = "apple.test.banana"
dot_count = string.count('.')
if dot_count > 1:
print('.'.join(string.split(".")[1:]))
Which outputs: test.banana

Best alternative to using if statement?

I am trying to break out of a bad habit of using if/else too frequently. I am new to how functions work and the proper way to call them but I am constantly researching the correct way to implement them with my code. The code that I am making is suppose to check for 3 different words and if the word is not in the input then the user will receive a statement that says "rejected" if the word is correct it will say "accepted". The issue that I am facing is getting my program to work correctly. So far I have set up my program to check each index of the word and if it matches the full word it will be marked as accepted. I am trying to figure out the correct way to add a rejected flag and to avoid the error that I recieve after running this program.
def checker():
q0 = input("enter word:")
if (q0[0]) +(q0[1]) == "if":
print ("accepted")
if (q0[0]) + (q0[1]) + (q0[2]) + q0[3] == "else":
print("accepted")
if(q0[0]) + (q0[1]) == "do":
print("accepted")
else:
print("rejected")
checker()
For this program, I am not going to use a dictionary so I can correctly challenge myself and implement this in an automata fashion. How can I implement this code without getting the string index out of range error. I tried to put break after my print statement but it doesn't work.
Thanks in advance to everyone. This is my first post so if I have made any mistakes in my post please let me know!
Here's an extensible one-liner for you:
def check():
q = input().strip()
acceptable = {'if', 'else', 'do'}
print('accepted' if q in acceptable else 'rejected')
The variable acceptable is set; a data structure which is very quick to check if something is inside of it. You can modify this set (or pass it to check as an argument!) to change the range of acceptable words without changing the control flow of the program (as you would in your original if/else implementation that you're laudably trying to move away from).
EDIT: I guess it's not strictly a 'one-liner'...
First, why do you access each character of the input string, then concatenate them again, then compare to a target string("if", "else", "do")?
Second, why do you use if statements repeatedly if matching either one of them will lead to the same result (print("accepted")?
Try this:
def checker():
q0 = input("enter word:")
if q0 in ["if", "else", "do"]:
print("accepted")
else:
print("rejected")
checker()
Now, you just compare a string q0 to another (each element of the list ["if", "else", "do"]). Also, the first hit in the list will make stop comparing anymore and will continue on to print "accepted".
++ Just to let you know why are you seeing "index out of range error", you are accessing each character of q0 without knowing how many there are. So if the user inputs a string like a, there's no q0[1] or q0[2], but you're asking your program to access it. Thus index out of range error.
You can do this with a for loop and one if statement if that is better for you. Simply put all the accepted values into a list and check if each word is in q0.
def checker():
q0 = input('enter word:')
for i in ['if', 'else', 'do']:
result = ('accepted' if i in q0 else 'rejected')
if result == 'accepted':
break
print(result)
you can do it as one liner with lambda function.
checker = lambda q: print("accepted" if q in ["elif", "if", "else"] else "rejected")
checker()
here is a sample
>>> checker = lambda q: print("accepted" if q in ["elif", "if", "else"] else
"rejected")
>>> checker("if")
accepted
>>> checker("fool")
rejected

ArcMap Field Calculator Program to create Unique ID's

I'm using the Field Calculator in ArcMap and
I need to create a unique ID for every storm drain in my county.
An ID Should look something like this: 16-I-003
The first number is the municipal number which is in the column/field titled "Munic"
The letter is using the letter in the column/field titled "Point"
The last number is simply just 1 to however many drains there are in a municipality.
So far I have:
rec=0
def autoIncrement()
pStart=1
pInterval=1
if(rec==0):
rec=pStart
else:
rec=rec+pInterval
return "16-I-" '{0:03}'.format(rec)
So you can see that I have manually been typing in the municipal number, the letter, and the hyphens. But I would like to use the fields: Munic and Point so I don't have to manually type them in each time it changes.
I'm a beginner when it comes to python and ArcMap, so please dumb things down a little.
I'm not familiar with the ArcMap, so can't directly help you, but you might just change your function to a generator as such:
def StormDrainIDGenerator():
rec = 0
while (rec < 99):
rec += 1
yield "16-I-" '{0:03}'.format(rec)
If you are ok with that, then parameterize the generator to accept the Munic and Point values and use them in your formatting string. You probably should also parameterize the ending value as well.
Use of a generator will allow you to drop it into any later expression that accepts an iterable, so you could create a list of such simply by saying list(StormDrainIDGenerator()).
Is your question on how to get Munic and Point values into the string ID? using .format()?
I think you can use following code to do that.
def autoIncrement(a,b):
global rec
pStart=1
pInterval=1
if(rec==0):
rec=pStart
else:
rec=rec+pInterval
r = "{1}-{2}-{0:03}".format(a,b,rec)
return r
and call
autoIncrement( !Munic! , !Point! )
The r = "{1}-{2}-{0:03}".format(a,b,rec) just replaces the {}s with values of variables a,b which are actually the values of Munic and Point passed to the function.

shortening python "if" statements

I've been constantly coding in Python using this inefficient style
checkbox = self.request.get(u'checkbox') # get data from a web form
if checkbox == u'yes':
someclass.enabled = True
else:
someclass.enabled = False
how do I shorten this?
someclass.enabled = self.request.get(u'checkbox') == u'yes'
You can do this without an if statement:
someclass.enabled = (checkbox == u'yes')
You can just set the value to the outcome of the statement:
checkbox = self.request.get(u'checkbox') # get data from a web form
someclass.enabled = checkbox == u'yes'
As checkbox == u'yes' returns a boolean value you can simply assign this result to the variable directly.
someclass.enabled = (checkbox == u'yes')
Perhaps you could split it into a different function:
def getCheckboxValue(name):
return (self.request.get(name) == u'yes')
Python eval the statement and return the output to the statement. So you can use the assign variable in right side.
like
variable = eval_statment
so your example will be
someclass.enabled = self.request.get(u'checkbox') == u'yes'
It's a little unclear if you used booleans in your example because they were inherent to your problem or because they were a convenient example. If you want to assign to variables more complicated types than booleans, you may also want to check out Python's ternary operator (if you're using version 2.5 or greater):
someclass.int_val = 1 if checkbox == u'yes' else 2
which translates to
if checkbox == u'yes':
someclass.int_val = 1
else
someclass.int_val = 2
For boolean variables, I'd recommend using Yuushi's solution, but for completeness, this is what it would look like:
someclass.enabled = True if checkbox == u'yes' else False
It's about the same amount of typing, but saves some vertical space, which can be useful.
If you ever need more than a boolean value, you should consider using the dispatch pattern:
targets = {
'yes': do_yes,
'no': do_no,
'maybe': do_maybe,
}
targets[self.request.get(u'tricheckbox')]()
# where do_yes, do_no, and do_maybe are the functions to call for each state.
As pointed-out in another answer you could use dispatch table to do different things based on a value. However using a dictionary's get() method rather than \performing a direct lookup would allow you to also easily handle cases where nothing matches. Since the mapping won't be used again it can be temporary and anonymous.
This approach is very generic and can expanded as necessary, but usually requires extra functions to be written. Because of the latter, for very simple cases like your example, one of the other answers would probably require the least effort.
def do_yes(): print 'do_yes'
def do_no(): print 'do_no'
def do_maybe(): print 'do_maybe'
def no_match(): print 'no_match'
{
u'yes': do_yes,
u'no': do_no,
u'maybe': do_maybe,
}.get(self.request.get(u'checkbox'), no_match) ()

How to combine initialization and assignment of dictionary in Python?

I would like to figure out if any deal is selected twice or more.
The following example is stripped down for sake of readability. But in essence I thought the best solution would be using a dictionary, and whenever any deal-container (e.g. deal_pot_1) contains the same deal twice or more, I would capture it as an error.
The following code served me well, however by itself it throws an exception...
if deal_pot_1:
duplicates[deal_pot_1.pk] += 1
if deal_pot_2:
duplicates[deal_pot_2.pk] += 1
if deal_pot_3:
duplicates[deal_pot_3.pk] += 1
...if I didn't initialize this before hand like the following.
if deal_pot_1:
duplicates[deal_pot_1.pk] = 0
if deal_pot_2:
duplicates[deal_pot_2.pk] = 0
if deal_pot_3:
duplicates[deal_pot_3.pk] = 0
Is there anyway to simplify/combine this?
There are basically two options:
Use a collections.defaultdict(int). Upon access of an unknown key, it will initialise the correposnding value to 0.
For a dictionary d, you can do
d[x] = d.get(x, 0) + 1
to initialise and increment in a single statement.
Edit: A third option is collections.Counter, as pointed out by Mark Byers.
It looks like you want collections.Counter.
Look at collections.defaultdict. It looks like you want defaultdict(int).
So you only want to know if there are duplicated values? Then you could use a set:
duplicates = set()
for value in values:
if value in duplicates():
raise Exception('Duplicate!')
duplicates.add(value)
If you would like to find all duplicated:
maybe_duplicates = set()
confirmed_duplicates = set()
for value in values:
if value in maybe_duplicates():
confirmed_duplicates.add(value)
else:
maybe_duplicates.add(value)
if confirmed_duplicates:
raise Exception('Duplicates: ' + ', '.join(map(str, confirmed_duplicates)))
A set is probably the way to go here - collections.defaultdict is probably more than you need.
Don't forget to come up with a canonical order for your hands - like sort the cards from least to greatest, by suit and face value. Otherwise you might not detect some duplicates.

Categories

Resources