Python niebędący idempotentem [zamknięty]

10

Napisz kilka wierszy kodu w języku Python X, który nie odwołuje się do żadnych zmiennych globalnych, takich jak

def method():
    X
    print(a)

method()

odciski, 1ale

def method():
    X
    X
    print(a)

method()

odciski 2.


Tak, nienawidzę być pedantem, ale wydaje się, varsi localssą rzeczywiście zmienne globalne w Pythonie:

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

Wygląda też na to, że ludzie chcieliby zobaczyć obiektywne kryteria wygrywające dla takich zagadek. Długość kodu tak naprawdę nie wydaje się tutaj, więc być może moglibyśmy stworzyć system punktów brownie dla różnych nowatorskich funkcji kodu? Nie jestem pewien, co to może być, ale oto początek:

  • +1 za naprawdę brak globali (nie varslub locals)
  • +1 za to, że jako pierwszy opublikował określoną technikę
  • +1 za najkrótsze opublikowane rozwiązanie
  • +1 za rozwiązanie obejmujące tylko jedną instrukcję Python
  • +1 za ciekawe „hacki”, takie jak łączenie na leksykalnych granicach
  • +1 za niestosowanie wyjątków

A jeśli możesz wymyślić więcej, możesz edytować to pytanie, aby dodać je do listy.

Czy ten problem można rozwiązać bez użycia wyjątków i bez użycia globałów takich jak varsi locals? Podejrzewam, że tak, choć jeszcze nie wiem, jak ...

piekarnik
źródło
Dobra łamigłówka! Upewniłem się, że nie przewijam w dół, aby samemu rozwiązać problem, nie widząc niczyich odpowiedzi. : D
mbomb007
1
Dziękujemy za puzzle Owen i witamy na stronie. Na stronie istnieje reguła, że ​​wszystkie pytania muszą mieć obiektywny warunek wygranej, więc prawdopodobnie powinieneś je dodać. Jedną z możliwości jest najkrótsza długość X, ale są też inne opcje.
isaacg
3
„wszystkie pytania muszą mieć obiektywny warunek wygranej” - głupia zasada imho. Kogo obchodzi „zwycięzca”, kiedy wszyscy najbardziej lubimy łamigłówki i uczenie się na podstawie różnych odpowiedzi.
JimmyB,
2
Dodaj tag golfa lub konkurs popularności , w zależności od tego, czy chcesz zoptymalizować kod skrótu, czy ogólną popularność. Wyobrażam sobie, że golf-golf jest lepszy do tego wyzwania (konkurs popularności jest zachęcany tylko do wyzwań, których inaczej nie można łatwo sklasyfikować), ale to zależy od ciebie.
apsillers
2
Dodałeś system punktacji, ale także tag popularności, co oznacza, że ​​o zwycięzcy decydują głosy. Co masz na myśli? Być może chcesz głosów jako remis?
xnor

Odpowiedzi:

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

Inicjalizuje zmienną ado 0tylko jeśli nie jest już zainicjowany w tabeli zmiennych. Następnie zwiększa.

W skrócie (dzięki histocrat za len):

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

Gdyby dwie kopie Xmogły znajdować się w tej samej linii, moglibyśmy to zrobić

a=0;a+=1;a

która podwaja się do

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

„ofiarny baranek” aapochłania drugie zmienne zadanie.

xnor
źródło
3
Nie chcę być psurzem, publikując to tak szybko, więc co powiesz na najkrótszy kod?
xnor
3
Nieco krótszy wariant:a=len(vars())+1
histokrata
@histocrat Fajny, dzięki!
xnor
9

Pyton

Myśl tego rozwiązania, ponieważ tryi exceptbył to pierwszy sposób myślałem o celu ustalenia, czy zmienna lub jeszcze nie istniał.

def method():
    try:a+=1
    except:a=1
    print(a)
mbomb007
źródło
5

Python 2

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

method()

Zasadniczo po execnapotkaniu w Pythonie 2 powoduje 0x01usunięcie specjalnej flagi ( ) method.func_code.co_flags, co powoduje, że localsprzypisania mają wpływ. Wykorzystałem to, aby zaimplementować nonlocalwsparcie w Pythonie 2 (patrz wiersz 43 dla xor modyfikującego flagę).

kirbyfan64sos
źródło
Dlaczego nie a = locals().get('a', 0) + 1?
Vincent
@Vincent byłem tiree. : O Naprawiono.
kirbyfan64sos
W takim razie nie potrzebujesz exec''już więcej;)
Vincent
@Vincent Eh, może powinienem trzymać się dłuższej wersji. To było bardziej kreatywne. Teraz wygląda to jak klon najlepiej głosowanej odpowiedzi ...: /
kirbyfan64sos
2

Moim pierwszym pomysłem (a potem wygładzeniem go) było:

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

Ale odpowiedź histokraty wydaje się optymalna.

Don Hatch
źródło
1

Moja próba Używa modułu matematycznego do śledzenia, czy X jest uruchamiany raz czy dwa.

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
źródło
1
def method(a=[]):  
  a.append(a)  
  print len(a)

Edytowane w odpowiedzi na komentarz: a jest listą pustych list o długości n, gdzie n jest liczbą wywoływanych metod. Wywołanie tej metody dwukrotnie powoduje wydrukowanie 1, a następnie 2.

WithScience
źródło
7
Wstawienie a=[]jako parametru wykracza poza parametry tego wyzwania.
mbomb007
Przepraszam, to moja odpowiedź i nie jest zbyt dobra. Jest to (prawdopodobnie) zaskakująco mało idempotentna operacja w Pythonie, ale nie ma sposobu na umieszczenie go w formacie przewidzianym dla wyzwania bez uczynienia go trywialnym.
WithScience
Ponadto wyzwanie polega na wydrukowaniu 1 lub 2, a nie tylko dwóch różnych rzeczy.
xnor
0
def method():
    #### X-block
    try:a
    except NameError:a=1
    else:a=2
    ####
    print(a)

Te trykontrole blokowe, jeśli zmienną jest zdefiniowana.
Jeśli zmienna nie jest zdefiniowana (tylko wtedy, gdy X-blok jest obecny raz), wówczas NameErrorzgłaszany jest wyjątek.
Jeśli zmienna jest zdefiniowana (to jest, gdy X-blok jest obecny dwukrotnie), to elsezostanie wprowadzona.

Kamehameha
źródło
Tak, oto rozwiązanie, które znalazłem, wyszukując w Google. Następnie stworzyłem moje obecne rozwiązanie, które jest krótsze.
mbomb007
@ mbomb007 Tak: P. Twoja droga jest krótsza niż używanieelse
Kamehameha