Python no idempotente [cerrado]

10

Escriba algunas líneas de código Python Xque no hagan referencia a ninguna variable global, de modo que

def method():
    X
    print(a)

method()

imprime 1pero

def method():
    X
    X
    print(a)

method()

impresiones 2.


Por lo tanto, me gusta ser muy estricto, pero parece varsy localsen realidad son variables globales en Python:

def test_global_1():
    global vars, locals
    vars = lambda: 2
    locals = lambda: 3

def test_global_2():
    print(vars())
    print(locals())

test_global_1()
test_global_2()

Además, parece que a la gente le gustaría ver criterios objetivos de ganar para acertijos como este. La longitud del código realmente no se siente bien aquí, entonces ¿tal vez podríamos hacer un sistema de puntos brownie para varias características nuevas del código? No estoy seguro de cuáles podrían ser exactamente, pero aquí hay un comienzo:

  • +1 para realmente no hay globals (no varso locals)
  • +1 por ser el primero en publicar una técnica en particular
  • +1 para la solución más corta publicada
  • +1 para una solución que involucra solo una declaración de Python
  • +1 para "hacks" interesantes como unirse a no-límites léxicos
  • +1 por no usar excepciones

Y si puede pensar en más, puede editar esta pregunta para agregarla a la lista.

¿Se puede resolver este problema sin usar excepciones y sin usar globales como varsy locals? Sospecho que puede, aunque aún no he descubierto exactamente cómo ...

Owen
fuente
Buen rompecabezas! Me aseguré de no desplazarme hacia abajo para poder resolverlo yo mismo sin ver las respuestas de nadie. : D
mbomb007
1
Gracias por los rompecabezas Owen, y bienvenidos al sitio. Hay una regla en el sitio que todas las preguntas deben tener una condición ganadora objetiva, por lo que probablemente debería agregar una. Una posibilidad es la más corta X, pero hay otras opciones.
isaacg
3
"todas las preguntas deben tener una condición ganadora objetiva" - Regla estúpida en mi humilde opinión. ¿A quién le importa un "ganador" cuando en realidad todos disfrutamos más de los enigmas y el aprendizaje de las diferentes respuestas?
JimmyB
2
Agregue una etiqueta de código de golf o de concurso de popularidad , dependiendo de si desea que las personas optimicen el código de falta o la popularidad general. Me imagino que el código de golf es mejor para este desafío (el concurso de popularidad se recomienda solo para desafíos que de otra manera no se pueden clasificar fácilmente), pero depende de usted.
apsillers
2
Agregó un sistema de puntaje, pero también agregó la etiqueta del concurso de popularidad, lo que significa que el ganador se decide por votos. ¿A qué te refieres aquí? ¿Quizás quieres votos solo como un desempate?
xnor

Respuestas:

12
def method():
    if 'a' not in vars():a=0
    a+=1
    if 'a' not in vars():a=0
    a+=1
    print(a)

Inicializa la variable aque 0sólo si no está ya inicializado en la tabla de variables. Luego, lo incrementa.

Más brevemente (gracias a histocrat por len):

def method():
    a=len(vars())+1
    a=len(vars())+1
    print(a)

Si las dos copias de Xpudieran estar en la misma línea, podríamos hacer

a=0;a+=1;a

que se duplica a

a=0;a+=1;aa=0;a+=1;a

con el "cordero sacrificial" aacomiendo la segunda asignación variable.

xnor
fuente
3
No quiero ser un spoilsport publicando esto tan rápido, así que ¿qué tal si intentamos el código más corto?
xnor
3
Variante ligeramente más corta:a=len(vars())+1
histocrat
@histocrat Nice one, gracias!
xnor
9

Pitón

El pensamiento de esta solución, puesto tryy exceptfue la primera forma en que pensaba de determinar si todavía existía o no una variable.

def method():
    try:a+=1
    except:a=1
    print(a)
mbomb007
fuente
5

Python 2

def method():
    exec'';locals()['a']=locals().get('a',0)+1
    exec'';locals()['a']=locals().get('a',0)+1
    print a

method()

Básicamente, cuando execse encuentra en Python 2, hace 0x01que se elimine un indicador especial ( ) method.func_code.co_flags, lo que hace que las localsasignaciones tengan un efecto. Exploté esto para implementar el nonlocalsoporte en Python 2 (ver la línea 43 para el xor que modifica la bandera).

kirbyfan64sos
fuente
¿Por qué no a = locals().get('a', 0) + 1?
Vincent
@ Vincent, estaba cansado. : O Fijo.
kirbyfan64sos
En ese caso, no necesitas exec''más;)
Vincent
@ Vincent Eh, tal vez debería seguir con la versión más larga. Se sintió más creativo. Ahora parece un clon de la respuesta más votada ...: /
kirbyfan64sos
2

Mi primera idea (y luego suavizarla) fue:

def method():
    a=2if'a'in vars()else 1 
    a=2if'a'in vars()else 1 
    print(a)

Pero la respuesta del histocrat parece óptima.

Don Hatch
fuente
1

Mi intento. Utiliza el módulo matemático para rastrear si X se ejecuta una o dos veces.

def module():
  import sys
  if 'math' in sys.modules:
    a+=1
  else:
    a=1
  import math

  import sys
  if 'math' in sys.modules:
    a+=1
  else:
    a=1
  import math

  print(a)

module()
toto
fuente
1
def method(a=[]):  
  a.append(a)  
  print len(a)

Editado en respuesta al comentario: a es una lista de listas vacías de longitud n, donde n es el número de veces que ha llamado al método. Llamar a este método dos veces imprime 1 y luego 2.

Con la ciencia
fuente
77
Poner a=[]como parámetro está fuera de los parámetros para este desafío.
mbomb007
Lo siento, esta es mi respuesta, y no es muy buena. Esta es (posiblemente) una operación sorprendentemente no idempotente en Python, pero no hay forma de ubicarla en el formato proporcionado para el desafío sin hacer que el desafío sea trivial.
WithScience
Además, el desafío requiere imprimir 1 o 2, no solo dos cosas diferentes.
xnor
0
def method():
    #### X-block
    try:a
    except NameError:a=1
    else:a=2
    ####
    print(a)

El trybloque verifica si la variable a está definida.
Si la variable no está definida (esto es solo cuando el bloque X está presente una vez), entonces se NameErrorgenera la Excepción.
Si se define la variable (esto es cuando el bloque X está presente dos veces) else, se ingresará.

Kamehameha
fuente
Sí, esa es la solución que encontré al buscar en Google. Luego creé mi solución actual, que es más corta.
mbomb007
@ mbomb007 Sí: P. Su camino es más corto que el usoelse
Kamehameha