Python não idempotente [fechado]


10

Escreva algumas linhas de código Python,, Xque não fazem referência a nenhuma variável global, como

def method():
    X
    print(a)

method()

imprime 1mas

def method():
    X
    X
    print(a)

method()

impressões 2.


Então, eu odeio ser um defensor, mas parece varse localssão realmente variáveis ​​globais em 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()

Além disso, parece que as pessoas gostariam de ver critérios objetivos de vitória para quebra-cabeças como esse. O tamanho do código não parece muito bom aqui, então talvez possamos criar um sistema de pontos brownie para vários recursos novos do código? Não sei exatamente o que poderia ser, mas aqui está um começo:

  • +1 para realmente não globais (nenhum varsou locals)
  • +1 por ser o primeiro a publicar uma técnica específica
  • +1 para a solução mais curta publicada
  • +1 para uma solução que envolve apenas uma única instrução Python
  • +1 para "hacks" interessantes, como ingressar em limites lexicais
  • +1 por não usar exceções

E se você puder pensar em mais, poderá editar esta pergunta para adicionar à lista.

Esse problema pode ser resolvido sem o uso de exceções e sem o uso de globais como varse locals? Suspeito que sim, embora ainda não tenha descoberto exatamente até agora ...


Bom quebra-cabeça! Tomei o cuidado de não rolar para baixo para poder resolver sozinho sem ver as respostas de ninguém. : D
mbomb007 30/07/2015

11
Obrigado pelos quebra-cabeças Owen, e bem-vindo ao site. Existe uma regra no site de que todas as perguntas devem ter uma condição objetiva de vitória, portanto, você provavelmente deve adicionar uma. Uma possibilidade é a menor X, mas existem outras opções.
Isaacg

3
"todas as perguntas devem ter uma condição de vitória objetiva" - regra estúpida imho. Quem se importa com um "vencedor", quando todos nós realmente gostamos do intrigante e aprendemos com as diferentes respostas.
JimmyB

2
Adicione uma tag code-golf ou popular-contest , dependendo se você deseja que as pessoas otimizem quanto ao código de falta ou à popularidade geral. Imagino que o código-golfe seja melhor para esse desafio (o concurso de popularidade é incentivado apenas para desafios que não podem ser facilmente classificados de outra forma), mas depende de você.
Apsillers

2
Você adicionou um sistema de pontuação, mas também adicionou a tag do concurso de popularidade, o que significa que um vencedor é decidido por votos. o que quer dizer aqui? Talvez você queira votos apenas como um tiebreak?
Xnor

Respostas:


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

Inicializa a variável ade 0somente se ele já não estiver inicializado na tabela de variáveis. Então, incrementa.

Mais brevemente (obrigado ao histocrat por len):

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

Se as duas cópias Xestivessem na mesma linha, poderíamos fazer

a=0;a+=1;a

que dobra para

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

com o "cordeiro sacrificial" aaconsumindo a segunda designação de variável.


3
Eu não quero ser um spoiler publicando isso tão rápido, então que tal tentarmos o código mais curto?
xnor

3
Variante ligeiramente mais curta:a=len(vars())+1
histocrat 30/07/2015

@histocrat Nice, obrigado!
xnor

9

Pitão

Pensei nessa solução, desde trye exceptfoi a primeira maneira que pensei em determinar se uma variável existia ainda ou não.

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

5

Python 2

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

method()

Basicamente, quando execé encontrado no Python 2, faz com que um sinalizador especial ( 0x01) seja removido method.func_code.co_flags, o que faz com que as localsatribuições tenham efeito. Eu explorei isso para implementar o nonlocalsuporte no Python 2 (consulte a linha 43 para o xor que modifica a flag).


Por que não a = locals().get('a', 0) + 1?
31415 Vincent

@ Vincent Eu estava cansada. : O fixo.
Kirbyfan64sos

Nesse caso, você não precisa exec''mais;)
Vincent

@ Vincent Eh, talvez eu devesse ficar com a versão mais longa. Parecia mais criativo. Agora parece um clone da resposta mais votada ...: /
kirbyfan64sos

2

Minha primeira ideia (e depois misturá-la) foi:

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

Mas a resposta do histocrata parece ótima.


1

Minha tentativa. Usa o módulo matemático para rastrear se o X é executado uma ou duas vezes.

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()

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

Editado em resposta ao comentário: a é uma lista de listas vazias de comprimento n, em que n é o número de vezes que você chamou o método. A chamada desse método duas vezes imprime 1 e 2.


7
Colocar a=[]como parâmetro está fora dos parâmetros desse desafio.
mbomb007

Desculpe, esta é a minha resposta e não é muito boa. Esta é (sem dúvida) uma operação surpreendentemente não-idempotente em python, mas não há como encaixá-la no formato fornecido para o desafio sem também torná-lo trivial.
WithScience

Além disso, o desafio pede para imprimir 1 ou 2, não apenas duas coisas diferentes.
Xnor

0
def method():
    #### X-block
    try:a
    except NameError:a=1
    else:a=2
    ####
    print(a)

O trybloco verifica se a variável a está definida.
Se a variável não estiver definida (somente quando o bloco X estiver presente uma vez), a NameErrorexceção será gerada.
Se a variável for definida (é quando o bloco X estiver presente duas vezes), elseserá inserida.


Sim, essa é a solução que encontrei pesquisando no Google. Então eu criei minha solução atual, que é mais curta.
mbomb007

@ mbomb007 Sim: P. Seu caminho é mais curto do que usarelse
Kamehameha
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.