Неімпотентний Python [закрито]


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, але є й інші варіанти.
isaacg

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лише якщо вона ще не ініціалізована в таблиці змінних. Потім збільшують його.

Більш коротко (завдяки histocrat для 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з'їдає другу змінну задачу.


3
Я не хочу, щоб цей спойлер розміщував це так швидко, тож як ми намагаємось отримати найкоротший код?
xnor

3
Трохи коротший варіант:a=len(vars())+1
гістократ

@histocrat Приємний, дякую!
xnor

9

Пітон

Думка цього рішення, так як tryі exceptбув першим , як я думав , щоб визначити , є чи змінна існувала ще чи ні.

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

5

Пітон 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, що модифікує прапор).


Чому ні a = locals().get('a', 0) + 1?
Вінсент

@Вінсент я був тире. : O Виправлено.
kirbyfan64sos

У такому випадку вам більше не потрібно exec'';)
Вінсент

@Vincent Eh, можливо, я повинен просто дотримуватися більш тривалої версії. Це відчувало себе більш творчим. Тепер це здається
чимось

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.


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він буде введений.


Так, це рішення я знайшов, шукаючи Google. Тоді я створив своє поточне рішення, яке коротше.
mbomb007

@ mbomb007 Так: P. Ваш шлях коротший, ніж використанняelse
Kamehameha
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.