Неидемпотентный питон [закрыто]

10

Напишите несколько строк кода Python X, который не ссылается ни на какие глобальные переменные, например

def method():
    X
    print(a)

method()

печатает 1но

def method():
    X
    X
    print(a)

method()

отпечатки 2.


Таким образом, я не хочу быть приверженцем, но, похоже , varsи localsна самом деле глобальные переменные в 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()

Кроме того, похоже, что люди хотели бы видеть объективные критерии победы для подобных головоломок. Длина кода здесь не совсем подходит, так что, может быть, мы могли бы создать систему коричневых очков для различных новых функций кода? Я не уверен, что именно это может быть, но вот начало:

  • +1 для действительно действительно нет глобальных (нет varsили locals)
  • +1 за то, что первым опубликовал конкретную технику
  • +1 за самое короткое опубликованное решение
  • +1 за решение, включающее только одну инструкцию Python
  • +1 за интересные "хаки", такие как присоединение к лексическим границам
  • +1 за неиспользование исключений

И если вы можете думать больше, вы можете отредактировать этот вопрос, чтобы добавить в список.

Можно ли решить эту проблему, не используя исключения и не используя глобальные переменные типа varsи locals? Я подозреваю, что это возможно, хотя я еще не выяснил, как именно ...

Оуэн
источник
Хорошая головоломка! Я постарался не прокручивать страницу вниз, чтобы решить сам, не видя чьих-либо ответов. : D
mbomb007
1
Спасибо за пазлы Оуэн, и добро пожаловать на сайт. На сайте существует правило, согласно которому все вопросы должны иметь объективное условие победы, поэтому вам, вероятно, следует добавить его. Одна возможность - самая короткая длина X, но есть и другие варианты.
Исаак
3
«Все вопросы должны иметь объективное условие победы», - глупое правило imho. Кого волнует «победитель», когда нам всем больше всего нравится загадывать и учиться на разных ответах.
JimmyB
2
Добавьте тег « код-гольф» или « конкурс популярности» , в зависимости от того, хотите ли вы, чтобы люди оптимизировали его по короткому коду или по общей популярности. Я полагаю, что код-гольф лучше подходит для этой задачи (конкурс на популярность поощряется только для задач, которые иначе нельзя легко классифицировать), но решать вам.
Апсиллеры
2
Вы добавили систему подсчета очков, но также добавили тег конкурса популярности, который означает, что победитель определяется голосованием. Что вы имеете в виду здесь? Может быть, вы хотите, чтобы голоса просто как тай-брейк?
xnor

Ответы:

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

Инициализировать переменную aдля 0только если он не инициализирован в таблице переменных. Затем увеличивает его.

Короче (спасибо гистократу за len):

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

Если две копии Xмогут быть на одной строке, мы могли бы сделать

a=0;a+=1;a

который удваивается

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

с «жертвенным ягненком», aaпоедающим второе переменное назначение.

XNOR
источник
3
Я не хочу быть спойлером, публикующим это так быстро, так как насчёт кратчайшего кода?
xnor
3
Чуть короче вариант:a=len(vars())+1
гистократ
@histocrat Хороший, спасибо!
xnor
9

питон

Мысль об этом решении, так как я tryи exceptбыл первым способом определить, существует ли переменная или нет.

def method():
    try:a+=1
    except:a=1
    print(a)
mbomb007
источник
5

Python 2

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

method()

В основном, когда execвстречается в Python 2, это вызывает специальный флаг (0x01 удаление ) method.func_code.co_flags, что дает localsэффект назначениям. Я использовал это для реализации nonlocalподдержки в Python 2 (см. Строку 43 для xor, который изменяет флаг).

kirbyfan64sos
источник
Почему нет a = locals().get('a', 0) + 1?
Винсент
@ Винсент, я был Тире. : O Исправлено.
kirbyfan64sos
В таком случае вам больше не нужно exec'';)
Винсент
@ Винсент Эх, может, мне стоит придерживаться более длинной версии? Это было более креативно. Теперь это выглядит как клон ответа с
наибольшим количеством
2

Моей первой идеей (а потом обмахиваясь этим) было:

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

Но ответ гистократа кажется оптимальным.

Дон хэтч
источник
1

Моя попытка. Использует математический модуль для отслеживания, запускается ли X один или два раза.

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)

Отредактировано в ответ на комментарий: a - это список пустых списков длиной n, где n - количество раз, которое вы вызвали методом. Вызов этого метода дважды выводит 1, затем 2.

WithScience
источник
7
Размещение a=[]в качестве параметра находится за пределами параметров для этой задачи.
mbomb007
Извините, это мой ответ, и он не очень хороший. Это (возможно) удивительно неидемпотентная операция в python, но нет способа вставить ее в формат, предусмотренный для вызова, не делая задачу тривиальной.
WithScience
Кроме того, задача просит напечатать 1 или 2, а не просто две разные вещи.
xnor
0
def method():
    #### X-block
    try:a
    except NameError:a=1
    else:a=2
    ####
    print(a)

В tryпроверяет блок , если переменная а определена.
Если переменная не определена, (это происходит только тогда, когда X-блок присутствует один раз), то NameErrorвозникает исключение.
Если переменная определена, (это когда X-блок присутствует дважды), то elseбудет введен.

Kamehameha
источник
Да, это решение, которое я нашел, выполнив поиск в Google. Затем я создал свое текущее решение, которое короче.
mbomb007
@ mbomb007 Да: P. Ваш путь короче, чем использованиеelse
Kamehameha