Что может пойти не так, если у операторов есть побочные эффекты? - PullRequest
0 голосов
/ 02 июня 2018

Я натолкнулся на библиотеку Python, которая определяет класс, аналогичный следующему, где оператор >> перегружен, чтобы иметь глобальный побочный эффект:

from collections import defaultdict

class V(object):
    """A Vertex in a graph."""

    graph = defaultdict(list)  # accessed globally

    def __init__(self, label):
        self.label = label

    def __rshift__(self, other):
        V.graph[self].append(other)
        return other

    def __repr__(self):
        return 'V(%r)' % (self.label,)

Библиотека делает это, потому что «этодает пользователю приятный синтаксис "для символического построения сетей, записывая простые выражения, такие как:

a = V('a')
b = V('b')
c = V('c')
a >> b >> c >> c

, чтобы построить сеть, в которой a подключен к b, который подключенна c, который периодически связан с самим собой.

Аналогичные механизмы существуют и в операторах +, * и @.Все это поведение задокументировано и ожидается пользователем.

Однако, могут ли произойти какие-то странные вещи, когда вы не думаете, что выражение должно быть оценено - но на самом деле это так - или наоборот?Versa?То есть модель исполнения для Python когда-либо предполагает, что определенные выражения свободны от каких-либо побочных эффектов?Я хочу знать, существует ли какой-либо прецедент или какие-либо особые меры предосторожности должны быть приняты пользователем.

Ответы [ 2 ]

0 голосов
/ 04 июня 2018

Мне неизвестна какая-либо другая библиотека Python, которая делает это.

Один из примеров чего-то странного или неожиданного для меня следующий:

a = V('a')
b = V('b')

def do_something(c=a>>b):
    return c>>c

do_something(a)

Это может быть рассмотренодать странный результат (a >> a и a >> b), поскольку аргумент по умолчанию оценивается, независимо от того, используется ли он в конечном итоге.


В качестве другого примера, при использовании try / except, любая частично завершенная оценка приведет к неполному набору побочных эффектов, которые не могут быть перемотаны.

try:
    a >> b >> c
except NameError:
    # do something else

Здесь при обработке ошибок может потребоваться тот факт, что a >> b все ещеОценено.


Я не рекомендую пользователям делать что-либо из этого.Я только утверждаю, что если бы пользователь сделал это, он мог бы получить поведение, которое было бы неожиданным, неожиданным или трудным для его отладки.

0 голосов
/ 04 июня 2018

Вы спрашивали конкретно о неожиданной оценке или не оценке.Python не предполагает, что какие-либо пользовательские операторы не имеют побочных эффектов, поэтому он не пропустит a >> b при неверном предположении, что он ничего не делает.У людей иногда возникают проблемы, когда они предполагают, что определенные функции не делают определенных вещей - например, предполагая, что функция, которая принимает итерацию, не будет пытаться len - но большинство таких проблем будет в равной степени справедливо для >> или метода.

У вас могут быть проблемы с альтернативными интерактивными средами, делающими предположения - например, я могу представить, что у меня есть проблемы с завершением табуляции, пытающимися оценить вещи, которые он не должен - но использование модуля в реальной программе Python не должно иметьтакие проблемы.

Ближайшая вещь, которую я ожидал бы к таким проблемам в реальной программе, - это проблемы с приоритетом.Например, использование C ++ << для печати приводит к проблемам, подобным следующему коду:

std::cout << true ? "a" : "b";

, который печатает 1 вместо a, потому что << связывает сильнеечем ?:.Я могу представить себе подобные проблемы, возникающие с этой библиотекой.

...