Generating sequences in python

Python random Module – Generate Random Numbers/Sequences

This article is about the random module in Python, which is used to generate pseudo-random numbers for various probabilistic distributions.

Python random Module Methods

1. seed()

This initializes a random number generator. To generate a new random sequence, a seed must be set depending on the current system time. random.seed() sets the seed for random number generation.

2. getstate()

This returns an object containing the current state of the generator. To restore the state, pass the object to setstate() .

3. setstate(state_obj)

This restores the state of the generator at the point when getstate() was called, by passing the state object.

4. getrandbits(k)

This returns a Python integer with k random bits. This is useful for methods like randrange() to handle arbitrary large ranges for random number generation.

>>> import random >>> random.getrandbits(100) # Get a random integer having 100 bits 802952130840845478288641107953

Here is an example to illustrate getstate() and setstate() methods.

import random random.seed(1) # Get the state of the generator state = random.getstate() print('Generating a random sequence of 3 integers. ') for i in range(3): print(random.randint(1, 1000)) # Restore the state to a point before the sequence was generated random.setstate(state) print('Generating the same identical sequence of 3 integers. ') for i in range(3): print(random.randint(1, 1000))
Generating a random sequence of 3 integers. 138 583 868 Generating the same identical sequence of 3 integers. 138 583 868

Generate Random Integers

The random module provides some special methods for generating random integers.

1. randrange(start, stop, step)

Returns a randomly selected integer from range(start, stop, step) . This raises a ValueError if start > stop .

2. randint(a, b)

Returns a random integer between a and b (both inclusive). This also raises a ValueError if a > b .

Here is an example that illustrates both the above functions.

import random i = 100 j = 20e7 # Generates a random number between i and j a = random.randrange(i, j) try: b = random.randrange(j, i) except ValueError: print('ValueError on randrange() since start > stop') c = random.randint(100, 200) try: d = random.randint(200, 100) except ValueError: print('ValueError on randint() since 200 > 100') print('i =', i, ' and j =', j) print('randrange() generated number:', a) print('randint() generated number:', c)
ValueError on randrange() since start > stop ValueError on randint() since 200 > 100 i = 100 and j = 200000000.0 randrange() generated number: 143577043 randint() generated number: 170

Generating Random floating point numbers

Similar to generating integers, there are functions that generate random floating point sequences.

  • random.random() -> Returns the next random floating point number between [0.0 to 1.0)
  • random.uniform(a, b) -> Returns a random floating point N such that a if a b if b < a.
  • random.expovariate(lambda) -> Returns a number corresponding to an exponential distribution.
  • random.gauss(mu, sigma) -> Returns a number corresponding to a gaussian distribution.

There are similar functions for other distributions, such as Normal Distribution, Gamma Distribution, etc.

An example of generating these floating-point numbers is given below:

import random print('Random number from 0 to 1 :', random.random()) print('Uniform Distribution between [1,5] :', random.uniform(1, 5)) print('Gaussian Distribution with mean = 0 and standard deviation = 1 :', random.gauss(0, 1)) print('Exponential Distribution with lambda = 0.1 :', random.expovariate(0.1)) print('Normal Distribution with mean = 1 and standard deviation = 2:', random.normalvariate(1, 5))
Random number from 0 to 1 : 0.44663645835100585 Uniform Distribution between [1,5] : 3.65657099941547 Gaussian Distribution with mean = 0 and standard deviation = 1 : -2.271813609629832 Exponential Distribution with lambda = 0.1 : 12.64275539117617 Normal Distribution with mean = 1 and standard deviation = 2 : 4.259037195111757

Random Sequences using the random module

Similar to integers and floating-point sequences, a generic sequence can be a collection of items, like a List / Tuple. The random module provides useful functions which can introduce a state of randomness to sequences.

1. random.shuffle(x)

This is used to shuffle the sequence in place. A sequence can be any list/tuple containing elements.

Example Code to illustrate shuffling:

import random sequence = [random.randint(0, i) for i in range(10)] print('Before shuffling', sequence) random.shuffle(sequence) print('After shuffling', sequence)
Before shuffling [0, 0, 2, 0, 4, 5, 5, 0, 1, 9] After shuffling [5, 0, 9, 1, 5, 0, 4, 2, 0, 0]

2. random.choice(seq)

This is a widely used function in practice, wherein you would want to randomly pick up an item from a List/sequence.

import random a = ['one', 'eleven', 'twelve', 'five', 'six', 'ten'] print(a) for i in range(5): print(random.choice(a))
['one', 'eleven', 'twelve', 'five', 'six', 'ten'] ten eleven six twelve twelve

3. random.sample(population, k)

Returns a random sample from a sequence of length k .

import random a = ['one', 'eleven', 'twelve', 'five', 'six', 'ten'] print(a) for i in range(3): b = random.sample(a, 2) print('random sample:', b)
['one', 'eleven', 'twelve', 'five', 'six', 'ten'] random sample: ['five', 'twelve'] random sample: ['ten', 'six'] random sample: ['eleven', 'one']

Random Seed

Since pseudorandom generation is based on the previous number, we usually use the system time to make sure that the program gives a new output every time we run it. We thus make use of seeds .

Python provides us with random.seed() with which we can set a seed to get an initial value. This seed value determines the output of a random number generator, so if it remains the same, the output also remains the same.

import random random.seed(1) print('Generating a random sequence of 4 numbers. ') print([random.randint(1, 100) for i in range(5)]) # Reset the seed to 1 again random.seed(1) # We now get the same sequence print([random.randint(1, 100) for i in range(5)])
Generating a random sequence of 4 numbers. [18, 73, 98, 9, 33] [18, 73, 98, 9, 33]

This ensures that we need to be mindful of our seed when dealing with pseudorandom sequences, since the sequence may repeat if the seed is unchanged.

Conclusion

We learned about various methods that Python’s random module provides us with, for dealing with Integers, floating-point numbers, and other sequences like Lists, etc. We also saw how the seed influences the sequence of the pseudorandom numbers.

References

Источник

Background

header image

header image

A sequence in mathematics, is a collection (like a set) of mathematical objects where the order of the objects is significant, and duplicate members of the collection are allowed. In computer science, we represent sequences as arrays, lists, streams, and a variety of other data structures. Creating sequences and operations on already existing sequences is at the core of many software applications. In this post, we’ll look at some techniques for creating sequences using Python 3. The methods will vary based on the sequence we want to produce. Some sequences are infinite, some depend on their index, some depend on previous values in the sequence.

Note: The sequences in this post are any generic type of iterable thing that matches the mathematical defintion of a sequence above. I am not talking about the specific Python notion of a sequence. For the Python version of a sequence, see here.

For-Loop

Sometimes when we know the length of a finite sequence, it is easy to write a simple for-loop to populate the sequence. Consider the sequence consisting of the first n values of the Fibonacci Sequence. The nth value in the Fibonacci sequence is given by the sum of the two previous values in the sequence, i.e. F[n] = F[n — 1] + F[n — 2] .

def fibonacci_first_n(n): sequence = [1, 1] if n == 1: return [1] elif n == 2: return [1, 1] for index in range(n): sequence.append(sequence[-1] + sequence[-2]) return sequence

This gives our desired output: 1, 1, 2, 3, 5, 8, 13, 21, …

List Comprehension

If each value in your sequence can be calculated using a simple expression (where every value follows some rule), list comprehensions provide a terse and expressive method for creating your sequence.

Let’s consider the simple example of generating the first n-even numbers:

def first_n_evens(n): return [2 * n for n in range(1, n + 1)]

or alternatively expressed using a conditional check,

def first_n_evens(n): return [n for n in range(1, 2 * (n + 1)) if n % 2 == 0]

This gives our desired output: 2, 4, 6, 8, 10, 12, …

Recursion

A function is recursive if it calls itself with new arguments, eventually leading to some terminating condition resulting in a value being returned from the intial function call. For example, our fibonacci sequence can also be defined recursively. Notice how the inner function recurse calls itself:

def fibonacci_recursive_first_n(n): if n == 1: return [1] elif n == 2: return [1, 1] def recurse(index, resultsSoFar): if index == n: return resultsSoFar intermediateResult = resultsSoFar + [resultsSoFar[-1] + resultsSoFar[-2]] return recurse(index + 1, intermediateResult) return recurse(2, [1, 1])

This gives our desired output: 1, 1, 2, 3, 5, 8, 13, 21, …

Create a Map Function

In functional programming, a map function takes a n input structure parameterized by type T1, and a mapping function from type T1 to type T2. Calling this map function will call the passed in mapping function on each value of the input structure and return an output structure parameterized by type T2. That sounds complicated, but in practice it’s pretty easy! For example, if we have a list of Rectangles with width and heights, and we call map passing in an area function that returns width * height, we end up with a list of areas.

class Rectangle: def __init__(self, width, height): self.width = width self.height = height rectangles = [ Rectangle(1, 2), Rectangle(4, 8), Rectangle(3, 2) ] areas = map(lambda rect: rect.width * rect.height, rectangles) print(list(areas))

Generator

A generator function is a special function in Python, that can yield multiple values, instead of just a single return. Calling the generator creates an iterator, which can be iterated through with a for-loop.

Generators are computed lazily. That means the next value isn’t calculated until you ask for it. This also means generators can represent infinite sequences. For example, the following generator represents all square numbers:

import itertools def squares(): n = 1 while(True): yield n*n n += 1

You can use the itertools.islice library to take the first n-values:

first10 = itertools.islice(squares(), 10)

Pro tip: The itertools module is very helpful for all things iterators.

Generator Expression

List comprehensions are to lists as generator expressions are to generators. We can create our squares example with a one-liner:

square_gen_expression = (n * n for n in itertools.count(1))

Implement a Class With __iter__ and __getitem__

You can create a container class that wraps some iterator type by implementing the __iter__ and __getitem__ methods.

class EveryThird: def __init__(self): super().__init__() def __iter__(self): return (3 * n for n in itertools.count(1)) def __getitem__(self, i): return (i + 1) * 3

You can test it out with the following code:

every_third = EveryThird() '''test the indexing behavior''' print(every_third[5]) for i in every_third: '''need this clause, because it's an infinite sequence''' if i == 18: break else: print(i)

Conclusion

Python offers a variety of methods to create sequences of values. Which you choose depends on the behavior you application needs, and the properties of the sequence you are representing.

Recent Posts

Implementing the .NET Profiling API in Rust

The Expression Problem in .NET

Fun Tricks with Mono.Cecil in F#

Getting Started with the Hugo Static Site Generator

About Camden

Camden is currently a software developer at M&T Bank. When he isn’t spending time with his family, he enjoys programming the full web stack, and experimenting with new frameworks/languages. Recently he has been especially interested in functional programming and Python. Camden can be contacted via e-mail at camdenreslink@gmail.com, or through his LinkedIn Profile.

Источник

Читайте также:  Создание пустых массивов php
Оцените статью