Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

228
Vistas
¿Cómo puedo hacer un objeto con una interfaz como un generador de números aleatorios, pero que en realidad genera una secuencia específica?

Me gustaría construir un objeto que funcione como un generador de números aleatorios, pero que genere números en una secuencia específica.

 # a random number generator rng = lambda : np.random.randint(2,20)//2 # a non-random number generator def nrng(): numbers = np.arange(1,10.5,0.5) for i in range(len(numbers)): yield numbers[i] for j in range(10): print('random number', rng()) print('non-random number', nrng())

El problema con el código anterior es que no puedo llamar a nrng en la última línea porque es un generador. Sé que la forma más sencilla de reescribir el código anterior es simplemente recorrer los números no aleatorios en lugar de definir el generador. Preferiría que el ejemplo anterior funcione porque estoy trabajando con una gran parte del código que incluye una función que acepta un generador de números aleatorios como argumento, y me gustaría agregar la funcionalidad para pasar secuencias de números no aleatorios sin reescribir el código completo.

EDITAR: Veo cierta confusión en los comentarios. Soy consciente de que los generadores de números aleatorios de Python generan números pseudoaleatorios. Esta publicación trata sobre la sustitución de un generador de números pseudoaleatorios por un generador de números que genera números a partir de una secuencia no aleatoria especificada por el usuario (por ejemplo, un generador que genera la secuencia 1,1,2,2,1,0,1 si quiero que lo haga).

over 4 years ago · Santiago Trujillo
6 Respuestas
Responde la pregunta

0

Puede llamar a next() con un generador o iterador como argumento para retirar exactamente un elemento de él. Guardar el generador en una variable de antemano le permite hacer esto varias veces.

 # make it a generator def _rng(): while True: yield np.random.randint(2,20)//2 # a non-random number generator def _nrng(): numbers = np.arange(1,10.5,0.5) for i in range(len(numbers)): yield numbers[i] rng = _rng() nrng = _nrng() for j in range(10): print('random number', next(rng)) print('non-random number', next(nrng))
over 4 years ago · Santiago Trujillo Denunciar

0

np.random.randint puede recordar el último número que generó porque es una función de la clase np.random.RandomState . Numpy simplemente crea un alias para el método de clase para que sea accesible directamente desde el módulo np.random en lugar de tener que acceder a él a través de la clase.

Sabiendo esto, puede escribir su propia clase para que funcione así:

 class NotRandom: numbers = np.arange(1,10.5,0.5) last_index = -1 @classmethod def nrng(cls): cls.last_index += 1 if cls.last_index < len(cls.numbers): return cls.numbers[cls.last_index] # else: return None # Create an alias to the classmethod nrng = NotRandom.nrng # Note this is OUTSIDE the class

Entonces, puedes hacer:

 print(nrng()) # 1.0 print(nrng()) # 1.5 print(nrng()) # 2.0

Si desea poder tener varias instancias simultáneas de nrng , puede hacer que nrng() un método de instancia en lugar de un método de clase:

 class NotRandom: def __init__(self): self.numbers = np.arange(1,10.5,0.5) self.last_index = -1 def nrng(self): self.last_index += 1 if self.last_index < len(self.numbers): return self.numbers[self.last_index] # else: return None # Create an object. Then create an alias to its method nrng = NotRandom().nrng

Luego, puede usar nrng() para hacer referencia al método que está vinculado a la instancia de NotRandom que creó. Si desea otra instancia, también puede tenerla:

 another_notrandom = NotRandom() nrng2 = another_notrandom.rng print(nrng()) # 1.0 print(nrng()) # 1.5 print(nrng2()) # 1.0 print(nrng()) # 2.0 print(nrng2()) # 1.5
over 4 years ago · Santiago Trujillo Denunciar

0

Editar:

La forma más limpia de hacer esto sería usar una lambda para ajustar su llamada a next(nrng) según el gran comentario de @GACy20:

 def nrng_gen(): yield from range(10) nrng = nrng_gen() nrng_func = lambda: next(nrng) for i in range(10): print(nrng_func())

Respuesta original:

Si desea que su objeto mantenga el estado y se vea como una función, cree una clase personalizada con el método __call__ .

p.ej.

 class NRNG: def __init__(self): self.numbers = range(10) self.state = -1 def __call__(self): self.state += 1 return self.numbers[self.state] nrng = NRNG() for i in range(10): print(nrng())

Sin embargo, no recomendaría esto a menos que sea absolutamente necesario, ya que oscurece el hecho de que su nrng mantiene un estado (aunque técnicamente, la mayoría de los rng mantienen su estado internamente).

Lo mejor es usar un generador regular con yield llamando a continuación o escribir un iterador personalizado (también basado en clases). Esos funcionarán con cosas como bucles for y otras herramientas de Python para la iteración (como el excelente paquete itertools).

over 4 years ago · Santiago Trujillo Denunciar

0

función que acepta un generador de números aleatorios como argumento

Llámalo así entonces:

 that_function(nrng().__next__)

O con functools.partial :

 that_function(partial(next, nrng()))

O sin tu generador, si ese arange es todo lo que quieres:

 that_function(iter(np.arange(1,10.5,0.5)).__next__)

Código de demostración ( rng y nrng son suyos, agregué that_function y las llamadas de prueba):

 import numpy as np from functools import partial # a random number generator rng = lambda : np.random.randint(2,20)//2 # a non-random number generator def nrng(): numbers = np.arange(1,10.5,0.5) for i in range(len(numbers)): yield numbers[i] def that_function(rng): print(*(rng() for j in range(10))) that_function(rng) that_function(nrng().__next__) that_function(iter(np.arange(1,10.5,0.5)).__next__) that_function(partial(next, nrng()))

Salida ( ¡Pruébelo en línea! ):

 4 6 1 3 8 7 3 6 2 1 1.0 1.5 2.0 2.5 3.0 3.5 4.0 4.5 5.0 5.5 1.0 1.5 2.0 2.5 3.0 3.5 4.0 4.5 5.0 5.5 1.0 1.5 2.0 2.5 3.0 3.5 4.0 4.5 5.0 5.5
over 4 years ago · Santiago Trujillo Denunciar

0

La solución más simple para hacer que un generador sea invocable es crear un método enlazado para __next__ :

 >>> def f(): yield 10 yield 20 yield 30 >>> g = f().__next__ >>> g() 10 >>> g() 20 >>> g() 30
over 4 years ago · Santiago Trujillo Denunciar

0

Estoy de acuerdo, next() parece el camino a seguir. Honestamente, simplemente habría hecho algo como esto:

 # Get the first n numbers (10 in this case) for i,j in enumerate(nrng()): if i > 9: break print('random number', rng()) print('non-random number', j) # Or this if you want to get all numbers in nrng() for j in nrng(): print('random number', rng()) print('non-random number', j)
over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda