Именование элементов списка с помощью оператора `with` - PullRequest
0 голосов
/ 20 февраля 2019

Я хочу сослаться на элемент (mem[0]) списка (mem) с другим именем (fetch):

mem = [0]
f = open("File.lx", "rb").read()
for b in f: mem += [b]
size = len(mem)

while mem[0] < size:        #using mem[0]
    char = (mem[0]*2)+1
    source = mem[char]
    target = mem[char + 1]

    mem[0] += 1
    mem[target] = mem[source]

И я попробовал это с with оператор:

mem = [0]
f = open("File.lx", "rb").read()
for b in f: mem += [b]
size = len(mem)

with mem[0] as fetch:        #with statement
   while fetch < size:       #using mem[0] as fetch
    char = (fetch*2)+1
    source = mem[char]
    target = mem[char + 1]

    fetch += 1
    mem[target] = mem[source]

Но я получил ошибку:

Traceback (most recent call last):
  File "C:\documents\test.py", line 6, in <module>
    with mem[0] as fetch:
AttributeError: __enter__

Я подумал, что так будет, потому что так делается с файловыми объектами:

with open("File.lx", "rb") as file:
    fileBytes = file.read()

Я прочитал docs для оператора with и там написано, что загружены методы __exit()__ и __enter()__.Согласно тому, что я понял после прочтения этого и из AttributeError, я предполагаю, что элементы последовательности (mem[0]) не имеют метода __enter()__.

Ответы [ 2 ]

0 голосов
/ 20 февраля 2019

Похоже, вам нужен изменчивый объект, который функционирует как псевдоним для определенного местоположения в списке.Я мог видеть некоторую утилиту в этом (поскольку явные индексы несколько уродливы в Python).Вы могли бы создать такой класс.Вот подтверждение концепции, реализующей три вещи, которые вы пытались сделать с fetch в своем коде:

class Fetcher:
    def __init__(self,target_list, index):
        self._list = target_list
        self._i = index

    def __iadd__(self,v):
        self._list[self._i] += v
        return self

    def __mul__(self,v):
        return self._list[self._i] * v

    def __lt__(self,v):
        return self._list[self._i] < v

Например,

mem = [0,1,2]
fetch = Fetcher(mem,0)

print(fetch < 2) #true
mem[0] = 1
print(fetch < 2) #still true
fetch += 1
print(fetch < 2) #false!
print(mem[0]) #2, showing that mem[0] was changed
print(fetch*2) #4 -- but 2*fetch won't work!

Последняя строка показывает, чтоЕсть предел тому, что вы могли бы достичь здесь.Чтобы сделать это действительно полезным, вам нужно реализовать еще много магических методов (помимо __iadd__ и т. Д.).Является ли все это полезным, чтобы избежать [0], вы будете судьей.

0 голосов
/ 20 февраля 2019

, как уже упоминалось в комментариях, mem[0] - это буквальное целое число, в котором нет __enter__ и __exit__, которые необходимы для работы ключевого слова as, и было бы действительно проще, если бы вы просто использовалиmem[0]

но это было бы слишком просто, что вы МОЖЕТЕ сделать (поскольку на самом деле это упражнение не делает), это расширить класс int и добавить __enter__ и __exit__ следующим образом:

class FancyInt(int):
    def __enter__(self):
        return self
    def __exit__(self, *args):
        pass

mem = [FancyInt(0)]
with mem[0] as fetch:
    print(fetch)

это аккуратно, но fetch является псевдонимом LITERAL! если вы измените fetch, mem[0] не изменится!

...