Is there any method like divide by or multiply by in python range()?

人盡茶涼 提交于 2021-02-16 19:39:46

问题


for java, we can do:

for(int i=100; i>2 ; i=i/2){things to execute}

but what if in python?

is there anything like

for i in range(100:2:something)

could solve this problem?


回答1:


If you need something simple which you can have at hand at several places, you can create a generator function:

def range_divide(start, end, denominator): # TODO: Think for a better name!
    value = start
    while value > end:
        yield value
        value /= denominator

and then do

for value in range_divide(100, 2, 2):
    # do_stuff

You could even flexibilize this with

def range_flexible(start, end, action):
    value = start
    while value > end:
        yield value
        value = action(value)

and do

for value in range_flexible(100, 2, lambda x: x/2):
    # do_stuff

or even

def for_loop(start, cont_condition, action):
    value = start
    while cont_condition(value):
        yield value
        value = action(value)

for value in for_loop(100, lambda x: x > 2, lambda x: x/2):
    # do_stuff



回答2:


There isn't by using a range, you could prepopulate a list and iterate over that but you'd be better off using a while loop.

i = 100
while i > 2:
     ...
     i = i / 2



回答3:


If you want it to look more like a java (or C) for loop, you can define a function that will process the parameters as a string in the C style (at the expense of execution speed):

cachedCFor = dict()
def cFor(params):
    if params in cachedCFor: return cachedCFor[params]()
    setup,condition,step = [ p.strip() for p in params.split(";") ]
    varName   = setup.split("=",1)[0].strip()
    fn    = dict()
    code  = f"""
def iterator():
    {setup}
    while {condition}:
        yield {varName}
        {step}
"""
    exec(code,{},fn)
    cachedCFor[params] = fn["iterator"]
    return fn["iterator"]()

for i in cFor("i=100;i>2;i=i/2"):
    print(i)

100
50.0
25.0
12.5
6.25
3.125

Note that the i variable in the string parameter is internal to the iterator and is not accessible within the for loop's code. We could have written for i in cFor("x=100;x>2;x=x/2") and still use i within the loop

That being said, I would still suggest that you embrace Python's way of doing things and not try to reproduce other language's syntax (i.e. use a while statement in this particular case)

for example:

x = 100
while x > 2:
    i,x = x,x/2 # using x for the next value allows this to be placed
                # at the beginning of the loop (rather than at the end)
                # and avoids issues with the continue statement
    print(i)
    # ... your code ...

Or, you could use a bit of math:

# 6 = int(math.log(100,2)) 
for i in [100/2**i for i in range(6)]:
    print(i) 

# Strangely enough, this is actually slower than the cFor() folly



回答4:


Here's another approach to handle special progressions in a cleaner and more generic fashion. It is a class that implements (and hides) internal workings of a loop variable.

class Loop:
    def __init__(self,start=0):
        self._firstPass  = True
        self._value      = start

    @property
    def value(self): return self._value

    def start(self,initial):
        if self._firstPass : self._value = initial
        return self

    def next(self,nextValue=None):
        if nextValue is None : nextValue = self.value + self._increment
        if self._firstPass : self._firstPass = False
        else               : self._value = nextValue 
        return self

    def up(self,by=1):
        return self.next(self.value+by)
    def down(self,by=1):
        return self.next(self.value-by)

    def upTo(self,last,by=1):
        if self._firstPass: self._firstPass = False
        else: self._value  += by
        return self.value <= last

    def downTo(self,last,by=1):
        if self._firstPass: self._firstPass = False
        else: self._value  -= by
        return self.value >= last

    def loop(self,condition=True):
        self._firstPass = False
        return condition

    def until(self,condition=False):
        self._firstPass = False
        return not condition

    def __getitem__(self,index):     return self.value[index]
    def __str__(self):               return str(self.value)
    def __int__(self):               return int(self.value)
    def __float__(self):             return float(self.value)    
    def __add__(self,other):         return self.value + other
    def __sub__(self,other):         return self.value - other
    def __mul__(self,other):         return self.value * other
    def __matmul__(self,other):      return self.value.__matmul__(other)
    def __divmod__(self,other):      return divmod(self.value,other)
    def __pow__(self,other):         return self.value ** other
    def __truediv__(self,other):     return self.value / other
    def __floordiv__(self,other):    return self.value // other
    def __mod__(self,other):         return self.value % other
    def __lshift__(self,other):      return self.value << other
    def __rshift__(self,other):      return self.value >> other
    def __lt__(self,other):          return self.value < other
    def __le__(self,other):          return self.value <= other
    def __eq__(self,other):          return self.value == other
    def __ne__(self,other):          return self.value != other
    def __gt__(self,other):          return self.value > other
    def __ge__(self,other):          return self.value >= other
    def __and__(self,other):         return self.value & other
    def __or__(self,other):          return self.value | other
    def __xor__(self,other):         return self.value ^ other
    def __invert__(self):            return -self.value
    def __neg__(self):               return -self.value
    def __pos__(self):               return self.value
    def __abs__(self):               return abs(self.value)    
    def __radd__(self, other):       return other + self.value 
    def __rsub__(self, other):       return other - self.value
    def __rmul__(self, other):       return other * self.value
    def __rmatmul__(self, other):    return other.__matmul__(self.value)
    def __rtruediv__(self, other):   return other / self.value
    def __rfloordiv__(self, other):  return other // self.value
    def __rmod__(self, other):       return other % self.value
    def __rdivmod__(self, other):    return divmod(other,self.value)
    def __rpow__(self, other):       return other ** self.value
    def __rlshift__(self, other):    return other << self.value
    def __rrshift__(self, other):    return other >> self.value
    def __rand__(self, other):       return other & self.value
    def __rxor__(self, other):       return other ^ self.value
    def __ror__(self, other):        return other | self.value

The class is designed to work with the while statement after initializing a loop variable. The loop variable behaves like a normal int (or float, or str, etc.) when used in calculations and conditions. This allows the progression and stop condition to be expressed as you would write them for an ordinary loop variable. The class adds a few method to control the loop process allowing for non-standard increments/decrements:

For example:

i = Loop()
while i.start(100).next(i//2).loop(i>2):
    print(i) # 100, 50, 25, 12, 6 ,3

    # Note: to use i for assignment or as parameter use +i or i.value
    #       example1: j = +i   
    #       example2: for j in range(+i)
    #
    # i.value cannot be modified during the loop

You can also give a start value in the constructor to make the while statement more concise. The class also has an until() function to invert the stop condition:

i = Loop(start=100)
while i.next(i//2).until(i<=2):
   print(i) # 100, 50.0, 25.0, 12.5, 6.25, 3.125

Finally there are a couple of helper functions to implement the simpler loops (although a for in would probably be better in most cases):

i = Loop()
while i.start(1).upTo(10):
    print(i) # 1,2,...,9,10

i = Loop()
while i.upTo(100,by=5):
    print(i) # 0,5,10,15,20,...,95,100

i = Loop(100)
while i.down(by=5).until(i<20):
    print(i) # 100,95,90,...,25,20


来源:https://stackoverflow.com/questions/56444418/is-there-any-method-like-divide-by-or-multiply-by-in-python-range

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!