How to iterate step with right shift in Python? - python

Is it possible to use right shift as the step argument in xrange?
Basically I'm trying to do this (pseudo-code)
for i in xrange(35926661, 0, _value_>>6):
//logic

No.
xrange always works by adding the third parameter. You cannot tell it to do something like a right shift instead.
A while loop will work, there may be better solutions but its hard to say without more information about what you are doing.

You can define a custom xrange-like function using a generator:
def lrange(a, b, f):
num = a
comp = operator.lt if (a < b) else operator.gt
while comp(num, b):
yield num
num = f(num)
Then:
for x in lrange(35926661, 0, lambda x: x>>6):
print(x)
http://codepad.org/0pYfWqSF

Related

Python condensed if statements

I am experimenting with how to condense if statements within my code. I have a project I am working on that has several "if" statements (too many to keep track of) and want to figure out a way to condense them. Obviously this involves a for loop, but I am having trouble adding additional operations within this loop.
I came up with the following working example to demonstrate my issue:
num=6
if_options = [num==5, num==6]
for i in range(len(if_options)):
if if_options[i]:
print(num)
I want to add an additional piece to the code. This additional piece will execute an operation within the if statement. See following non-working example as a framework for what I am trying to accomplish:
num=6
if_options = [num==5, num==6]
operations = [num=num+1, num=num-1]
for i in range(len(if_options)):
if if_options[i]:
operations[i]
print(num)
For whatever reason, it will not execute the operation portion of the code and fails with a syntax error. It does not let me declare the command "num=num+1" (without quotes) within a list, however this declaration is necessary for executing the command. I feel like I am missing one little thing and it should be an easy fix. Thank you in advance!!
The problem here is that the operations are evaluated when you create the list of them. You want to write them as strings, and then eval/exec them in the loop. I will assume you also want the conditions evaluated in the loop.
num = 6
if_options = ['num==5', 'num==6']
operations = ['num=num+1', 'num=num-1']
for i in range(len(if_options)):
if eval(if_options[i]):
exec(operations[i])
print(num)
why not functions?
def check(inp):
#you can do some logic and type checking here
return type(inp)==int # for example, or return arguments to pass to the operatiins
def operation(inp2):
if inp2: # check if true or not empty, as an example
#do some operations
# and then you do something like
for x in input_of_things:
operation( check( x ) )
You could use lambda expressions too.
num = 6
if_option_checks = [lambda x: x == 5, lambda x: x == 6]
operations = [lambda x: x + 1, lambda x: x - 1]
for check, operation in zip(if_option_checks, operations):
if check(num):
num = operation(num)
Or you could use dictionaries and lambda expressions
num = 6
if_option_checks = {"add": lambda x: x == 5, "sub": lambda x: x == 6}
operations = {"add": lambda x: x + 1, "sub": lambda x: x - 1}
for key, check in if_option_checks.items():
if check(num):
num = operations[key](num)
Perhaps a switch statement structure could help.
First define a switch function:
def switch(v): yield lambda *c: v in c
Then use is in a one-iteration for loop that yields a case function for the switch value:
for case in switch(num):
if case(5):
num = num + 1
break
if case(6):
num = num - 1
break
...

Is there a way to take conditions for for loop as an input in python? I am having trouble with this code

I recently had an idea of doing sigma(Σ) using python
So, I wrote this code.
def sigma(i,target,condition='i'):
if condition=='i':
a=0
for f in range(i,target+1): #the loop sums all the numbers from i to the target given
a+=f
print(a)
'''if user enters a condition than,
every number will follow condition and then be added to each other'''
else:
lis=list()
condition for i in range(i,target+1):
lis.append(i)
print(sum(lis))
but the code I wrote above just gives me a wrong output as it takes the variable condition as type 'string'.
The problem is actully to take the argument condition not as a string
for example, let's say user entered:
sigma(1,100,condition='i'*2)
so the code should run for loop like this:
i*2 for i in range(i, target+1)
but it runs like this:
'ii' for i in range(i, target+1)
For what I can understand, you should pass an anonymous function as argument to accomplish what you are looking for.
Consider that this is not a valid syntax: i*2 for i in range(i, target+1), so I consider it as a pseudo code explained by your comment.
You should change your method in this way:
def sigma(i, target, condition='i'):
if condition=='i':
a=0
for f in range(i,target+1):
a+=f
print(a)
else:
lis=list()
for i in range(i, target+1):
lis.append(i)
print(condition(sum(lis)))
So that if you call sigma(1,100,'i') #=> 5050 you fall in the true part of the statement.
For the false part of the statement you need to call the method passing a lambda expression as parameter:
sigma(1,100, lambda i: 2*i) #=> 10100
It happens that the argument condition when passed as lambda works as if it was defined as:
def condition(i):
return 2 * i
I would like to point out that the sum of the first n natural numbers is given by a math formula, so you don't need a loop:
n * (n + 1) // 2
Also should be better to return a value than to print.
I'd rewrite the method:
def sigma_2(i, target, condition=None):
sum_i_to_target = (target*(target+1)-(i-1)*i)//2
if condition is not None:
return condition(sum_i_to_target)
else: # need to check that condition is a lambda function
return sum_i_to_target
So call this way:
sigma_2(2, 20) #=> 209
sigma_2(2, 20, lambda i: 2*i) #=> 418
You've initialized i from what I can see from your code as a string.
If you would like for the compiler to read it as int then initialize i as int.
For example:
i=1

Taking the maximum of an arbitrary amount of arguments in Python

I have very little experience in coding and I'm learning Python in a class. I'm learning about conditionals and loops and have been asked to create a function that'll take an arbitrary amount of arguments and give me the maximum. Obviously I'm not allowed to use the built-in max function.
So far, I have:
def max(x):
current_max = x[1]
for i in x[i]:
if x[i] > current_max:
current_max = x[i]
When I run the code, it gives me no errors, but when I try to run max() it'll only accept one argument. The only idea that came to mind was adding in:
x = input('Enter numbers to compare:')
When I ran this, I got:
UnboundLocalError: local variable 'i' referenced before assignment
And I'm unsure of what I can do at this point as I'm unsure of whether or not I'm not defining the argument correctly or there's just an error in the code defining max(x) that didn't show up in the first time for some reason.
Two things:
1) In Python, you need to add a single * before the argument to indicate that the argument is actually a list of arguments. Without that *, you're function is only going to expect a single argument. EDIT: Ah I just saw you are actually passing a list object into your function, in which case the * isn't needed. If you wanted to support a call such as max(1,3,7,-4) then you would indeed want a *.
2) When iterating through a list, or any other "iterable", you can use for item in list_of_items: to iterate over and examine each item in the list. This is used all the time in Python and is the preferred way (ie. the Pythonic way) to iterate over the list of args in a case such as this.
Here's an example max function that ties it all together (and supports a call such as max(1,5,7,3):
def max(*x):
current_max = x[0] # Note we're assuming at least one argument was passed in. What if nothing was passed in?
for i in x:
if i > current_max:
current_max = i
return current_max
And here's an example max function that supports a call such as max([1,5,7,3]):
def max(x):
current_max = x[0] # Note we're assuming at least one argument was passed in. What if nothing was passed in?
for i in x:
if i > current_max:
current_max = i
return current_max
FYI My examples are not the best solutions to this problem, so I suggest you expand on them for your final solution.
x[i] is executed before the loop is for processed by the compiler so trying to loop through x[i] without i being declared beforehand will result in an error.
Given x where x is the list x = [ 1,2,3,4 ] the following should work
def max(x):
current_max = x[0]
for i in x:
if i > current_max:
current_max = i
return current_max
x = [1,2,3,4]
print max(x)
Your algorithm will work but there are two small problems. First, there is a problem with iterating over an array. Normally you don't need indexes at all, just do:
some_list = [1, 2, 3]
for item in some_list:
print item
# Will print 1, then 2 and finally 3
Also you need to return current_max when you are done with your loop.
Reusing names of builtin functions is not a great idea, so I'd call it my_max or something like that. If you also want to check your arguments and add a docstring, you'll end up with this:
def my_max(x):
""" Return the biggest item in an iterable. """
if len(x) == 0:
raise ValueError("my_max() arg is an empty sequence")
current_max = x[0]
for i in x:
if i > current_max:
current_max = i
return current_max
If you prefer a functional coding style, you can use reduce to reduce your list to the biggest element. Simply define the lambda that returns the biggest element:
def my_max(xs):
return reduce(lambda x, y: x if x > y else y, xs)
If you wonder how Python's built-in max is defined, it's actually written in C like many of Python's built-in functions. You can check it out on GitHub if you're curious. Internally it works just as min, since comparisons are done using something called PyObject_RichCompareBool that can compare two objects in different ways (less, less or equal, equal, not equal, ...)

Python String Reversal

This exercise involves a codeacademy problem to write a function which takes a string as an input and outputs the string in reverse, I've found solutions as to how to do it online, I'm just confused as to why mine doesnt work:
def reverse(c):
empty=[]
stringsize= len(c)
for x in range(stringsize):
empty[x]=c[stringsize-x]
return empty
You need to start at indexing your string from -1 through to -stringsize, and use empty.append() to add values:
for x in range(stringsize):
empty.append(c[stringsize - x - 1])
Python indexing starts at 0, making stringsize - 1 the last index. Because empty is an empty list, you cannot index into it. Using the list.append() method adds new values at the end instead.
You don't really need the stringsize reference there, because negative indices automatically are subtracted from the length for you:
for x in range(len(c)):
empty.append(c[-x-1])
Since this is supposed to return a string, not a list, you need to join the characters again at the end:
return ''.join(empty)
The easiest way to reverse a list is to use a negative slice stride:
def reverse(c):
return c[::-1]
One solution :
def reverse(c):
empty=[]
stringsize= len(c)
for x in range(stringsize):
empty.append(c[-(x+1)])
return ''.join(empty)
print reverse('string')
Another:
def reverse(c):
empty=[]
stringsize= len(c)
for x in range(stringsize):
empty.append(c[stringsize - (x+1)])
return ''.join(empty)
print reverse('string')
Using recursion:
def reverse(string,start,stop):
if start < stop - 1:
string[start],string[stop - 1] = string[stop - 1],string[start]
reverse(string,start+1, stop-1)
return ''.join(string)
print reverse(list('string'), 0, len('string'))
In Python a string is an iterable so iterable functions can be used with it. For example reversed function:
>>> "".join(reversed("123"))
'321'
The least changes necessary to make your code run seem to be:
def reverse(c):
stringsize= len(c)
empty=[None] * stringsize
for x in range(stringsize):
empty[x]=c[stringsize-x-1]
return empty
But you should reconsider your name empty (as Martijn pointed out) because that thing isn't empty (at least in the end), so the name is misleading.
The classic answer to this problem is to use a slice with a negative step to get what you want:
def reverse(c):
return c[::-1]
...but maybe that's not allowed for you?

Python command working but why?

I have a simple code that goes like this in Python:
a = [1,2,3]
b = [2,4,6]
def union(a,b):
pos = 0
while pos < len(b):
n = b[pos]
if n in a is not 'True':
a = a
else:
a.append(n)
pos = pos +1
return a
print union(a,b)
As you can see, the first IF statement makes no sense. However, if I code it this way:
if n in a is 'True':
a.append(n)
it does not work. The first code segment changes a = [1,2,4,6] - only adding numbers from list 'b' that are not in list 'a' already. If I change the 'IF' snippet to "is 'True" as suggested, it does not work.
While this function does what I intended it to do, I feel it is not clean and I have no idea why "if n in a is 'True':" would not behave equal to the else part of the "if n in a is not 'True':" function.
Can somebody please help me understand this?
It is not a very pythonic way to use boolean check and then compare it with a string, so it would be better to do it this way:
a = [1,2,3]
b = [2,4,6]
def union(x,y):
for v in y:
if v not in x:
x.append(v)
return x
print union(a,b)
OR:
a.extend(set(b).difference(set(a)))
print a
>>> [1, 2, 3, 4, 6]
OR in case you don't care about new objects creating than:
print list(set(a).union(b))
in and is/is not are both relational operators, and in Python relational operators are chained. Therefore n in a is not 'True' is equivalent to n in a and a is not 'True', and n in a is 'True' is equivalent to n in a and a is 'True'. Clearly these are not negations of each other since they both have n in a.
But don't use is unless you know you need it, and never compare against a boolean either (unless yadda yadda).
You should just use True not the string 'True'
or better yet, just
if n not in a:
a.append(n)
If you are a beginner, you may not realise that Python has a builtin type called set
set objects already have methods for intersection/union etc.
You can use
if n in a
or
if n not in a
instead of the is 'True'.

Categories

Resources